Skip to content
Snippets Groups Projects
Commit d5e55b69 authored by mcmlxxix's avatar mcmlxxix
Browse files

remove clone function (no longer needed), reject root object requests, no...

remove clone function (no longer needed), reject root object requests, no longer self-instantiate, bundle LOCK/operation/UNLOCK requests when a lock is specified on an operation
parent 396d041c
Branches
Tags
No related merge requests found
......@@ -27,12 +27,25 @@
*/
if(!this.Database) {
Database = new (function() {
function JSONdb (fileName) {
this.VERSION = "$Revision$".split(' ')[1];
/* database storage file */
if(fileName)
this.file=new File(fileName);
else
this.file=undefined;
/* master database object */
this.data={};
/* database record subscription and locking object */
this.shadow={};
/* queued array of data requests (get/put/create/delete) */
this.queue=[];
/* database settings */
this.settings={
/* record lock constants, incremental (do not change the order or value) */
......@@ -57,76 +70,6 @@ Database = new (function() {
ERROR_DUPLICATE_LOCK:5
};
/**************************** database objects *****************************/
/* locking object generated by Database.lock() method
contains the type of lock requested, and the time at which the request came in
TODO: possibly "expire" unfulfilled lock requests after a certain period */
function Lock(lock_type,timestamp) {
this.type=lock_type;
this.timestamp=timestamp;
}
/* error object containing a description of the error */
function Error(error_num,error_desc) {
this.operation="ERROR";
this.error_num=error_num;
this.error_desc=error_desc;
}
/* shadow properties generated by composite_sketch()
contains a relative object's subscribers, locks, and child name */
function Shadow() {
this._lock=[];
this._lock_pending=false;
this._subscribers=[];
}
/* record object returned by identify_remains()
contains the requested object, its shadow object,
the prevailing lock state of that object (affected by parents/children),
and a list of subscribers associated with that object or its parents */
function Record(data,shadow,parent_name,child_name,info) {
this.data=data;
this.shadow=shadow;
this.parent_name=parent_name;
this.child_name=child_name;
this.info=info;
}
/* request object generated by Database.queue() method
contains the requested object parent, the specific child property requested,
data (in the case of a PUT operation ) */
function Request(client,operation,parent_name,child_name,data) {
this.client=client;
this.operation=operation;
this.parent_name=parent_name;
this.child_name=child_name;
this.data=data;
}
/* in the event of a corrupt JSON object or database problem,
it would be beneficial to be able to single-out the affected
module for correction, rather than destroy the entire database
it would also allow for a much simpler mechanism for removing
games you no longer wish to host (simply delete the db file and edit your service inis) */
/*************************** database data ******************************/
/* database storage file */
if(argv[0])
this.file=new File(argv[0]);
else
this.file=undefined;
/* master database object */
this.data={};
/* database record subscription and locking object */
this.shadow={};
/* queued array of data requests (get/put/create/delete) */
this.queue=[];
/*************************** database methods ****************************/
/* subscribe a client to an object */
this.subscribe = function(client,record) {
......@@ -211,7 +154,7 @@ Database = new (function() {
if(client_lock) {
/* if this was a write lock, send an update to all record subscribers */
if(client_lock.type == this.settings.LOCK_WRITE)
send_updates(record);
send_updates(client,record);
delete record.shadow[record.child_name]._lock[client.id];
return true;
}
......@@ -229,8 +172,7 @@ Database = new (function() {
this.read = function(client,record) {
/* if this client has this record locked, read */
if(record.info.lock[client.id]) {
var data = clone(record.data[record.child_name]);
send_packet(client,data,"RESPONSE");
send_packet(client,record.data[record.child_name],"RESPONSE");
return true;
}
/* if there is no lock for this client, error */
......@@ -298,24 +240,33 @@ Database = new (function() {
var parent_name = query.location.substring(0,query.location.lastIndexOf("."));
/* store the child name */
var child_name = query.location.substr(query.location.lastIndexOf(".")+1);
/* if the data request is invalid or empty, return an error */
if(!parent_name || !child_name) {
this.error(client,this.settings.ERROR_INVALID_REQUEST);
return false;
}
/* temporary array for queue additions */
var q=[];
/* if an operation is requested */
if(query.operation !== undefined) {
request = new Request(client,query.operation,parent_name,child_name,query.data);
/* push this query into a queue to be processed at the next response cycle (this.cycle()) */;
q.push(request);
}
/* if there is an attached lock operation, process accordingly */
if(query.lock !== undefined) {
request = new Request(client,"LOCK",parent_name,child_name,query.lock);
/* if this is a read or write lock, put it ahead of the operation in the request queue */
if(query.lock == this.settings.LOCK_UNLOCK)
q.unshift(request);
/* if this is an unlock, process it after the operation in the request queue */
else if(query.lock == this.settings.LOCK_READ || query.lock == this.settings.LOCK_WRITE)
q.push(request);
/* put lock ahead of the operation in request queue */
q.unshift(new Request(
client,"LOCK",parent_name,child_name,query.lock
));
/* put unlock after the operation in the request queue */
q.push(new Request(
client,"LOCK",parent_name,child_name,this.settings.LOCK_UNLOCK
));
}
/* add the temporary queue to the main queue */
this.queue=this.queue.concat(q);
......@@ -413,7 +364,11 @@ Database = new (function() {
var result=false;
/* locate the requested record within the database */
var record=identify_remains.call(this,request.client,request.parent_name,request.child_name);
var record=identify_remains.call(
this,request.client,request.parent_name,request.child_name
);
log("r: " + record.data.toSource());
if(!record) {
log(LOG_DEBUG,"db: bad request removed from queue");
......@@ -464,6 +419,53 @@ Database = new (function() {
}
};
/**************************** database objects *****************************/
/* locking object generated by Database.lock() method
contains the type of lock requested, and the time at which the request came in
TODO: possibly "expire" unfulfilled lock requests after a certain period */
function Lock(lock_type,timestamp) {
this.type=lock_type;
this.timestamp=timestamp;
}
/* error object containing a description of the error */
function Error(error_num,error_desc) {
this.operation="ERROR";
this.error_num=error_num;
this.error_desc=error_desc;
}
/* shadow properties generated by composite_sketch()
contains a relative object's subscribers, locks, and child name */
function Shadow() {
this._lock=[];
this._lock_pending=false;
this._subscribers=[];
}
/* record object returned by identify_remains()
contains the requested object, its shadow object,
the prevailing lock state of that object (affected by parents/children),
and a list of subscribers associated with that object or its parents */
function Record(data,shadow,parent_name,child_name,info) {
this.data=data;
this.shadow=shadow;
this.parent_name=parent_name;
this.child_name=child_name;
this.info=info;
}
/* request object generated by Database.queue() method
contains the requested object parent, the specific child property requested,
data (in the case of a PUT operation ) */
function Request(client,operation,parent_name,child_name,data) {
this.client=client;
this.operation=operation;
this.parent_name=parent_name;
this.child_name=child_name;
this.data=data;
}
/*************************** database functions ****************************/
/* traverse object and create a shadow copy of the object structure
for record locking and subscribers, and create location names for database objects */
......@@ -490,12 +492,6 @@ Database = new (function() {
function identify_remains(client,parent_name,child_name) {
var p=parent_name.split(/\./);
/* if the data request is invalid or empty, return an error */
if(!p) {
this.error(client,this.settings.ERROR_INVALID_REQUEST);
return false;
}
var data=this.data;
var shadow=this.shadow;
var info={
......@@ -560,12 +556,6 @@ Database = new (function() {
}
}
/* make a copy of an object to avoid modifying the original */
function clone(obj) {
var newobj=eval(obj.toSource());
return newobj;
}
/* return the prevailing lock type and pending lock status for an object */
function investigate(shadow, info) {
/* if we havent found a write locked record yet, keep searching */
......@@ -596,8 +586,11 @@ Database = new (function() {
}
/* send updates of this object to all subscribers */
function send_updates(record) {
function send_updates(client,record) {
for each(var c in record.info.subscribers) {
/* do not send updates to request originator */
if(c.id == client.id)
continue;
var data = {
location:record.parent_name + "." + record.child_name,
data:record.data[record.child_name]
......@@ -617,9 +610,7 @@ Database = new (function() {
/* constructor */
this.init();
})();
}
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment