return query_ext.records.get(record_key);
}
+ this.del_record = function(query_uuid, record_key)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ return query_ext.records.remove(record_key);
+ }
+
+ this.del_state = function(query_uuid, record_key)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ return query_ext.state.remove(record_key);
+ }
+
this.add_record = function(query_uuid, record, new_state)
{
var query_ext, key, record_key;
} else {
record_key = record;
}
-
- manifold.query_store.set_record_state(query_uuid, record_key, STATE_SET, new_state);
+
+ if ((query_ext.query.object == 'lease') && (new_state == STATE_SET_OUT)) {
+ // Leases that are marked out are in fact leases from other slices
+ // We need to _remove_ leases that we mark as OUT
+ manifold.query_store.del_record(query_uuid, record_key);
+ manifold.query_store.del_state(query_uuid, record_key);
+ } else {
+ manifold.query_store.set_record_state(query_uuid, record_key, STATE_SET, new_state);
+ }
}
this.iter_records = function(query_uuid, callback)
{
var query_ext = this.find_analyzed_query_ext(query_uuid);
query_ext.filters = $.grep(query_ext.filters, function(x) {
- return x == filter;
+ return x != filter;
});
this.apply_filters(query_uuid);
{
return function() {
ret = "";
- for (i=0; i < key_fields.length; i++)
+ for (var i=0; i < key_fields.length; i++)
ret += "@@" + this[key_fields[i]];
return ret;
};
},
- record_equals: function(key_fields)
+ _record_equals: function(self, other, key_fields)
{
- var self = this;
-
- return function(other) {
- for (i=0; i < key_fields.length; i++) {
- var this_value = this[key_fields[i]];
- var other_value = other[key_fields[i]];
+ for (var i=0; i < key_fields.length; i++) {
+ var this_value = self[key_fields[i]];
+ var other_value = other[key_fields[i]];
- var this_type = self.get_type(this_value);
- var other_type = self.get_type(other_value);
- if (this_type != other_type)
- return false;
+ var this_type = manifold.get_type(this_value);
+ var other_type = manifold.get_type(other_value);
+ if (this_type != other_type)
+ return false;
- switch (this_type) {
- case TYPE_VALUE:
- case TYPE_LIST_OF_VALUES:
- if (this_value != other_value)
- return false;
- break;
- case TYPE_RECORD:
- if (!(record_equals(this_value, other_value)))
- return false;
- break;
- case TYPE_LIST_OF_RECORDS:
- if (this_value.length != other_value.length)
+ switch (this_type) {
+ case TYPE_VALUE:
+ case TYPE_LIST_OF_VALUES:
+ if (this_value != other_value)
+ return false;
+ break;
+ case TYPE_RECORD:
+ if (!(_record_equals(this_value, other_value, key_fields)))
+ return false;
+ break;
+ case TYPE_LIST_OF_RECORDS:
+ if (this_value.length != other_value.length)
+ return false;
+ for (var j = 0; j < this_value.length; j++)
+ if (!(_record_equals(this_value[j], other_value[j], key_fields)))
return false;
- for (i = 0; i < this_value.length; i++)
- if (!(record_equals(this_value, other_value)))
- return false;
- break;
- }
+ break;
}
- return true;
+ }
+ return true;
+ },
+
+ record_equals: function(key_fields)
+ {
+ return function(other) {
+ return manifold._record_equals(this, other, key_fields);
};
},
+ _in_array: function(element, array, key_fields)
+ {
+ if (key_fields.length > 1) {
+ for (var i = 0; i < array.length; i++) {
+ if (manifold._record_equals(element, array[i], key_fields))
+ return true;
+ }
+ return false;
+ } else {
+ // XXX TODO If we have a dict, extract the key first
+ return ($.inArray(element, array) != -1);
+ }
+ },
/**************************************************************************
* Metadata management
if (query_ext.set_query_ext) {
// We have a domain query
// The results are stored in the corresponding set_query
- manifold.query_store.set_records(query_ext.set_query_ext.query.query_uuid, records)
+ manifold.query_store.set_records(query_ext.set_query_ext.query.query_uuid, records);
} else if (query_ext.domain_query_ext) {
// We have a set query, it is only used to determine which objects are in the set, we should only retrieve the key
messages.debug ("<<<<< publish_result_rec " + query.object);
},
- setup_update_query: function(query, records) {
+ setup_update_query: function(query, records)
+ {
// We don't prepare an update query if the result has more than 1 entry
if (records.length != 1)
return;
throw "Not implemented";
break;
- case TYPE_LIST_OF_VALUES:
+ /*
+case TYPE_LIST_OF_VALUES:
// Same as list of records, but we don't have to extract keys
// The rest of exactly the same (XXX factorize)
break;
+ */
+ case TYPE_LIST_OF_VALUES: // XXX Until fixed
case TYPE_LIST_OF_RECORDS:
+ var key, new_state, cur_query_uuid;
+
+ cur_query_uuid = query.analyzed_query.subqueries[field].query_uuid;
+
// example: slice.resource
// - update_query_orig.params.resource = resources in slice before update
// - update_query.params.resource = resource requested in slice
// - keys from field = resources obtained
- var key = manifold.metadata.get_key(field);
+
+ if (field == 'lease') {
+ // lease_id has been added to be repeated when
+ // constructing request rspec. We don't want it for
+ // comparisons
+ key = ['start_time', 'end_time', 'resource'];
+ } else {
+ key = manifold.metadata.get_key(field);
+ }
if (!key)
continue;
+ /*
if (key.length > 1) {
throw "Not implemented";
continue;
}
key = key[0];
+ */
/* XXX should be modified for multiple keys */
var result_keys = $.map(record[field], function(x) { return manifold.record_get_value(x, key); });
+ // XXX All this could be deduced from record state : STATE_IN_PENDING and STATE_OUT_PENDING
+ // what we had at the begining
var update_keys = update_query_orig.params[field];
+ // what we asked
var query_keys = update_query.params[field];
- var added_keys = $.grep(query_keys, function (x) { return $.inArray(x, update_keys) == -1 });
- var removed_keys = $.grep(update_keys, function (x) { return $.inArray(x, query_keys) == -1 });
+ // what we added and removed
+ var added_keys = $.grep(query_keys, function (x) { return (!(manifold._in_array(x, update_keys, key))); });
+ var removed_keys = $.grep(update_keys, function (x) { return (!(manifold._in_array(x, query_keys, key))); });
+ // Send events related to parent query
+ $.each(added_keys, function(i, added_key) {
+ new_state = (manifold._in_array(added_key, result_keys, key)) ? STATE_SET_IN_SUCCESS : STATE_SET_IN_FAILURE;
- $.each(added_keys, function(i, key) {
- if ($.inArray(key, result_keys) == -1) {
- data = {
- state: STATE_SET,
- key : field,
- op : STATE_SET_IN_FAILURE,
- value: key
- }
- } else {
- data = {
- state: STATE_SET,
- key : field,
- op : STATE_SET_IN_SUCCESS,
- value: key
- }
- }
+ // Update record state for children queries
+ manifold.query_store.set_record_state(cur_query_uuid, added_key, STATE_SET, new_state);
+
+ // XXX This could be optimized
+ manifold.query_store.recount(cur_query_uuid);
+
+ data = { state: STATE_SET, key : field, op : new_state, value: added_key }
manifold.raise_record_event(query_uuid, FIELD_STATE_CHANGED, data);
+
+ // Inform subquery also
+ data.key = '';
+ manifold.raise_record_event(cur_query_uuid, FIELD_STATE_CHANGED, data);
+ // XXX Passing no parameters so that they can redraw everything would
+ // be more efficient but is currently not supported
+ // XXX We could also need to inform plugins about nodes IN (not pending) that are no more, etc.
+ // XXX refactor all this when suppressing update_queries, and relying on state instead !
});
- $.each(removed_keys, function(i, key) {
- if ($.inArray(key, result_keys) == -1) {
- data = {
- state: STATE_SET,
- key : field,
- op : STATE_SET_OUT_SUCCESS,
- value: key
- }
- } else {
- data = {
- state: STATE_SET,
- key : field,
- op : STATE_SET_OUT_FAILURE,
- value: key
- }
- }
+ $.each(removed_keys, function(i, removed_key) {
+ new_state = (manifold._in_array(removed_key, result_keys, key)) ? STATE_SET_OUT_FAILURE : STATE_SET_OUT_SUCCESS;
+
+ // Update record state for children queries
+ manifold.query_store.set_record_state(cur_query_uuid, removed_key, STATE_SET, new_state);
+
+ // XXX This could be optimized
+ manifold.query_store.recount(cur_query_uuid);
+
+ data = { state: STATE_SET, key : field, op : new_state, value: removed_key }
manifold.raise_record_event(query_uuid, FIELD_STATE_CHANGED, data);
- });
+ // Inform subquery also
+ data.key = '';
+ manifold.raise_record_event(cur_query_uuid, FIELD_STATE_CHANGED, data);
+ });
break;
}
var query_ext = manifold.query_store.find_query_ext(query.query_uuid);
query_ext.query_state = QUERY_STATE_DONE;
+
// Send DONE message to plugins
- manifold.raise_record_event(query.query_uuid, DONE);
+ query.iter_subqueries(function(sq, data, parent_query) {
+ manifold.raise_record_event(sq.query_uuid, DONE);
+ });
},
/**
* Event handler helpers
*/
- _get_next_state_add: function(prev_state, event_type)
+ _get_next_state_add: function(prev_state)
{
switch (prev_state) {
case STATE_SET_OUT:
return new_state;
},
- _get_next_state_remove: function(prev_state, event_type)
+ _get_next_state_remove: function(prev_state)
{
switch (prev_state) {
case STATE_SET_IN:
}
},
- _enforce_constraints: function(query_ext, record, resource_key, event_type)
+ _enforce_constraints: function(query_ext, record, record_key, event_type)
{
var query, data;
// XXX Not always a resource
var is_reservable = (record.exclusive == true);
if (is_reservable) {
- var warnings = manifold.query_store.get_record_state(query.query_uuid, resource_key, STATE_WARNINGS);
+ var warnings = manifold.query_store.get_record_state(query.query_uuid, record_key, STATE_WARNINGS);
if (event_type == STATE_SET_ADD) {
// We should have a lease_query associated
var lease_query = query_ext.parent_query_ext.query.subqueries['lease']; // in options
var lease_query_ext = manifold.query_store.find_analyzed_query_ext(lease_query.query_uuid);
// Do we have lease records (in) with this resource
- var lease_records = $.grep(lease_query_ext.records.entries(), this._grep_active_lease_callback(lease_query, resource_key));
+ var lease_records = $.grep(lease_query_ext.records.entries(), this._grep_active_lease_callback(lease_query, record_key));
if (lease_records.length == 0) {
// Sets a warning
// XXX Need for a better function to manage warnings
delete warnings[CONSTRAINT_RESERVABLE_LEASE];
}
- manifold.query_store.set_record_state(query.query_uuid, resource_key, STATE_WARNINGS, warnings);
+ manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
}
/* This was redundant */
// Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
data = {
state: STATE_WARNINGS,
- key : resource_key,
+ key : record_key,
op : null,
value : warnings
}
break;
case 'lease':
- var resource_key = record.resource;
+ var resource_key = record_key.resource;
var resource_query = query_ext.parent_query_ext.query.subqueries['resource'];
var warnings = manifold.query_store.get_record_state(resource_query.query_uuid, resource_key, STATE_WARNINGS);
break;
case STATE_SET:
+ var prev_state, new_state;
+ var main_query, record, new_data, path;
+
+ // We only track state in the analyzed query
+ prev_state = manifold.query_store.get_record_state(query_uuid, data.value, STATE_SET);
+ if (prev_state === null)
+ prev_state = STATE_SET_OUT;
switch(data.op) {
case STATE_SET_ADD:
- var prev_state, new_state;
- var main_query, record, new_data;
-
- prev_state = manifold.query_store.get_record_state(query_uuid, data.value, STATE_SET);
- if (prev_state === null)
- prev_state = STATE_SET_OUT;
- new_state = this._get_next_state_add(prev_state, data.state);
-
- if (!data.key) {
- /* data.value containts the resource key */
- manifold.query_store.add_record(query_uuid, data.value, new_state);
- record = manifold.query_store.get_record(query_uuid, data.value);
- this._enforce_constraints(query_ext, record, data.value, STATE_SET_ADD);
-
- /* Inform the parent query: important for update */
- new_data = {
- state : STATE_SET,
- key : '', //this._get_query_path(query_ext),
- op : STATE_SET_ADD,
- value : data.value,
- };
- main_query = query_ext.main_query_ext.query;
- this.raise_event(main_query.query_uuid, FIELD_STATE_CHANGED, new_data);
-
- new_data.op = new_state;
-
- } else {
- // mainquery: proceed to update
-
- //if ($.inArray(data.value, update_query_orig.params[data.key]) != -1)
- // value.request = FIELD_REQUEST_ADD_RESET;
-
- if (update_query.params[data.key] === undefined)
- update_query.params[data.key] = Array();
- update_query.params[data.key].push(data.value);
+ new_state = this._get_next_state_add(prev_state);
- new_data = {
- state : STATE_SET,
- key : this._get_query_path(query_ext),// null???
- op : new_state,
- value : data.value,
- }
- }
-
- /* Propagate the event to other plugins subscribed to the query */
- manifold.query_store.recount(query_uuid);
- manifold.raise_record_event(query_uuid, event_type, new_data);
+ /* data.value containts the resource key */
+ manifold.query_store.add_record(query_uuid, data.value, new_state);
+ record = manifold.query_store.get_record(query_uuid, data.value);
+ this._enforce_constraints(query_ext, record, data.value, STATE_SET_ADD);
+
+ /* Process update query in parent */
+ path = this._get_query_path(query_ext);
+ if (update_query.params[path] === undefined)
+ update_query.params[path] = Array();
+ update_query.params[path].push(data.value);
break;
case STATE_SET_REMOVE:
- var prev_state, new_state;
- var main_query, record, new_data;
-
- prev_state = manifold.query_store.get_record_state(query_uuid, data.value, STATE_SET);
- if (prev_state === null)
- prev_state = STATE_SET_OUT;
- new_state = this._get_next_state_remove(prev_state, data.state);
-
- if (!data.key) {
- /* data.value contains the resource key */
- manifold.query_store.remove_record(query_uuid, data.value, new_state);
- record = manifold.query_store.get_record(query_uuid, data.value);
- this._enforce_constraints(query_ext, record, data.value, STATE_SET_REMOVE);
-
- /* Inform the parent query: important for update */
- new_data = {
- state : STATE_SET,
- key : '', //this._get_query_path(query_ext),
- op : STATE_SET_REMOVE,
- value : data.value,
- };
- main_query = query_ext.main_query_ext.query;
- this.raise_event(main_query.query_uuid, FIELD_STATE_CHANGED, new_data);
-
- new_data.op = new_state
+ new_state = this._get_next_state_remove(prev_state);
+
+ /* data.value contains the resource key */
+ manifold.query_store.remove_record(query_uuid, data.value, new_state);
+ record = manifold.query_store.get_record(query_uuid, data.value);
+ this._enforce_constraints(query_ext, record, data.value, STATE_SET_REMOVE);
- } else {
- // main query: proceed to update
-
- //if ($.inArray(data.value, update_query_orig.params[data.key]) == -1)
- // value.request = FIELD_REQUEST_REMOVE_RESET;
-
- var arr = update_query.params[data.key];
- arr = $.grep(arr, function(x) { return x != data.value; });
- if (update_query.params[data.key] === undefined)
- update_query.params[data.key] = Array();
- update_query.params[data.key] = arr;
-
- new_data = {
- state : STATE_SET,
- key : this._get_query_path(query_ext),// null???
- op : new_state,
- value : data.value,
- }
- }
-
- /* Propagate the event to other plugins subscribed to the query */
- manifold.query_store.recount(query_uuid);
- manifold.raise_query_event(query_uuid, event_type, new_data);
+ /* Process update query in parent */
+ path = this._get_query_path(query_ext);
+ arr = update_query.params[path];
+
+ var key = manifold.metadata.get_key(query.object);
+ arr = $.grep(arr, function(x) { return (!(manifold._record_equals(x, data.value, key))); });
+ if (update_query.params[path] === undefined)
+ update_query.params[path] = Array();
+ update_query.params[path] = arr;
break;
}
+
+ /* Inform the parent query: important for update */
+ new_data = {
+ state : STATE_SET,
+ key : path,
+ op : new_state,
+ value : data.value,
+ };
+ main_query = query_ext.main_query_ext.query;
+ manifold.raise_record_event(main_query.query_uuid, event_type, new_data);
+ /* Propagate the event to other plugins subscribed to the query */
+ manifold.query_store.recount(query_uuid);
+ new_data.key = ''
+ manifold.raise_record_event(query_uuid, event_type, new_data);
+
break;
}
/*
// FILTERS
case FILTER_ADDED:
+ console.log("FILTER ADDED", data);
/* Update internal record state */
manifold.query_store.add_filter(query_uuid, data);
break;
case FILTER_REMOVED:
+ console.log("FILTER REMOVED", data);
/* Update internal record state */
manifold.query_store.remove_filter(query_uuid, data);