From d46d6fdd4b578f4b0bac7d557d598178013756bc Mon Sep 17 00:00:00 2001
From: mcmlxxix <>
Date: Fri, 13 Apr 2012 16:04:33 +0000
Subject: [PATCH] fix release() method bug, remove invalid requests from queue
 (should never occur, really), add array slice() method

---
 exec/load/json-client.js | 17 +++++++-
 exec/load/json-db.js     | 92 +++++++++++++++++++++++++++-------------
 2 files changed, 79 insertions(+), 30 deletions(-)

diff --git a/exec/load/json-client.js b/exec/load/json-client.js
index 2f0a7826fb..fb17236a0d 100644
--- a/exec/load/json-client.js
+++ b/exec/load/json-client.js
@@ -74,7 +74,7 @@ function JSONClient(serverAddr,serverPort) {
 		throw("no port specified");
 	
 	this.settings={
-		CONNECTION_TIMEOUT:		5,
+		CONNECTION_TIMEOUT:		10,
 		PING_INTERVAL:			60*1000,
 		PING_TIMEOUT:			10*1000,
 		SOCK_TIMEOUT:			10*1000,
@@ -151,6 +151,21 @@ function JSONClient(serverAddr,serverPort) {
 		});
 		return this.wait();
     }
+	
+	/* array slice method */
+	this.slice=function(scope,location,start,end,lock) {
+		this.send(scope,"QUERY",{
+            oper:"SLICE",
+            location:location,
+			data:{
+				start:start,
+				end:end
+			},
+			lock:lock,
+ 			timeout:this.settings.TIMEOUT
+		});
+		return this.wait();
+	}
 
 	/* read multiple object data (lock for reading or writing, blocking) */
 	/* readmulti([['tw2','sector.1',undefined,'sector'],['tw2','planets.1',undefined,'planet']]); */
diff --git a/exec/load/json-db.js b/exec/load/json-db.js
index ed0b22ffbc..3f294acb80 100644
--- a/exec/load/json-db.js
+++ b/exec/load/json-db.js
@@ -52,7 +52,10 @@ function JSONdb (fileName) {
 	this.queue={};
 	
 	/* general list of db subscribers (for quick release if no subscriptions) */
-	this.subscriptions=[];
+	this.subscriptions={};
+	
+	/* list of disconnected clients */
+	this.disconnected={};
 	
 	/* database settings */
 	this.settings={
@@ -89,7 +92,8 @@ function JSONdb (fileName) {
 		UNSUBSCRIBE:9,
 		WHO:10,
 		STATUS:11,
-		KEYS:12
+		KEYS:12,
+		SLICE:13
 	}
 	
 	/* error constants */
@@ -117,10 +121,15 @@ function JSONdb (fileName) {
 		}
 		if(!this.subscriptions[client.id][record.location]) {
 	        record.shadow[record.child_name]._subscribers[client.id]=client;
-			this.subscriptions[client.id][record.location] = record;
+			this.subscriptions[client.id][record.location]=record;
+			record.subtime = Date.now();
 			send_subscriber_updates(client,record,"SUBSCRIBE");
 		}
 		else {
+			log(LOG_WARNING,
+				client.id + "@" + 
+				this.subscriptions[client.id][record.location].subtime + ": " +
+				record.location);
 			this.error(client,errors.DUPLICATE_SUB);
 		}
 		return true;
@@ -353,6 +362,31 @@ function JSONdb (fileName) {
         }
 	}
 	
+	/* shift a record off the end of an array */
+	this.slice = function(request,record) {
+		var client = request.client;
+		/* if the requested data does not exist, result is undefined */
+		if(record.data === undefined) {
+            send_packet(client,undefined,"RESPONSE");
+			return true;
+		}
+		/* if this client has this record locked  */
+		else if(record.info.lock[client.id]) {
+			if(record.data[record.child_name] instanceof Array) {
+				var d = record.data[record.child_name].slice(request.data.start,request.data.end);
+				send_packet(client,d,"RESPONSE");
+			}
+			else {
+				this.error(client,errors.NON_ARRAY);
+			}
+			return true;
+		}
+        /* if there is no lock for this client, error */
+        else {
+            return false;
+        }
+	}
+	
     /* server's data submission method (not directly called by client) */    
     this.write = function(request,record) {
 		var client = request.client;
@@ -600,24 +634,9 @@ function JSONdb (fileName) {
  
 	/* schedule client for subscription and lock release */
 	this.release = function(client) {
-		if(!this.queue[client.id])
-			this.queue[client.id] = [];
-		this.queue[client.id].push(new Request(client,"CLOSE"));
+		this.disconnected[client.id] = client;
 	}
  
-	/* release any locks or subscriptions held by a disconnected client */
-	this.close = function(client) {
-		/* release any locks the client holds */
-		free_prisoners(client,this.shadow);
-		
-		/* release any subscriptions the client holds */
-		cancel_subscriptions(client,this.subscriptions[client.id]);
-		
-		/* remove any remaining client queries */
-		fuh_queue(client,this.queue);
-		return true;
-	};
-	
     /* main "loop" called by server */
     this.cycle = function() {
 		/* process request queue, removing successful operations */
@@ -630,17 +649,9 @@ function JSONdb (fileName) {
 				var request=this.queue[c][r];
 				var result=false;
 				
-				/* if we have been asked to clear a client's locks, DEW IT */
-				if(request.oper.toUpperCase() == "CLOSE") {
-					this.queue[c].splice(r--,1);
-					this.close(request.client);
-					break;
-				}
-
 				/* locate the requested record within the database */
 				var record=identify_remains.call(
-					this,request.client,request.parent_name,request.child_name,
-					request.oper.toUpperCase() == "WRITE"
+					this,request.client,request.parent_name,request.child_name
 				);
 				
 				/* if there was an error parsing object location, delete request */
@@ -673,6 +684,9 @@ function JSONdb (fileName) {
 				case "UNSHIFT":
 					result=this.unshift(request,record);
 					break;
+				case "SLICE":
+					result=this.slice(request,record);
+					break;
 				case "DELETE":
 					result=this.remove(request,record);
 					break;
@@ -691,6 +705,10 @@ function JSONdb (fileName) {
 				case "WHO":
 					result=this.who(request,record);
 					break;
+				default:
+					this.error(client,errors.INVALID_REQUEST);
+					this.queue[c].splice(r--,1);
+					break;
 				}
 				
 				/* if the request did not succeed, move to the next user queue */
@@ -699,6 +717,22 @@ function JSONdb (fileName) {
 				this.queue[c].splice(r--,1);
 			}
 		} 
+		
+		/* terminate any disconnected clients after processing queue */
+		for each(var c in this.disconnected) {
+			/* release any locks the client holds */
+			free_prisoners(client,this.shadow);
+			
+			/* release any subscriptions the client holds */
+			cancel_subscriptions(client,this.subscriptions[client.id]);
+			
+			/* remove any remaining client queries */
+			fuh_queue(client,this.queue);
+		}
+		
+		/* reset disconnected client object */
+		this.disconnected={};
+		
 		if(!this.settings.UPDATES)
 			return;
 		if(!this.settings.SAVE_INTERVAL > 0)
@@ -779,7 +813,7 @@ function JSONdb (fileName) {
 
 	/* parse an object location name and return the object (ex: dicewarz2.games.1.players.1.tiles.0)
 	an object containing the corresponding data and its shadow object */
-	function identify_remains(client,parent_name,child_name,create_new) {
+	function identify_remains(client,parent_name,child_name) {
 
 		var data=this.data;
 		var shadow=this.shadow;
-- 
GitLab