Skip to content

Commit 6b43e3a

Browse files
authored
Merge pull request #343 from teharrison/master
locking and saving
2 parents 053e7c5 + 87889d3 commit 6b43e3a

File tree

10 files changed

+324
-275
lines changed

10 files changed

+324
-275
lines changed

shock-server/controller/node/index/index.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,9 @@ func IndexTypedRequest(ctx context.Context) {
300300
return
301301
}
302302

303-
if err := n.SetIndexInfo(idxType, idxInfo); err != nil {
304-
logger.Error("err@node.SetIndexInfo: " + err.Error())
303+
n.SetIndexInfo(idxType, idxInfo)
304+
if err := n.Save(); err != nil {
305+
logger.Error("err@node.Save: " + err.Error())
305306
}
306307

307308
if conf.LOG_PERF {

shock-server/controller/node/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func (cr *NodeController) Replace(id string, ctx context.Context) error {
8282
}
8383
}
8484

85-
err = n.Update(params, files)
85+
err = n.Update(params, files, false)
8686
if err != nil {
8787
err_msg := "err@node_Update: " + id + ": " + err.Error()
8888
logger.Error(err_msg)

shock-server/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ func mapRoutes() {
119119
return nil
120120
})
121121

122-
goweb.Map("/openparts", func(ctx context.Context) error {
123-
ids := node.LockMgr.GetNodes()
122+
goweb.Map("/locked", func(ctx context.Context) error {
123+
ids := node.LockMgr.GetLocked()
124124
return responder.RespondWithData(ctx, ids)
125125
})
126126

shock-server/node/expire.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ func (nr *NodeReaper) Handle() {
4040
logger.Error(err_msg)
4141
}
4242
}
43+
// remove old nodes from Locker, value is hours old
44+
LockMgr.RemoveOldNodes(1)
4345
}
4446
}
4547

shock-server/node/fs.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func (node *Node) SetFile(file FormFile) (err error) {
1919
if err != nil {
2020
return
2121
}
22+
2223
os.Rename(file.Path, node.FilePath())
2324
node.File.Name = file.Name
2425
node.File.Size = fileStat.Size()
@@ -38,7 +39,7 @@ func (node *Node) SetFile(file FormFile) (err error) {
3839
Format: "dynamic",
3940
CreatedOn: time.Now(),
4041
}
41-
err = node.Save()
42+
4243
return
4344
}
4445

@@ -115,7 +116,6 @@ func (node *Node) SetFileFromSubset(subsetIndices FormFile) (err error) {
115116
CreatedOn: time.Now(),
116117
}
117118

118-
err = node.Save()
119119
return
120120
}
121121

@@ -210,7 +210,7 @@ func (node *Node) SetFileFromPath(path string, action string) (err error) {
210210
} else {
211211
node.File.Path = path
212212
}
213-
err = node.Save()
213+
214214
return
215215
}
216216

shock-server/node/locker.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package node
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
"time"
7+
)
8+
9+
var (
10+
LockMgr = NewLocker()
11+
)
12+
13+
func NewLocker() *Locker {
14+
return &Locker{
15+
nodes: map[string]*NodeLock{},
16+
}
17+
}
18+
19+
type Locker struct {
20+
nodes map[string]*NodeLock
21+
sync.Mutex
22+
}
23+
24+
type NodeLock struct {
25+
isLocked bool
26+
updated time.Time
27+
writeLock chan int
28+
}
29+
30+
func (n *NodeLock) init() {
31+
n.isLocked = false
32+
n.updated = time.Now()
33+
n.writeLock = make(chan int, 1)
34+
n.writeLock <- 1 // Put the initial value into the channel
35+
}
36+
37+
func (n *NodeLock) lock(id string) (err error) {
38+
select {
39+
case <-n.writeLock: // Grab the ticket - here is where we wait
40+
case <-time.After(time.Minute * 30):
41+
err = fmt.Errorf("Timeout!! Waited 30 mins on lock for node %s", id)
42+
return
43+
}
44+
n.isLocked = true
45+
n.updated = time.Now()
46+
return
47+
}
48+
49+
func (n *NodeLock) unlock() {
50+
n.isLocked = false
51+
n.updated = time.Now()
52+
n.writeLock <- 1 // Release the ticket
53+
}
54+
55+
func (l *Locker) LockNode(id string) (err error) {
56+
// add if missing, may happen if shock restarted
57+
if _, ok := l.nodes[id]; !ok {
58+
l.AddNode(id)
59+
}
60+
err = l.nodes[id].lock(id)
61+
return
62+
}
63+
64+
func (l *Locker) UnlockNode(id string) {
65+
// skip missing id
66+
if _, ok := l.nodes[id]; ok {
67+
l.nodes[id].unlock()
68+
}
69+
}
70+
71+
func (l *Locker) GetLocked() (ids []string) {
72+
l.Lock()
73+
for id, n := range l.nodes {
74+
if n.isLocked {
75+
ids = append(ids, id)
76+
}
77+
}
78+
l.Unlock()
79+
return
80+
}
81+
82+
func (l *Locker) AddNode(id string) {
83+
l.Lock()
84+
l.nodes[id] = new(NodeLock)
85+
l.nodes[id].init()
86+
l.Unlock()
87+
}
88+
89+
func (l *Locker) RemoveNode(id string) {
90+
l.Lock()
91+
delete(l.nodes, id)
92+
l.Unlock()
93+
}
94+
95+
func (l *Locker) RemoveOldNodes(hours int) {
96+
currTime := time.Now()
97+
expireTime := currTime.Add(time.Duration(hours*-1) * time.Hour)
98+
l.Lock()
99+
for id, n := range l.nodes {
100+
if (!n.isLocked) && n.updated.Before(expireTime) {
101+
delete(l.nodes, id)
102+
}
103+
}
104+
l.Unlock()
105+
}

shock-server/node/node.go

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"io/ioutil"
1616
"os"
1717
"strconv"
18+
"strings"
1819
"time"
1920
)
2021

@@ -130,13 +131,13 @@ func CreateNodeUpload(u *user.User, params map[string]string, files FormFiles) (
130131
return
131132
}
132133

133-
err = node.Update(params, files)
134+
// update saves node
135+
err = node.Update(params, files, true)
134136
if err != nil {
137+
err = fmt.Errorf("(node.Update) %s", err.Error())
135138
node.Rmdir()
136-
return
137139
}
138140

139-
err = node.Save()
140141
return
141142
}
142143

@@ -219,9 +220,9 @@ func CreateNodesFromArchive(u *user.User, params map[string]string, files FormFi
219220

220221
// save nodes, only return those that were created / saved
221222
for _, n := range tempNodes {
222-
if err = n.Save(); err != nil {
223+
if serr := n.Save(); serr != nil {
223224
n.Rmdir()
224-
return nil, err
225+
continue
225226
}
226227
nodes = append(nodes, n)
227228
}
@@ -264,6 +265,13 @@ func (node *Node) DynamicIndex(name string) (idx index.Index, err error) {
264265
}
265266

266267
func (node *Node) Delete() (err error) {
268+
// lock node
269+
err = LockMgr.LockNode(node.Id)
270+
if err != nil {
271+
return
272+
}
273+
defer LockMgr.RemoveNode(node.Id)
274+
267275
// check to make sure this node isn't referenced by a vnode
268276
virtualNodes := Nodes{}
269277
if _, err = dbFind(bson.M{"file.virtual_parts": node.Id}, &virtualNodes, "", nil); err != nil {
@@ -306,7 +314,8 @@ func (node *Node) Delete() (err error) {
306314
if err = dbDelete(bson.M{"id": node.Id}); err != nil {
307315
return err
308316
}
309-
return node.Rmdir()
317+
err = node.Rmdir()
318+
return
310319
}
311320

312321
func (node *Node) DeleteIndex(indextype string) (err error) {
@@ -319,22 +328,8 @@ func (node *Node) DeleteIndex(indextype string) (err error) {
319328
return
320329
}
321330

322-
func (node *Node) SetIndexInfo(indextype string, idxinfo IdxInfo) (err error) {
331+
func (node *Node) SetIndexInfo(indextype string, idxinfo IdxInfo) {
323332
node.Indexes[indextype] = idxinfo
324-
err = node.Save()
325-
return
326-
}
327-
328-
func (node *Node) SetFileFormat(format string) (err error) {
329-
node.File.Format = format
330-
err = node.Save()
331-
return
332-
}
333-
334-
func (node *Node) SetPriority(priority int) (err error) {
335-
node.Priority = priority
336-
err = node.Save()
337-
return
338333
}
339334

340335
func (node *Node) SetExpiration(expire string) (err error) {
@@ -356,21 +351,6 @@ func (node *Node) SetExpiration(expire string) (err error) {
356351
}
357352

358353
node.Expiration = currTime.Add(expireTime)
359-
err = node.Save()
360-
return
361-
}
362-
363-
func (node *Node) RemoveExpiration() (err error) {
364-
// reset to empty time
365-
node.Expiration = time.Time{}
366-
err = node.Save()
367-
return
368-
}
369-
370-
func (node *Node) ClearRevisions() (err error) {
371-
// empty the revisions array
372-
node.Revisions = []Node{}
373-
err = node.Save()
374354
return
375355
}
376356

@@ -384,7 +364,6 @@ func (node *Node) SetAttributes(attr FormFile) (err error) {
384364
if err != nil {
385365
return
386366
}
387-
err = node.Save()
388367
return
389368
}
390369

@@ -393,6 +372,26 @@ func (node *Node) SetAttributesFromString(attributes string) (err error) {
393372
if err != nil {
394373
return
395374
}
396-
err = node.Save()
397375
return
398376
}
377+
378+
func (node *Node) UpdateDataTags(types string) {
379+
tagslist := strings.Split(types, ",")
380+
for _, newtag := range tagslist {
381+
if contains(node.Tags, newtag) {
382+
continue
383+
}
384+
node.Tags = append(node.Tags, newtag)
385+
}
386+
}
387+
388+
func (node *Node) UpdateLinkages(ltype string, ids string, operation string) {
389+
var link linkage
390+
link.Type = ltype
391+
idList := strings.Split(ids, ",")
392+
for _, id := range idList {
393+
link.Ids = append(link.Ids, id)
394+
}
395+
link.Operation = operation
396+
node.Linkages = append(node.Linkages, link)
397+
}

shock-server/node/parts.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,7 @@ func (node *Node) initParts(partsCount string, compressionFormat string) (err er
4545
Parts: make([]partsFile, count),
4646
Compression: compressionFormat,
4747
}
48-
if err = node.Save(); err != nil {
49-
return err
50-
}
5148

52-
// add node id to LockMgr
53-
LockMgr.AddNode(node.Id)
5449
return
5550
}
5651

@@ -82,7 +77,6 @@ func (node *Node) addVirtualParts(ids []string) (err error) {
8277
} else {
8378
return err
8479
}
85-
err = node.Save()
8680
return
8781
}
8882

@@ -116,7 +110,6 @@ func (node *Node) addPart(n int, file *FormFile) (err error) {
116110
if err = os.Rename(file.Path, fmt.Sprintf("%s/parts/%d", node.Path(), n+1)); err != nil {
117111
return err
118112
}
119-
err = node.Save()
120113
return
121114
}
122115

@@ -126,10 +119,6 @@ func (node *Node) closeParts(allowEmpty bool) (err error) {
126119
if err = node.SetFileFromParts(allowEmpty); err != nil {
127120
return err
128121
}
129-
if err = os.RemoveAll(node.Path() + "/parts/"); err != nil {
130-
return err
131-
}
132-
// remove node id from LockMgr
133-
LockMgr.RemoveNode(node.Id)
122+
err = os.RemoveAll(node.Path() + "/parts/")
134123
return
135124
}

0 commit comments

Comments
 (0)