Commit 3cfc4665 authored by Tristan Cavelier's avatar Tristan Cavelier

Merge branch 'splitstorage'

parents 9d099782 bf4d0443
...@@ -162,6 +162,8 @@ var clearlog = function () { ...@@ -162,6 +162,8 @@ var clearlog = function () {
<script type="text/javascript" src="../lib/jsSha2/sha2.js"></script> <script type="text/javascript" src="../lib/jsSha2/sha2.js"></script>
<script type="text/javascript" src="../src/jio.storage/revisionstorage.js"> <script type="text/javascript" src="../src/jio.storage/revisionstorage.js">
</script> </script>
<script type="text/javascript" src="../src/jio.storage/splitstorage.js">
</script>
<script type="text/javascript" src="../lib/sjcl/sjcl.min.js"></script> <script type="text/javascript" src="../lib/sjcl/sjcl.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
......
/*
* Copyright 2013, Nexedi SA
* Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html
*/
/*jslint indent:2, maxlen: 80, nomen: true */
/*global jIO: true, exports: true, define: true */
/**
* Provides a split storage for JIO. This storage splits data
* and store them in the sub storages defined on the description.
*
* {
* "type": "split",
* "storage_list": [<storage description>, ...]
* }
*/
(function () {
"use strict";
var queries;
/**
* Get the real type of an object
*
* @param {Any} value The value to check
* @return {String} The value type
*/
function type(value) {
// returns "String", "Object", "Array", "RegExp", ...
return (/^\[object ([a-zA-Z]+)\]$/).exec(
Object.prototype.toString.call(value)
)[1];
}
/**
* Generate a new uuid
*
* @method generateUuid
* @private
* @return {String} The new uuid
*/
function generateUuid() {
function S4() {
/* 65536 */
var i, string = Math.floor(
Math.random() * 0x10000
).toString(16);
for (i = string.length; i < 4; i += 1) {
string = '0' + string;
}
return string;
}
return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() +
S4() + S4();
}
/**
* Class to merge allDocs responses from several sub storages.
*
* @class AllDocsResponseMerger
* @constructor
*/
function AllDocsResponseMerger() {
/**
* A list of allDocs response.
*
* @attribute response_list
* @type {Array} Contains allDocs responses
* @default []
*/
this.response_list = [];
}
AllDocsResponseMerger.prototype.constructor = AllDocsResponseMerger;
/**
* Add an allDocs response to the response list.
*
* @method addResponse
* @param {Object} response The allDocs response.
* @return {AllDocsResponseMerger} This
*/
AllDocsResponseMerger.prototype.addResponse = function (response) {
this.response_list.push(response);
return this;
};
/**
* Add several allDocs responses to the response list.
*
* @method addResponseList
* @param {Array} response_list An array of allDocs responses.
* @return {AllDocsResponseMerger} This
*/
AllDocsResponseMerger.prototype.addResponseList = function (response_list) {
var i;
for (i = 0; i < response_list.length; i += 1) {
this.response_list.push(response_list[i]);
}
return this;
};
/**
* Merge the response_list to one allDocs response.
*
* The merger will find rows with the same id in order to merge them, thanks
* to the onRowToMerge method. If no row correspond to an id, rows with the
* same id will be ignored.
*
* @method merge
* @param {Object} [option={}] The merge options
* @param {Boolean} [option.include_docs=false] Tell the merger to also
* merge metadata if true.
* @return {Object} The merged allDocs response.
*/
AllDocsResponseMerger.prototype.merge = function (option) {
var result = [], row, to_merge = [], tmp, i;
if (this.response_list.length === 0) {
return [];
}
while ((row = this.response_list[0].rows.shift()) !== undefined) {
console.log('row', row);
to_merge[0] = row;
for (i = 1; i < this.response_list.length; i += 1) {
to_merge[i] = AllDocsResponseMerger.listPopFromRowId(
this.response_list[i].rows,
row.id
);
if (to_merge[i] === undefined) {
break;
}
}
console.log('to merge', to_merge);
tmp = this.onRowToMerge(to_merge, option || {});
if (tmp !== undefined) {
result[result.length] = tmp;
}
}
this.response_list = [];
return {"total_rows": result.length, "rows": result};
};
/**
* This method is called when the merger want to merge several rows with the
* same id.
*
* @method onRowToMerge
* @param {Array} row_list An array of rows.
* @param {Object} [option={}] The merge option.
* @param {Boolean} [option.include_docs=false] Also merge the metadata if
* true
* @return {Object} The merged row
*/
AllDocsResponseMerger.prototype.onRowToMerge = function (row_list, option) {
var i, k, new_row = {"value": {}}, data = "";
option = option || {};
for (i = 0; i < row_list.length; i += 1) {
new_row.id = row_list[i].id;
if (row_list[i].key) {
new_row.key = row_list[i].key;
}
if (option.include_docs) {
new_row.doc = new_row.doc || {};
for (k in row_list[i].doc) {
if (row_list[i].doc.hasOwnProperty(k)) {
if (k[0] === "_") {
new_row.doc[k] = row_list[i].doc[k];
}
}
}
data += row_list[i].doc.data;
}
}
if (option.include_docs) {
try {
data = JSON.parse(data);
} catch (e) { return undefined; }
for (k in data) {
if (data.hasOwnProperty(k)) {
new_row.doc[k] = data[k];
}
}
}
return new_row;
};
/**
* Search for a specific row and pop it. During the search operation, all
* parsed rows are stored on a dictionnary in order to be found instantly
* later.
*
* @method listPopFromRowId
* @param {Array} rows The row list
* @param {String} doc_id The document/row id
* @return {Object/undefined} The poped row
*/
AllDocsResponseMerger.listPopFromRowId = function (rows, doc_id) {
var row;
if (!rows.dict) {
rows.dict = {};
}
if (rows.dict[doc_id]) {
row = rows.dict[doc_id];
delete rows.dict[doc_id];
return row;
}
while ((row = rows.shift()) !== undefined) {
if (row.id === doc_id) {
return row;
}
rows.dict[row.id] = row;
}
};
/**
* The split storage class used by JIO.
*
* A split storage instance is able to i/o on several sub storages with
* split documents.
*
* @class splitStorage
*/
function splitStorage(spec, my) {
var that = my.basicStorage(spec, my), priv = {};
/**
* The list of sub storages we want to use to store part of documents.
*
* @attribute storage_list
* @private
* @type {Array} Array of storage descriptions
*/
priv.storage_list = spec.storage_list;
//////////////////////////////////////////////////////////////////////
// Overrides
/**
* Overrides the original {{#crossLink "storage/specToStore:method"}}
* specToStore method{{/crossLink}}.
*
* @method specToStore
* @return {Object} The specificities to store
*/
that.specToStore = function () {
return {"storage_list": priv.storage_list};
};
/**
* TODO validateState
*/
//////////////////////////////////////////////////////////////////////
// Tools
/**
* Send a command to all sub storages. All the response are returned
* in a list. The index of the response correspond to the storage_list
* index. If an error occurs during operation, the callback is called with
* `callback(err, undefined)`. The response is given with
* `callback(undefined, response_list)`.
*
* `doc` is the document informations but can also be a list of dedicated
* document informations. In this case, each document is associated to one
* sub storage.
*
* @method send
* @private
* @param {String} method The command method
* @param {Object,Array} doc The document information to send to each sub
* storages or a list of dedicated document
* @param {Object} option The command option
* @param {Function} callback Called at the end
*/
priv.send = function (method, doc, option, callback) {
var i, answer_list = [], failed = false;
function onEnd() {
i += 1;
if (i === priv.storage_list.length) {
callback(undefined, answer_list);
}
}
function onSuccess(i) {
return function (response) {
if (!failed) {
answer_list[i] = response;
}
onEnd();
};
}
function onError(i) {
return function (err) {
if (!failed) {
failed = true;
err.index = i;
callback(err, undefined);
}
};
}
if (type(doc) !== "Array") {
for (i = 0; i < priv.storage_list.length; i += 1) {
that.addJob(
method,
priv.storage_list[i],
doc,
option,
onSuccess(i),
onError(i)
);
}
} else {
for (i = 0; i < priv.storage_list.length; i += 1) {
that.addJob(
method,
priv.storage_list[i],
doc[i],
option,
onSuccess(i),
onError(i)
);
}
}
i = 0;
};
/**
* Split document metadata then store them to the sub storages.
*
* @method postOrPut
* @private
* @param {Object} doc A serialized document object
* @param {Object} option Command option properties
* @param {String} method The command method ('post' or 'put')
*/
priv.postOrPut = function (doc, option, method) {
var i, data, doc_list = [], doc_underscores = {};
if (!doc._id) {
doc._id = generateUuid();
}
for (i in doc) {
if (doc.hasOwnProperty(i)) {
if (i[0] === "_") {
doc_underscores[i] = doc[i];
delete doc[i];
}
}
}
data = JSON.stringify(doc);
for (i = 0; i < priv.storage_list.length; i += 1) {
doc_list[i] = JSON.parse(JSON.stringify(doc_underscores));
doc_list[i].data = data.slice(
(data.length / priv.storage_list.length) * i,
(data.length / priv.storage_list.length) * (i + 1)
);
}
priv.send(method, doc_list, option, function (err, response) {
if (err) {
err.message = "Unable to " + method + " document";
delete err.index;
return that.error(err);
}
that.success({"ok": true, "id": doc_underscores._id});
});
};
//////////////////////////////////////////////////////////////////////
// JIO commands
/**
* Split document metadata then store them to the sub storages.
*
* @method post
* @param {Command} command The JIO command
*/
that.post = function (command) {
priv.postOrPut(command.cloneDoc(), command.cloneOption(), 'post');
};
/**
* Split document metadata then store them to the sub storages.
*
* @method put
* @param {Command} command The JIO command
*/
that.put = function (command) {
priv.postOrPut(command.cloneDoc(), command.cloneOption(), 'put');
};
/**
* Puts an attachment to the sub storages.
*
* @method putAttachment
* @param {Command} command The JIO command
*/
that.putAttachment = function (command) {
var i, attachment_list = [], data = command.getAttachmentData();
for (i = 0; i < priv.storage_list.length; i += 1) {
attachment_list[i] = command.cloneDoc();
attachment_list[i]._data = data.slice(
(data.length / priv.storage_list.length) * i,
(data.length / priv.storage_list.length) * (i + 1)
);
}
priv.send(
'putAttachment',
attachment_list,
command.cloneOption(),
function (err, response) {
if (err) {
err.message = "Unable to put attachment";
delete err.index;
return that.error(err);
}
that.success({
"ok": true,
"id": command.getDocId(),
"attachment": command.getAttachmentId()
});
}
);
};
/**
* Gets splited document metadata then returns real document.
*
* @method get
* @param {Command} command The JIO command
*/
that.get = function (command) {
var doc, option, data, attachments;
doc = command.cloneDoc();
option = command.cloneOption();
priv.send('get', doc, option, function (err, response) {
var i, k;
if (err) {
err.message = "Unable to get document";
delete err.index;
return that.error(err);
}
doc = '';
for (i = 0; i < response.length; i += 1) {
doc += response[i].data;
}
doc = JSON.parse(doc);
for (i = 0; i < response.length; i += 1) {
for (k in response[i]) {
if (response[i].hasOwnProperty(k)) {
if (k[0] === "_") {
doc[k] = response[i][k];
}
}
}
}
delete doc._attachments;
for (i = 0; i < response.length; i += 1) {
if (response[i]._attachments) {
for (k in response[i]._attachments) {
if (response[i]._attachments.hasOwnProperty(k)) {
doc._attachments = doc._attachments || {};
doc._attachments[k] = doc._attachments[k] || {
"length": 0,
"content_type": ""
};
doc._attachments[k].length += response[i]._attachments[k].
length;
// if (response[i]._attachments[k].digest) {
// if (doc._attachments[k].digest) {
// doc._attachments[k].digest += " " + response[i].
// _attachments[k].digest;
// } else {
// doc._attachments[k].digest = response[i].
// _attachments[k].digest;
// }
// }
doc._attachments[k].content_type = response[i]._attachments[k].
content_type;
}
}
}
}
doc._id = command.getDocId();
that.success(doc);
});
};
/**
* Gets splited document attachment then returns real attachment data.
*
* @method getAttachment
* @param {Command} command The JIO command
*/
that.getAttachment = function (command) {
var doc, option;
doc = command.cloneDoc();
option = command.cloneOption();
priv.send('getAttachment', doc, option, function (err, response) {
var i, k;
if (err) {
err.message = "Unable to get attachment";
delete err.index;
return that.error(err);
}
doc = '';
for (i = 0; i < response.length; i += 1) {
doc += response[i];
}
that.success(doc);
});
};
/**
* Removes a document from the sub storages.
*
* @method remove
* @param {Command} command The JIO command
*/
that.remove = function (command) {
priv.send(
'remove',
command.cloneDoc(),
command.cloneOption(),
function (err, response_list) {
if (err) {
err.message = "Unable to remove document";
delete err.index;
return that.error(err);
}
that.success({"id": command.getDocId(), "ok": true});
}
);
};
/**
* Removes an attachment from the sub storages.
*
* @method removeAttachment
* @param {Command} command The JIO command
*/
that.removeAttachment = function (command) {
var doc = command.cloneDoc();
priv.send(
'removeAttachment',
doc,
command.cloneOption(),
function (err, response_list) {
if (err) {
err.message = "Unable to remove attachment";
delete err.index;
return that.error(err);
}
that.success({
"id": doc._id,
"attachment": doc._attachment,
"ok": true
});
}
);
};
/**
* Retreive a list of all document in the sub storages.
*
* If include_docs option is false, then it returns the document list from
* the first sub storage. Else, it will merge results and return.
*
* @method allDocs
* @param {Command} command The JIO command
*/
that.allDocs = function (command) {
var option = command.cloneOption();
option = {"include_docs": option.include_docs};
priv.send(
'allDocs',
command.cloneDoc(),
option,
function (err, response_list) {
var all_docs_merger;
if (err) {
err.message = "Unable to retrieve document list";
delete err.index;
return that.error(err);
}
all_docs_merger = new AllDocsResponseMerger();
all_docs_merger.addResponseList(response_list);
return that.success(all_docs_merger.merge(option));
}
);
};
return that;
} // end of splitStorage
//////////////////////////////
// exports to JIO
if (typeof define === "function" && define.amd) {
define(['jio'], function (jio) {
try {
queries = require('complex_queries');
} catch (e) {}
jio.addStorageType('split', splitStorage);
});
} else if (typeof require === "function") {
require('jio').addStorageType('split', splitStorage);
} else if (typeof jIO === "object") {
jIO.addStorageType('split', splitStorage);
} else {
throw new Error("Unable to export splitStorage to JIO.");
}
}());
...@@ -7347,6 +7347,493 @@ test ("XWiki Live Server setup", function () { ...@@ -7347,6 +7347,493 @@ test ("XWiki Live Server setup", function () {
})(); // xwiki })(); // xwiki
module("SplitStorage + LocalStorage");
test("Post", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "post1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "post2"
}]
});
// post without id
o.spy(o, "jobstatus", "done", "Post document without id");
o.jio.post({
"_underscored_meta": "uvalue",
"meta": "data"
}, function (err, response) {
o.f(err, response);
o.uuid = (err || response).id;
ok(isUuid(o.uuid), "Uuid should look like " +
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx : " + o.uuid);
});
o.tick(o);
// check uploaded documents
deepEqual(
localstorage.getItem('jio/localstorage/splitstorage/post1/' + o.uuid),
{"_id": o.uuid, "_underscored_meta": "uvalue", "data": "{\"meta\""},
"Check uploaded document in sub storage 1"
);
deepEqual(
localstorage.getItem('jio/localstorage/splitstorage/post2/' + o.uuid),
{"_id": o.uuid, "_underscored_meta": "uvalue", "data": ":\"data\"}"},
"Check uploaded document in sub storage 2"
);
// post with id
o.spy(o, "value", {"ok": true, "id": "one"}, "Post document with id");
o.jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"hello": "world"
}, o.f);
o.tick(o);
// check uploaded documents
deepEqual(localstorage.getItem('jio/localstorage/splitstorage/post1/one'), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "{\"meta\":\"data\","
}, "Check uploaded document in sub storage 1");
deepEqual(localstorage.getItem('jio/localstorage/splitstorage/post2/one'), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "\"hello\":\"world\"}"
}, "Check uploaded document in sub storage 2");
// post with id
o.spy(o, "status", 409, "Post document with same id");
o.jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"hello": "world"
}, o.f);
o.tick(o);
o.jio.stop();
});
test("PutAttachment", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "putAttachment1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "putAttachment2"
}]
});
o.spy(o, "status", 404, "Put attachment on a inexistent document");
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
}, o.f);
o.tick(o);
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
o.spy(o, "value", {
"ok": true,
"id": "one",
"attachment": "my_attachment"
}, "Put attachment");
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
}, o.f);
o.tick(o);
// check uploaded documents
deepEqual(localstorage.getItem(
'jio/localstorage/splitstorage/putAttachment1/one'
), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "{\"meta\"",
"_attachments": {
"my_attachment": {
"length": 3,
"digest": "md5-1b4686bc8ca15befdccb1da1dcb8c271", // md5("My ")
"content_type": "text/plain"
}
}
}, "Check uploaded document in sub storage 1");
deepEqual(localstorage.getItem(
'jio/localstorage/splitstorage/putAttachment2/one'
), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": ":\"data\"}",
"_attachments": {
"my_attachment": {
"length": 4,
"digest": "md5-f6068daa29dbb05a7ead1e3b5a48bbee", // md5("Data")
"content_type": "text/plain"
}
}
}, "Check uploaded document in sub storage 2");
deepEqual(localstorage.getItem(
'jio/localstorage/splitstorage/putAttachment1/one/my_attachment'
), "My ", "Check uploaded document in sub storage 1");
deepEqual(localstorage.getItem(
'jio/localstorage/splitstorage/putAttachment2/one/my_attachment'
), "Data", "Check uploaded document in sub storage 2");
o.jio.stop();
});
test("Get", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "get1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "get2"
}]
});
o.spy(o, "status", 404, "Get missing document");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Get posted document");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"_attachments": {
"my_attachment": {
"length": 7,
"content_type": "text/plain"
}
}
}, "Get document with attachment informations");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
o.jio.stop();
});
test("GetAttachment", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "getAttachment1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "getAttachment2"
}]
});
o.spy(o, "status", 404, "Get attachment from missing document");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
o.spy(o, "status", 404, "Get missing attachment from document");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
o.spy(o, "value", "My Data", "Get attachment");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.jio.stop();
});
test("removeAttachment", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "removeAttachment1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "removeAttachment2"
}]
});
o.spy(o, "status", 404, "Remove attachment from inexistent document");
o.jio.removeAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
o.spy(o, "status", 404, "Remove inexistent attachment");
o.jio.removeAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
o.spy(o, "value", {
"ok": true,
"id": "one",
"attachment": "my_attachment"
}, "Remove attachment");
o.jio.removeAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
o.spy(o, "status", 404, "Get attachment for check");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.jio.stop();
});
test("remove", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "remove1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "remove2"
}]
});
o.spy(o, "status", 404, "Remove missing document");
o.jio.remove({"_id": "one"}, o.f);
o.tick(o);
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
o.spy(o, "value", {"ok": true, "id": "one"}, "Remove document");
o.jio.remove({"_id": "one"}, o.f);
o.tick(o);
o.spy(o, "status", 404, "Get attachment for check");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
o.spy(o, "status", 404, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
o.jio.stop();
});
test("Put", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "put1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "put2"
}]
});
o.spy(o, "value", {"ok": true, "id": "one"}, "Put document");
o.jio.put({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"}, o.f);
o.tick(o)
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
o.spy(o, "value", {"ok": true, "id": "one"}, "Put document again");
o.jio.put({"_id": "one", "_underscored_meta": "uvalue", "meow": "dog"}, o.f);
o.tick(o)
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meow": "dog"
}, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
o.jio.stop();
});
test("AllDocs", function () {
var o = generateTools(this);
o.jio = JIO.newJio({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "alldocs1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "alldocs2"
}]
});
for (o.i = 0; o.i < 5; o.i += 1) {
o.jio.post({
"_id": "doc" + o.i,
"_underscored_meta": "uvalue" + o.i,
"meta": "data" + o.i
});
o.clock.tick(1000);
}
for (o.i = 0; o.i < 2; o.i += 1) {
o.jio.putAttachment({
"_id": "doc" + o.i,
"_attachment": "my_attachment" + o.i,
"_data": "My Data" + o.i,
"_mimetype": "text/plain"
});
o.clock.tick(1000);
}
o.spy(o, "value", {
"_id": "doc1",
"_underscored_meta": "uvalue1",
"meta": "data1",
"_attachments": {
"my_attachment1": {
"length": 8,
"content_type": "text/plain"
}
}
}, "Get document for check");
o.jio.get({"_id": "doc1"}, o.f);
o.tick(o);
o.spy(o, "value", {
"total_rows": 5,
"rows": [{
"id": "doc0",
"key": "doc0",
"value": {}
}, {
"id": "doc1",
"key": "doc1",
"value": {}
}, {
"id": "doc2",
"key": "doc2",
"value": {}
}, {
"id": "doc3",
"key": "doc3",
"value": {}
}, {
"id": "doc4",
"key": "doc4",
"value": {}
}]
}, "AllDocs with document ids only");
o.jio.allDocs(function (err, response) {
if (response && Array.isArray(response.rows)) {
response.rows.sort(function (a, b) {
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
});
}
o.f(err, response);
});
o.tick(o);
o.jio.stop();
});
}; // end thisfun }; // end thisfun
if (window.requirejs) { if (window.requirejs) {
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
</script> </script>
<script type="text/javascript" src="../src/jio.storage/s3storage.js"> <script type="text/javascript" src="../src/jio.storage/s3storage.js">
</script> </script>
<script type="text/javascript" src="../src/jio.storage/splitstorage.js">
</script>
<script type="text/javascript" src="./jiotests.js"></script> <script type="text/javascript" src="./jiotests.js"></script>
</body> </body>
</html> </html>
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