@@ -10,15 +10,12 @@ import (
1010
1111// callback function is a function that should be executed right after it inserted into hashmap
1212// generally callback is responsible for the removing itself from the hashmap
13- // id - id of the lock
1413// notifyCh - channel to notify that all locks were removed
1514// stopCh - broadcast channel to stop all the callbacks associated with the resource
16- type callback func (id string , notifyCh chan <- struct {}, stopCh <- chan struct {})
15+ type callback func (notifyCh chan <- struct {}, stopCh <- chan struct {})
1716
1817// item represents callback element
1918type item struct {
20- // callback to remove the item
21- callback callback
2219 // item's stop channel
2320 stopCh chan struct {}
2421 // item's update TTL channel
@@ -102,21 +99,19 @@ func (l *locker) lock(ctx context.Context, res, id string, ttl int) bool {
10299
103100 rr .ownerID .Store (new (id ))
104101 rr .writerCount .Store (1 )
105- rr .readerCount .Store (0 )
106102
107103 l .resources [res ] = rr
108104
109105 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
110106
111107 rr .locks .Store (id , & item {
112- callback : callb ,
113108 stopCh : stopCbCh ,
114109 updateTTLCh : updateTTLCh ,
115110 })
116111
117112 // run the callback
118113 go func () {
119- callb (id , rr .notificationCh , rr .stopCh )
114+ callb (rr .notificationCh , rr .stopCh )
120115 }()
121116
122117 l .globalMu .unlock ()
@@ -167,12 +162,14 @@ func (l *locker) lock(ctx context.Context, res, id string, ttl int) bool {
167162 l .log .Debug ("got release mutex back" , "id" , id )
168163
169164 // inconsistent, still have readers/writers after notification
170- if r .writerCount .Load () != 0 && r .readerCount .Load () != 0 {
165+ if r .writerCount .Load () != 0 || r .readerCount .Load () != 0 {
171166 l .log .Error ("inconsistent state, should be zero writers and zero readers" ,
172167 "resource" , res ,
173168 "id" , id ,
174169 "writers" , r .writerCount .Load (),
175170 "readers" , r .readerCount .Load ())
171+
172+ r .resourceMu .unlock ()
176173 return false
177174 }
178175
@@ -183,13 +180,12 @@ func (l *locker) lock(ctx context.Context, res, id string, ttl int) bool {
183180 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
184181
185182 r .locks .Store (id , & item {
186- callback : callb ,
187183 stopCh : stopCbCh ,
188184 updateTTLCh : updateTTLCh ,
189185 })
190186 // run the callback
191187 go func () {
192- callb (id , r .notificationCh , r .stopCh )
188+ callb (r .notificationCh , r .stopCh )
193189 }()
194190
195191 r .resourceMu .unlock ()
@@ -264,7 +260,7 @@ func (l *locker) lock(ctx context.Context, res, id string, ttl int) bool {
264260 }
265261
266262 // inconsistent, still have readers/writers after notification
267- if r .writerCount .Load () != 0 && r .readerCount .Load () != 0 {
263+ if r .writerCount .Load () != 0 || r .readerCount .Load () != 0 {
268264 l .log .Error ("inconsistent state, should be zero writers and zero readers" ,
269265 "resource" , res ,
270266 "id" , id ,
@@ -284,14 +280,13 @@ func (l *locker) lock(ctx context.Context, res, id string, ttl int) bool {
284280 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
285281
286282 r .locks .Store (id , & item {
287- callback : callb ,
288283 stopCh : stopCbCh ,
289284 updateTTLCh : updateTTLCh ,
290285 })
291286
292287 // run the callback
293288 go func () {
294- callb (id , r .notificationCh , r .stopCh )
289+ callb (r .notificationCh , r .stopCh )
295290 }()
296291
297292 r .resourceMu .unlock ()
@@ -322,14 +317,13 @@ func (l *locker) lock(ctx context.Context, res, id string, ttl int) bool {
322317 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
323318
324319 r .locks .Store (id , & item {
325- callback : callb ,
326320 stopCh : stopCbCh ,
327321 updateTTLCh : updateTTLCh ,
328322 })
329323
330324 // run the callback
331325 go func () {
332- callb (id , r .notificationCh , r .stopCh )
326+ callb (r .notificationCh , r .stopCh )
333327 }()
334328
335329 r .resourceMu .unlock ()
@@ -363,14 +357,13 @@ func (l *locker) lock(ctx context.Context, res, id string, ttl int) bool {
363357 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
364358
365359 r .locks .Store (id , & item {
366- callback : callb ,
367360 stopCh : stopCbCh ,
368361 updateTTLCh : updateTTLCh ,
369362 })
370363
371364 // run the callback
372365 go func () {
373- callb (id , r .notificationCh , r .stopCh )
366+ callb (r .notificationCh , r .stopCh )
374367 }()
375368
376369 r .resourceMu .unlock ()
@@ -416,22 +409,20 @@ func (l *locker) lockRead(ctx context.Context, res, id string, ttl int) bool {
416409 }
417410
418411 rr .ownerID .Store (new (""))
419- rr .writerCount .Store (0 )
420412 rr .readerCount .Store (1 )
421413
422414 l .resources [res ] = rr
423415
424416 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
425417
426418 rr .locks .Store (id , & item {
427- callback : callb ,
428419 stopCh : stopCbCh ,
429420 updateTTLCh : updateTTLCh ,
430421 })
431422
432423 // run the callback
433424 go func () {
434- callb (id , rr .notificationCh , rr .stopCh )
425+ callb (rr .notificationCh , rr .stopCh )
435426 }()
436427
437428 l .globalMu .unlock ()
@@ -490,7 +481,7 @@ func (l *locker) lockRead(ctx context.Context, res, id string, ttl int) bool {
490481 }
491482
492483 // inconsistent, still have readers/writers after notification
493- if r .writerCount .Load () != 0 && r .readerCount .Load () != 0 {
484+ if r .writerCount .Load () != 0 || r .readerCount .Load () != 0 {
494485 l .log .Error ("inconsistent state, should be zero writers and zero readers" ,
495486 "resource" , res ,
496487 "id" , id ,
@@ -507,14 +498,13 @@ func (l *locker) lockRead(ctx context.Context, res, id string, ttl int) bool {
507498 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
508499
509500 r .locks .Store (id , & item {
510- callback : callb ,
511501 stopCh : stopCbCh ,
512502 updateTTLCh : updateTTLCh ,
513503 })
514504
515505 // run the callback
516506 go func () {
517- callb (id , r .notificationCh , r .stopCh )
507+ callb (r .notificationCh , r .stopCh )
518508 }()
519509
520510 r .resourceMu .unlock ()
@@ -534,21 +524,19 @@ func (l *locker) lockRead(ctx context.Context, res, id string, ttl int) bool {
534524 "resource" , res ,
535525 "id" , id )
536526 // increase readers
537- r .writerCount .Store (0 )
538527 r .readerCount .Add (1 )
539528
540529 // we have TTL, create callback
541530 callb , stopCbCh , updateTTLCh := l .makeLockCallback (res , id , ttl )
542531
543532 r .locks .Store (id , & item {
544- callback : callb ,
545533 stopCh : stopCbCh ,
546534 updateTTLCh : updateTTLCh ,
547535 })
548536
549537 // run the callback
550538 go func () {
551- callb (id , r .notificationCh , r .stopCh )
539+ callb (r .notificationCh , r .stopCh )
552540 }()
553541
554542 r .resourceMu .unlock ()
@@ -698,11 +686,7 @@ func (l *locker) exists(ctx context.Context, res, id string) bool {
698686
699687 // Special case, check if we have any locks
700688 if id == "*" {
701- if r .writerCount .Load () > 0 || r .readerCount .Load () > 0 {
702- return true
703- }
704-
705- return false
689+ return r .writerCount .Load () > 0 || r .readerCount .Load () > 0
706690 }
707691
708692 if _ , existsID := r .locks .Load (id ); ! existsID {
@@ -751,15 +735,6 @@ func (l *locker) updateTTL(ctx context.Context, res, id string, ttl int) bool {
751735 "resource" , res ,
752736 "id" , id )
753737
754- if ! ok {
755- l .log .Warn ("no such resource" ,
756- "resource" , res ,
757- "id" , id )
758-
759- r .resourceMu .unlockRelease ()
760- return false
761- }
762-
763738 rl , ok := r .locks .Load (id )
764739 if ! ok {
765740 l .log .Warn ("no such resource ID" ,
@@ -811,7 +786,7 @@ func (l *locker) makeLockCallback(res, id string, ttl int) (callback, chan struc
811786 updateTTLCh := make (chan int , 1 )
812787
813788 // at this point, when adding lock, we should not have the callback
814- return func (lockID string , notifCh chan <- struct {}, sCh <- chan struct {}) {
789+ return func (notifCh chan <- struct {}, sCh <- chan struct {}) {
815790 // case for the items without TTL. We should add such items to control their flow
816791 cbttl := ttl
817792 if cbttl == 0 {
@@ -820,45 +795,47 @@ func (l *locker) makeLockCallback(res, id string, ttl int) (callback, chan struc
820795
821796 // TTL channel
822797 ta := time .NewTicker (time .Microsecond * time .Duration (cbttl ))
823- loop:
824- select {
825- case <- ta .C :
826- l .log .Debug ("r/lock: ttl expired" ,
827- "resource" , res ,
828- "id" , lockID ,
829- "ttl microseconds" , cbttl ,
830- )
831- ta .Stop ()
832- // broadcast stop channel
833- case <- sCh :
834- l .log .Debug ("r/lock: ttl removed, stop broadcast call" ,
835- "resource" , res ,
836- "id" , lockID ,
837- "ttl microseconds" , cbttl ,
838- )
839- ta .Stop ()
840- // item stop channel
841- case <- stopCbCh :
842- l .log .Debug ("r/lock: ttl removed, stop callback call" ,
843- "resource" , res ,
844- "id" , lockID ,
845- "ttl microseconds" , cbttl ,
846- )
847- ta .Stop ()
848- case newTTL := <- updateTTLCh :
849- // if the new TTL is 0, we should treat it as unlimited
850- if newTTL == 0 {
851- newTTL = 31555952000000 // year
798+ for {
799+ select {
800+ case <- ta .C :
801+ l .log .Debug ("r/lock: ttl expired" ,
802+ "resource" , res ,
803+ "id" , id ,
804+ "ttl microseconds" , cbttl ,
805+ )
806+ ta .Stop ()
807+ // broadcast stop channel
808+ case <- sCh :
809+ l .log .Debug ("r/lock: ttl removed, stop broadcast call" ,
810+ "resource" , res ,
811+ "id" , id ,
812+ "ttl microseconds" , cbttl ,
813+ )
814+ ta .Stop ()
815+ // item stop channel
816+ case <- stopCbCh :
817+ l .log .Debug ("r/lock: ttl removed, stop callback call" ,
818+ "resource" , res ,
819+ "id" , id ,
820+ "ttl microseconds" , cbttl ,
821+ )
822+ ta .Stop ()
823+ case newTTL := <- updateTTLCh :
824+ // if the new TTL is 0, we should treat it as unlimited
825+ if newTTL == 0 {
826+ newTTL = 31555952000000 // year
827+ }
828+ l .log .Debug ("r/lock: ttl was updated" ,
829+ "resource" , res ,
830+ "id" , id ,
831+ "new ttl microseconds" , newTTL )
832+ // update the initial ttl
833+ cbttl = newTTL
834+ ta .Reset (time .Microsecond * time .Duration (cbttl ))
835+ // in case of TTL, we don't need to remove the item, only update TTL
836+ continue
852837 }
853- l .log .Debug ("r/lock: ttl was updated" ,
854- "resource" , res ,
855- "id" , id ,
856- "new ttl microseconds" , newTTL )
857- // update the initial ttl
858- cbttl = newTTL
859- ta .Reset (time .Microsecond * time .Duration (cbttl ))
860- // in case of TTL, we don't need to remove the item, only update TTL
861- goto loop
838+ break
862839 }
863840
864841 // unlimited but should not be long
0 commit comments