Commit d8602cf1 authored by Tristan Cavelier's avatar Tristan Cavelier

indexstorage.js: check & repair + tests

parent 86c22afe
......@@ -98,6 +98,12 @@
"statusText": "Conflicts",
"error": "conflicts",
"reason": "already exist"
},
"Different Index": {
"status": 40,
"statusText": "Check failed",
"error": "check_failed",
"reason": "incomplete database"
}
};
......@@ -279,7 +285,7 @@
};
/**
* Checks if the index document is correct
* Checks if the index database document is correct
*
* @method check
*/
......@@ -305,6 +311,43 @@
}
};
that.equals = function (json_index) {
function equalsDirection(a, b) {
var k;
for (k in a._location) {
if (a._location.hasOwnProperty(k)) {
if (b._location[k] === undefined ||
JSON.stringify(b._database[b._location[k]]) !==
JSON.stringify(a._database[a._location[k]])) {
return false;
}
}
}
return true;
}
if (!equalsDirection(that, json_index)) {
return false;
}
if (!equalsDirection(json_index, that)) {
return false;
}
return true;
};
that.checkDocument = function (doc) {
var i, key, db_doc;
if (typeof that._location[doc._id] !== "number" ||
(db_doc = that._database(that._location[doc._id])._id) !== doc._id) {
throw new TypeError("Different Index");
}
for (i = 0; i < that._indexing.length; i += 1) {
key = that._indexing[i];
if (doc[key] !== db_doc[key]) {
throw new TypeError("Different Index");
}
}
};
/**
* Recreates database indices and remove free space
*
......@@ -679,35 +722,11 @@
};
that.check = function (command) {
todo
var database_index = -1, i;
for (i = 0; i < priv.indices.length; i += 1) {
if (priv.indices[i].id === command.getDocId()) {
database_index = i;
break;
}
}
that.addJob(
"check",
priv.sub_storage,
command.cloneDoc(),
command.cloneOption(),
function (response) {
if (database_index !== -1) {
// check index database
} else {
// regular document
}
},
function (err) {
err.message = "Could not repair sub storage";
that.error(err);
}
);
that.repair(command, true);
};
priv.repairIndexDatabase = function (command, index) {
var i;
priv.repairIndexDatabase = function (command, index, just_check) {
var i, option = command.cloneOption();
that.addJob(
'allDocs',
priv.sub_storage,
......@@ -722,9 +741,22 @@
db.put(response.rows[i].doc);
}
db_list[index] = db;
priv.storeIndexDatabaseList(db_list, {}, function () {
that.success({"ok": true, "_id": command.getDocId()});
});
if (just_check) {
priv.getIndexDatabase(option, index, function (current_db) {
if (db.equals(current_db)) {
return that.success({"ok": true, "_id": command.getDocId()});
}
return that.error(generateErrorObject(
"Different Index",
"Check failed",
"corrupt index database"
));
});
} else {
priv.storeIndexDatabaseList(db_list, {}, function () {
that.success({"ok": true, "_id": command.getDocId()});
});
}
},
function (err) {
err.message = "Unable to repair the index database";
......@@ -733,7 +765,7 @@
);
};
priv.repairDocument = function (command) {
priv.repairDocument = function (command, just_check) {
var i, option = command.cloneOption();
that.addJob(
"get",
......@@ -743,12 +775,27 @@
function (response) {
response._id = command.getDocId();
priv.getIndexDatabaseList(option, function (database_list) {
for (i = 0; i < database_list.length; i += 1) {
database_list[i].put(response);
if (just_check) {
for (i = 0; i < database_list.length; i += 1) {
try {
database_list[i].checkDocument(response);
} catch (e) {
return that.error(generateErrorObject(
e.message,
"Check failed",
"corrupt index database"
));
}
}
that.success({"_id": command.getDocId(), "ok": true});
} else {
for (i = 0; i < database_list.length; i += 1) {
database_list[i].put(response);
}
priv.storeIndexDatabaseList(database_list, option, function () {
that.success({"ok": true, "id": command.getDocId()});
});
}
priv.storeIndexDatabaseList(database_list, option, function () {
that.success({"ok": true, "id": command.getDocId()});
});
});
},
function (err) {
......@@ -758,7 +805,7 @@
);
};
that.repair = function (command) {
that.repair = function (command, just_check) {
var database_index = -1, i;
for (i = 0; i < priv.indices.length; i += 1) {
if (priv.indices[i].id === command.getDocId()) {
......@@ -773,9 +820,9 @@
command.cloneOption(),
function (response) {
if (database_index !== -1) {
priv.repairIndexDatabase(command, database_index);
priv.repairIndexDatabase(command, database_index, just_check);
} else {
priv.repairDocument(command);
priv.repairDocument(command, just_check);
}
},
function (err) {
......
......@@ -4520,7 +4520,7 @@ test ("Put", function(){
o.jio.stop();
});
test("Repair", function () {
test("Check & Repair", function () {
var o = generateTools(this), i;
o.jio = JIO.newJio({
......@@ -4564,6 +4564,14 @@ test("Repair", function () {
}
o.clock.tick(5000);
o.spy(o, "status", 40, "Check database");
o.jio.check({"_id": "A"}, o.f);
o.tick(o);
o.spy(o, "status", 40, "Check database");
o.jio.check({"_id": "B"}, o.f);
o.tick(o);
o.spy(o, "value", {"_id": "A", "ok": true}, "Repair database");
o.jio.repair({"_id": "A"}, o.f);
o.tick(o);
......@@ -4572,8 +4580,16 @@ test("Repair", function () {
o.jio.repair({"_id": "B"}, o.f);
o.tick(o);
o.spy(o, "value", {"_id": "A", "ok": true}, "Check database again");
o.jio.check({"_id": "A"}, o.f);
o.tick(o);
o.spy(o, "value", {"_id": "B", "ok": true}, "Check database again");
o.jio.check({"_id": "B"}, o.f);
o.tick(o);
// check index file
o.spy(o, "value", o.fakeIndexA, "Check index file");
o.spy(o, "value", o.fakeIndexA, "Manually check index file");
o.jio.get({"_id": "A"}, function (err, response) {
if (response) {
delete response.location;
......@@ -4585,7 +4601,7 @@ test("Repair", function () {
});
o.tick(o);
o.spy(o, "value", o.fakeIndexB, "Check index file");
o.spy(o, "value", o.fakeIndexB, "Manually check index file");
o.jio.get({"_id": "B"}, function (err, response) {
if (response) {
delete response.location;
......@@ -4606,12 +4622,20 @@ test("Repair", function () {
o.fakeIndexA.database.unshift({"_id": "blah", "director": "d"});
o.fakeIndexB.database.unshift({"_id": "blah", "year": "y"});
o.spy(o, "status", 40, "Check Document");
o.jio.check({"_id": "blah"}, o.f)
o.tick(o);
o.spy(o, "value", {"id": "blah", "ok": true}, "Repair Document");
o.jio.repair({"_id": "blah"}, o.f)
o.tick(o);
o.spy(o, "value", {"id": "blah", "ok": true}, "Check Document again");
o.jio.repair({"_id": "blah"}, o.f)
o.tick(o);
// check index file
o.spy(o, "value", o.fakeIndexA, "Check index file");
o.spy(o, "value", o.fakeIndexA, "Manually check index file");
o.jio.get({"_id": "A"}, function (err, response) {
if (response) {
delete response.location;
......@@ -4623,7 +4647,7 @@ test("Repair", function () {
});
o.tick(o);
o.spy(o, "value", o.fakeIndexB, "Check index file");
o.spy(o, "value", o.fakeIndexB, "Manually check index file");
o.jio.get({"_id": "B"}, function (err, response) {
if (response) {
delete response.location;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment