Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

first working code

  • Loading branch information...
commit 911222ea5704cc93e13cd99df3cfa33c033f01ef 0 parents
Ian Babrou authored June 09, 2012
125  index.js
... ...
@@ -0,0 +1,125 @@
  1
+(function(module) {
  2
+	var net              = require("net"),
  3
+		Lock             = require("./lib/Lock"),
  4
+		LockQueueManager = require("./lib/LockQueuemanager");
  5
+	
  6
+	function releaseLocks(locksRegistry) {
  7
+		Object.keys(locksRegistry).forEach(function(key) {
  8
+			locksRegistry[key].release();
  9
+		});
  10
+	};
  11
+	
  12
+	function Locker() {
  13
+		var manager = new LockQueueManager();
  14
+
  15
+		this.server = net.createServer(function(connection) {
  16
+			var locksRegistry   = {},
  17
+				currentSequence = 0,
  18
+				data            = new Buffer(0),
  19
+				temp            = new Buffer(0);
  20
+		
  21
+			connection.on("error", function(error) {
  22
+				//console.log(error);
  23
+				connection.end();
  24
+				releaseLocks(locksRegistry);
  25
+			});
  26
+		
  27
+			connection.on("end", function() {
  28
+				releaseLocks(locksRegistry);
  29
+			});
  30
+			
  31
+			connection.on("timeout", function() {
  32
+				releaseLocks(locksRegistry);
  33
+			});
  34
+			
  35
+			connection.on("connect", function() {
  36
+				//console.log("got connection");
  37
+			});
  38
+			
  39
+			connection.on("data", function(part) {
  40
+				var sequence = 0,
  41
+					wait     = 0,
  42
+					timeout  = 0,
  43
+					action   = 0,
  44
+					name;
  45
+		
  46
+				temp = new Buffer(data.length + part.length);
  47
+				data.copy(temp, 0);
  48
+				part.copy(temp, data.length);
  49
+				
  50
+				data = new Buffer(temp)
  51
+				
  52
+				while (data.length && ((data[0] + 14) <= data.length)) {
  53
+					sequence = data.readUInt32LE(1);
  54
+					action   = data[13];
  55
+		
  56
+					if ((currentSequence < sequence && action == 1) || action == 0) {
  57
+						currentSequence = sequence;
  58
+						
  59
+						length   = data[0];
  60
+						wait     = data.readUInt32LE(5);
  61
+						timeout  = data.readUInt32LE(9);
  62
+						name     = data.slice(14, length + 14).toString();
  63
+						
  64
+						//console.log([length, wait, timeout, action, name]);
  65
+						
  66
+						if (action == 1) {
  67
+							lock(name, sequence, wait, timeout);
  68
+						} else if (action == 0) {
  69
+							unlock(sequence);
  70
+						}
  71
+		
  72
+						data = data.slice(length + 14);
  73
+						
  74
+						//console.log("data after all")
  75
+					} else {
  76
+						//console.log("SHIT!");
  77
+						connection.end();
  78
+						break;
  79
+					}
  80
+				}
  81
+			});
  82
+			
  83
+			function lock(name, sequence, wait, timeout) {
  84
+				var lock = new Lock(name, manager);
  85
+		
  86
+				locksRegistry[sequence] = lock;
  87
+				
  88
+				lock.acquire(wait, timeout, function(error) {
  89
+					respond(sequence, 1, error ? 0 : 1);
  90
+				});
  91
+			};
  92
+			
  93
+			function unlock(sequence) {
  94
+				var lock = locksRegistry[sequence];
  95
+				
  96
+				if (lock) {
  97
+					delete locksRegistry[sequence];
  98
+				}
  99
+				
  100
+				respond(sequence, 0, lock && lock.release());
  101
+			};
  102
+			
  103
+			function respond(sequence, action, result) {
  104
+				var response = new Buffer(6);
  105
+		
  106
+				response.writeUInt32LE(sequence, 0);
  107
+				response[4] = action;
  108
+				response[5] = result ? 1 : 0;
  109
+				
  110
+				//console.log("Written response: " + sequence + " " + action + " " + result);
  111
+				connection.write(response, "binary");
  112
+			};
  113
+		});
  114
+	};
  115
+	
  116
+	Locker.prototype.listen = function() {
  117
+		this.server.listen.apply(this.server, arguments);
  118
+	};
  119
+	
  120
+	Locker.prototype.close = function() {
  121
+		this.server.close.apply(this.server, arguments);
  122
+	};
  123
+	
  124
+	module.exports = Locker;
  125
+})(module);
82  lib/Lock.js
... ...
@@ -0,0 +1,82 @@
  1
+(function(module) {
  2
+	function Lock(name, manager) {
  3
+		this.name         = name;
  4
+		this.acquired     = false;
  5
+		this.manager      = manager;
  6
+		this.waitTimer    = undefined;
  7
+		this.timeoutTimer = undefined;
  8
+	};
  9
+	
  10
+	Lock.prototype.getName = function() {
  11
+		return this.name;
  12
+	};
  13
+	
  14
+	Lock.prototype.isAcquired = function() {
  15
+		return this.acquired;
  16
+	};
  17
+	
  18
+	Lock.prototype.acquire = function(wait, timeout, callback) {
  19
+		var self = this;
  20
+		
  21
+		if (self.acquired) {
  22
+			return true;
  23
+		}
  24
+		
  25
+		self.waitTimer = setTimeout(function() {
  26
+			//console.log("TWO");
  27
+			if (!self.acquired) {
  28
+				self.release();
  29
+				callback(new Error("Lock waiting timeout for " + self.getName()));
  30
+			}
  31
+		}, wait);
  32
+		
  33
+		self.queue = self.manager.getQueue(self.getName());
  34
+		self.queue.push(self, function(error) {
  35
+			//console.log("ONE");
  36
+			if (self.waitTimer) {
  37
+				clearTimeout(self.waitTimer);
  38
+				self.waitTimer = undefined;
  39
+			}
  40
+			
  41
+			if (error) {
  42
+				return callback(error);
  43
+			}
  44
+			
  45
+			self.acquired = true;
  46
+			
  47
+			callback(undefined, true);
  48
+			
  49
+			self.timeoutTimer = setTimeout(function() {
  50
+				//console.log("releasing");
  51
+				//console.log(self.acquired);
  52
+				if (self.acquired) {
  53
+					//console.log("really releasing");
  54
+					self.release();
  55
+				}
  56
+			}, timeout);
  57
+		});
  58
+		
  59
+		return false;
  60
+	};
  61
+	
  62
+	Lock.prototype.release = function() {
  63
+		var result = this.acquired;
  64
+	
  65
+		if (this.waitTimer) {
  66
+			clearTimeout(this.waitTimer);
  67
+			this.waitTimer = undefined;
  68
+		}
  69
+		
  70
+		if (this.timeoutTimer) {
  71
+			clearTimeout(this.timeoutTimer);
  72
+			this.timeoutTimer = undefined;
  73
+		}
  74
+		
  75
+		this.queue.pop(this);
  76
+		this.acquired = false;
  77
+		
  78
+		return result;
  79
+	};
  80
+	
  81
+	module.exports = Lock;
  82
+})(module);
49  lib/LockQueue.js
... ...
@@ -0,0 +1,49 @@
  1
+(function(module) {
  2
+	function LockQueue(name) {
  3
+		this.name  = name;
  4
+		this.queue = [];
  5
+	};
  6
+	
  7
+	LockQueue.prototype.getName = function() {
  8
+		return this.name;
  9
+	};
  10
+	
  11
+	LockQueue.prototype.push = function(lock, callback) {
  12
+		if (lock.getName() != this.getName()) {
  13
+			return callback(new Error("Incorrect lock name " + lock.getName() + " for queue " + this.getName()));
  14
+		}
  15
+		
  16
+		this.queue.push({
  17
+			lock     : lock,
  18
+			callback : callback
  19
+		});
  20
+		
  21
+		//console.log("queue length: " + this.queue.length);
  22
+	
  23
+		if (this.queue.length == 1) {
  24
+			callback(undefined, true);
  25
+		}
  26
+	};
  27
+	
  28
+	LockQueue.prototype.pop = function(lock) {
  29
+		//console.log("POP FROM QUEUE!")
  30
+		
  31
+		var first = this.queue[0];
  32
+		if (first && first.lock == lock) {
  33
+			this.queue.shift();
  34
+	
  35
+			// take next lock to acquire
  36
+			first = this.queue[0];
  37
+			
  38
+			if (first && first.callback) {
  39
+				first.callback(undefined, true);
  40
+			}
  41
+		} else {
  42
+			this.queue = this.queue.filter(function(current) {
  43
+				return current.lock != lock;
  44
+			});
  45
+		}
  46
+	};
  47
+	
  48
+	module.exports = LockQueue;
  49
+})(module);
20  lib/LockQueueManager.js
... ...
@@ -0,0 +1,20 @@
  1
+(function(module) {
  2
+	var LockQueue = require("./LockQueue");
  3
+	
  4
+	function LockQueueManager() {
  5
+		this.queues   = {};
  6
+		this.registry = {};
  7
+	};
  8
+	
  9
+	LockQueueManager.prototype.getQueue = function(name) {
  10
+		if (!this.queues[name]) {
  11
+			this.queues[name] = new LockQueue(name);
  12
+		}
  13
+		
  14
+		// need to release some queues that is empty
  15
+		
  16
+		return this.queues[name];
  17
+	};
  18
+	
  19
+	module.exports = LockQueueManager;
  20
+})(module);

0 notes on commit 911222e

Please sign in to comment.
Something went wrong with that request. Please try again.