Commit 86ef40f0 by preetwinder

Use replicatestorage to repair

1 parent 44ba7ad2
......@@ -35,6 +35,7 @@
throw new TypeError("IndexStorage2 'index_keys' description property " +
"must be an Array");
}
this._sub_storage_description = description.sub_storage;
this._sub_storage = jIO.createJIO(description.sub_storage);
this._database_name = "jio:" + description.database;
this._index_keys = description.index_keys || [];
......@@ -68,38 +69,6 @@
return doc;
}
function getDocs(storage) {
var promise_hash = {}, i;
try {
storage.hasCapacity('include');
return storage.allDocs({include_docs: true});
} catch (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 501)) {
storage.hasCapacity('list');
return storage.allDocs()
.push(function (result) {
var id;
for (i = 0; i < result.data.total_rows; i += 1) {
id = result.data.rows[i].id;
promise_hash[id] = storage.get(id);
}
return RSVP.hash(promise_hash);
})
.push(function (temp_result) {
var final_result = {data: {rows: []}}, keys;
keys = Object.keys(temp_result);
for (i = 0; i < keys.length; i += 1) {
final_result.data.rows.push({id: keys[i],
doc: temp_result[keys[i]]});
}
final_result.data.total_rows = final_result.data.rows.length;
return final_result;
});
}
throw error;
}
}
function waitForIDBRequest(request) {
return new RSVP.Promise(function (resolve, reject) {
request.onerror = reject;
......@@ -107,10 +76,55 @@
});
}
function handleUpgradeNeeded(evt, index_keys, repair_storage) {
function VirtualIDB(description) {
this._write_operations = description.write_operations;
}
VirtualIDB.prototype.put = function () {
this._write_operations.put.push(arguments);
};
VirtualIDB.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'select');
};
VirtualIDB.prototype.get = function (id) {
throw new jIO.util.jIOError("Cannot find document: " + id, 404);
};
VirtualIDB.prototype.buildQuery = function () {
return [];
};
jIO.addStorage("virtualidb", VirtualIDB);
function getVirtualIDB(write_operations, sub_storage_description) {
return jIO.createJIO({
type: "replicate",
local_sub_storage: sub_storage_description,
check_local_modification: false,
check_local_deletion: false,
check_local_creation: true,
check_remote_modification: false,
check_remote_creation: false,
check_remote_deletion: false,
remote_sub_storage: {
type: "virtualidb",
write_operations: write_operations,
},
signature_sub_storage: {
type: "query",
sub_storage: {
type: "memory"
}
}
});
}
function handleUpgradeNeeded(evt, index_keys, sub_storage_description) {
var db = evt.target.result, store, i, current_indices, required_indices,
put_promise_list = [], docs_promise,
repeatUntilPromiseFulfilled;
put_promise_list = [], repair_promise, repeatUntilPromiseFulfilled,
write_operations;
required_indices = new Set(index_keys.map(function (name) {
return 'Index-' + name;
}));
......@@ -142,35 +156,34 @@
'doc.' + index_keys[i], { unique: false });
}
docs_promise = getDocs(repair_storage);
write_operations = {put: []};
repair_promise = getVirtualIDB(write_operations, sub_storage_description)
.repair();
repeatUntilPromiseFulfilled = function repeatUntilPromiseFulfilled(req) {
req.onsuccess = function () {
if (docs_promise.isRejected) {
throw new jIO.util.jIOError(docs_promise.rejectedReason.message,
docs_promise.rejectedReason.status_code);
if (repair_promise.isRejected) {
evt.target.transaction.abort();
return;
}
if (docs_promise.isFulfilled) {
for (i = 0; i < docs_promise.fulfillmentValue.data.total_rows;
i += 1) {
if (repair_promise.isFulfilled) {
for (i = 0; i < write_operations.put.length; i += 1) {
put_promise_list.push(waitForIDBRequest(store.put({
id: docs_promise.fulfillmentValue.data.rows[i].id,
doc: filterDocValues(
docs_promise.fulfillmentValue.data.rows[i].doc,
index_keys
)
id: write_operations.put[i][0],
doc: filterDocValues(write_operations.put[i][1], index_keys)
})));
}
write_operations.put = [];
return RSVP.all(put_promise_list);
}
repeatUntilPromiseFulfilled(store.getAll());
return repeatUntilPromiseFulfilled(store.getAll());
};
};
repeatUntilPromiseFulfilled(store.getAll());
}
}
function waitForOpenIndexedDB(db_name, version, index_keys, repair_storage,
callback) {
function waitForOpenIndexedDB(db_name, version, index_keys,
sub_storage_description, callback) {
function resolver(resolve, reject) {
// Open DB //
var request = indexedDB.open(db_name, version);
......@@ -205,7 +218,7 @@
// Create DB if necessary //
request.onupgradeneeded = function (evt) {
handleUpgradeNeeded(evt, index_keys, repair_storage);
handleUpgradeNeeded(evt, index_keys, sub_storage_description);
};
request.onversionchange = function () {
......@@ -292,7 +305,7 @@
IndexStorage2.prototype._runQuery = function (key, value, limit) {
var context = this;
return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, context._sub_storage, function (db) {
context._index_keys, context._sub_storage_description, function (db) {
return waitForTransaction(db, ["index-store"], "readonly",
function (tx) {
return context._iterateCursor(tx.objectStore("index-store")
......@@ -336,7 +349,7 @@
return;
}
return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, context._sub_storage, function (db) {
context._index_keys, context._sub_storage_description, function (db) {
return waitForTransaction(db, ["index-store"], "readwrite",
function (tx) {
return waitForIDBRequest(tx.objectStore("index-store").put({
......@@ -368,7 +381,7 @@
return context._sub_storage.remove(id)
.push(function () {
return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, context._sub_storage, function (db) {
context._index_keys, context._sub_storage_description, function (db) {
return waitForTransaction(db, ["index-store"], "readwrite",
function (tx) {
return waitForIDBRequest(tx.objectStore("index-store")
......
......@@ -244,7 +244,7 @@
module("indexStorage2.buildQuery", {
setup: function () {
DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include');
return (name === 'list') || (name === 'include') || (name === 'select');
};
DummyStorage3.prototype.buildQuery = function () {
return [];
......@@ -256,7 +256,7 @@
});
test("Sub-storage handles empty options", function () {
var context = this;
var context = this, call_count = 0;
context.jio = jIO.createJIO({
type: "index2",
database: "index2_test",
......@@ -273,6 +273,10 @@
};
DummyStorage3.prototype.buildQuery = function (options) {
call_count += 1;
if (call_count === 1) {
return [];
}
if (options.include_docs !== true) {
return [
{id: "2", value: {}},
......@@ -307,7 +311,7 @@
});
test("Sub storage capacities are used by default", function () {
var context = this;
var context = this, kemp = 0;
context.jio = jIO.createJIO({
type: "index2",
database: "index2_test",
......@@ -329,6 +333,10 @@
};
DummyStorage3.prototype.buildQuery = function (options) {
kemp += 1;
if (kemp === 1) {
return [];
}
if (options.include_docs === true) {
return [];
}
......@@ -488,7 +496,7 @@
});
});
test("Repair on storage without include_docs support", function () {
test("Use existing data to build Index", function () {
var context = this, fake_data;
context.jio = jIO.createJIO({
type: "index2",
......@@ -499,7 +507,7 @@
}
});
stop();
expect(3);
expect(2);
fake_data = {
"1": {a: "id54", b: 2, c: "night"},
......@@ -508,7 +516,7 @@
};
DummyStorage3.prototype.hasCapacity = function (name) {
return name === 'list';
return (name === 'list') || (name === 'select');
};
DummyStorage3.prototype.put = function (id, value) {
fake_data[id] = value;
......@@ -517,60 +525,9 @@
DummyStorage3.prototype.get = function (id) {
return fake_data[id];
};
DummyStorage3.prototype.buildQuery = function (options) {
deepEqual(options, {});
DummyStorage3.prototype.buildQuery = function () {
var keys = Object.keys(fake_data);
return keys.map(function (v) { return {id: v, value: {}}; });
};
RSVP.all([
context.jio.put("3", {a: "ab43", b: 9, c: "absorb"}),
context.jio.put("5", {a: "gu31", b: 5, c: "control"}),
context.jio.put("7", {a: "zf76", b: 3, c: "rules"}),
context.jio.put("6", {a: "cc92", b: 6, c: "afraid"})
])
.then(function () {
return context.jio.allDocs({query: 'c:"control"'});
})
.then(function (result) {
equal(result.data.total_rows, 2);
deepEqual(result.data.rows.sort(idCompare), [{id: "5", value: {}},
{id: "9", value: {}}]);
})
.fail(function (error) {
console.log(error);
})
.always(function () {
start();
});
});
test("Repair on storage with include_docs support", function () {
var context = this, fake_data;
context.jio = jIO.createJIO({
type: "index2",
database: "index2_test",
index_keys: ["a", "c"],
sub_storage: {
type: "dummystorage3"
}
});
stop();
expect(3);
fake_data = [
{id: "1", doc: {a: "id54", b: 2, c: "night"}},
{id: "4", doc: {a: "vn92", b: 7, c: "matter"}},
{id: "9", doc: {a: "ru23", b: 3, c: "control"}}
];
DummyStorage3.prototype.put = function (id, value) {
fake_data.push({id: id, doc: value});
return id;
};
DummyStorage3.prototype.buildQuery = function (options) {
deepEqual(options, {include_docs: true});
return fake_data;
return keys.map(function (v) { return {id: v, value: {id: v}}; });
};
RSVP.all([
......@@ -694,18 +651,23 @@
expect(8);
dummy_data = {
"32": {id: "32", doc: {"a": "3", "b": "2", "c": "inverse"}},
"5": {id: "5", doc: {"a": "6", "b": "2", "c": "strong"}},
"14": {id: "14", doc: {"a": "67", "b": "3", "c": "disolve"}}
"32": {id: "32", doc: {"a": "3", "b": "2", "c": "inverse"},
value: {"a": "3", "b": "2", "c": "inverse"}},
"5": {id: "5", doc: {"a": "6", "b": "2", "c": "strong"},
value: {"a": "6", "b": "2", "c": "strong"}},
"14": {id: "14", doc: {"a": "67", "b": "3", "c": "disolve"},
value: {"a": "67", "b": "3", "c": "disolve"}}
};
DummyStorage3.prototype.put = function (id, value) {
dummy_data[id] = {id: id, doc: value};
dummy_data[id] = {id: id, doc: value, value: value};
return id;
};
DummyStorage3.prototype.get = function (id) {
return dummy_data[id].doc;
};
DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include');
return (name === 'list') || (name === 'include') || (name === 'select');
};
DummyStorage3.prototype.buildQuery = function () {
......@@ -802,6 +764,31 @@
});
});
test("Repair fails", function () {
var context = this;
context.jio = jIO.createJIO({
type: "index2",
database: "index2_test",
index_keys: ["a", "c"],
sub_storage: {
type: "dummystorage3"
}
});
stop();
expect(1);
DummyStorage3.prototype.buildQuery = undefined;
context.jio.allDocs({query: 'c: "control"'})
.fail(function (error) {
equal(error.message, "Version change transaction was aborted in" +
" upgradeneeded event handler.");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// IndexStorage2.getAttachment
/////////////////////////////////////////////////////////////////
......@@ -948,7 +935,7 @@
};
DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include');
return (name === 'list') || (name === 'include') || (name === 'select');
};
DummyStorage3.prototype.buildQuery = function () {
......@@ -1040,7 +1027,7 @@
};
DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include');
return (name === 'list') || (name === 'include') || (name === 'select');
};
DummyStorage3.prototype.buildQuery = function () {
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!