2015-07-20 00:09:47 -07:00
'use strict' ;
2022-04-14 17:41:41 -05:00
const assert = require ( 'assert' ) ,
2019-12-04 10:29:06 -08:00
BoxError = require ( './boxerror.js' ) ,
2015-07-20 00:09:47 -07:00
debug = require ( 'debug' ) ( 'box:locker' ) ,
EventEmitter = require ( 'events' ) . EventEmitter ,
util = require ( 'util' ) ;
function Locker ( ) {
this . _operation = null ;
this . _timestamp = null ;
this . _watcherId = - 1 ;
2015-09-04 22:06:43 -07:00
this . _lockDepth = 0 ; // recursive locks
2015-07-20 00:09:47 -07:00
}
util . inherits ( Locker , EventEmitter ) ;
// these are mutually exclusive operations
Locker . prototype . OP _BOX _UPDATE = 'box_update' ;
2023-08-12 19:28:07 +05:30
Locker . prototype . OP _INFRA _START = 'infra_start' ;
2015-07-20 00:09:47 -07:00
Locker . prototype . OP _FULL _BACKUP = 'full_backup' ;
Locker . prototype . OP _APPTASK = 'apptask' ;
Locker . prototype . lock = function ( operation ) {
assert . strictEqual ( typeof operation , 'string' ) ;
2019-08-28 21:59:14 -07:00
if ( this . _operation !== null ) {
2019-12-04 10:29:06 -08:00
let error = new BoxError ( BoxError . CONFLICT , ` Locked for ${ this . _operation } ` ) ;
2019-08-28 21:59:14 -07:00
error . operation = this . _operation ;
return error ;
}
2015-07-20 00:09:47 -07:00
this . _operation = operation ;
2015-09-04 22:06:43 -07:00
++ this . _lockDepth ;
2015-07-20 00:09:47 -07:00
this . _timestamp = new Date ( ) ;
2022-04-14 17:41:41 -05:00
this . _watcherId = setInterval ( ( ) => { debug ( 'Lock unreleased %s' , this . _operation ) ; } , 1000 * 60 * 5 ) ;
2015-07-20 00:09:47 -07:00
debug ( 'Acquired : %s' , this . _operation ) ;
this . emit ( 'locked' , this . _operation ) ;
return null ;
} ;
2015-09-04 22:06:43 -07:00
Locker . prototype . recursiveLock = function ( operation ) {
if ( this . _operation === operation ) {
++ this . _lockDepth ;
debug ( 'Re-acquired : %s Depth : %s' , this . _operation , this . _lockDepth ) ;
return null ;
}
return this . lock ( operation ) ;
} ;
2015-07-20 00:09:47 -07:00
Locker . prototype . unlock = function ( operation ) {
assert . strictEqual ( typeof operation , 'string' ) ;
2021-08-17 15:20:30 -07:00
if ( this . _operation !== operation ) throw new BoxError ( BoxError . BAD _STATE , 'Mismatched unlock. Current lock is for ' + this . _operation ) ; // throw because this is a programming error
2015-07-20 00:09:47 -07:00
2015-09-04 22:06:43 -07:00
if ( -- this . _lockDepth === 0 ) {
debug ( 'Released : %s' , this . _operation ) ;
2015-07-20 00:09:47 -07:00
2015-09-04 22:06:43 -07:00
this . _operation = null ;
this . _timestamp = null ;
clearInterval ( this . _watcherId ) ;
this . _watcherId = - 1 ;
} else {
debug ( 'Recursive lock released : %s. Depth : %s' , this . _operation , this . _lockDepth ) ;
}
2015-07-20 00:09:47 -07:00
this . emit ( 'unlocked' , operation ) ;
return null ;
2015-07-28 13:09:24 -07:00
} ;
2015-07-20 00:09:47 -07:00
exports = module . exports = new Locker ( ) ;