Commit 332a13ba authored by Romain Courteaud's avatar Romain Courteaud

Release version 3.40.0

Fix indexedDB getAttachment
parent eeead6da
......@@ -26,7 +26,7 @@ TESTDIR = test
EXAMPLEDIR = examples
EXTERNALDIR = external
VERSION = 3.39.0
VERSION = 3.40.0
JIOVERSION = ${DISTDIR}/jio-v${VERSION}.js
JIOLATEST = ${DISTDIR}/jio-latest.js
JIONODEVERSION = ${DISTDIR}/jio-v${VERSION}-node.js
......
......@@ -14890,14 +14890,15 @@ return new Parser;
/*jslint nomen: true */
/*global indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
DOMError, Event*/
DOMError, Set*/
(function (indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
DOMError) {
DOMError, Set) {
"use strict";
// Read only as changing it can lead to data corruption
var UNITE = 2000000;
var UNITE = 2000000,
INDEX_PREFIX = 'doc.';
function IndexedDBStorage(description) {
if (typeof description.database !== "string" ||
......@@ -14906,6 +14907,8 @@ return new Parser;
"must be a non-empty string");
}
this._database_name = "jio:" + description.database;
this._version = description.version;
this._index_key_list = description.index_key_list || [];
}
IndexedDBStorage.prototype.hasCapacity = function (name) {
......@@ -14916,35 +14919,65 @@ return new Parser;
return key_list.join("_");
}
function handleUpgradeNeeded(evt) {
function handleUpgradeNeeded(evt, index_key_list) {
var db = evt.target.result,
store;
store,
current_store_list = Array.from(db.objectStoreNames),
current_index_list,
i,
index_key;
store = db.createObjectStore("metadata", {
keyPath: "_id",
autoIncrement: false
});
// It is not possible to use openKeyCursor on keypath directly
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=19955
store.createIndex("_id", "_id", {unique: true});
if (current_store_list.indexOf("metadata") === -1) {
store = db.createObjectStore("metadata", {
keyPath: "_id",
autoIncrement: false
});
// It is not possible to use openKeyCursor on keypath directly
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=19955
store.createIndex("_id", "_id", {unique: true});
} else {
store = evt.target.transaction.objectStore("metadata");
}
store = db.createObjectStore("attachment", {
keyPath: "_key_path",
autoIncrement: false
});
store.createIndex("_id", "_id", {unique: false});
current_index_list = new Set(store.indexNames);
current_index_list.delete("_id");
for (i = 0; i < index_key_list.length; i += 1) {
// Prefix the index name to prevent conflict with _id
index_key = INDEX_PREFIX + index_key_list[i];
if (current_index_list.has(index_key)) {
current_index_list.delete(index_key);
} else {
store.createIndex(index_key, index_key,
{unique: false});
}
}
current_index_list = Array.from(current_index_list);
for (i = 0; i < current_index_list.length; i += 1) {
store.deleteIndex(current_index_list[i]);
}
store = db.createObjectStore("blob", {
keyPath: "_key_path",
autoIncrement: false
});
store.createIndex("_id_attachment",
["_id", "_attachment"], {unique: false});
store.createIndex("_id", "_id", {unique: false});
if (current_store_list.indexOf("attachment") === -1) {
store = db.createObjectStore("attachment", {
keyPath: "_key_path",
autoIncrement: false
});
store.createIndex("_id", "_id", {unique: false});
}
if (current_store_list.indexOf("blob") === -1) {
store = db.createObjectStore("blob", {
keyPath: "_key_path",
autoIncrement: false
});
store.createIndex("_id_attachment",
["_id", "_attachment"], {unique: false});
store.createIndex("_id", "_id", {unique: false});
}
}
function waitForOpenIndexedDB(db_name, callback) {
var request;
function waitForOpenIndexedDB(storage, callback) {
var request,
db_name = storage._database_name;
function canceller() {
if ((request !== undefined) && (request.result !== undefined)) {
......@@ -14954,7 +14987,7 @@ return new Parser;
function resolver(resolve, reject) {
// Open DB //
request = indexedDB.open(db_name);
request = indexedDB.open(db_name, storage._version);
request.onerror = function (error) {
canceller();
if ((error !== undefined) &&
......@@ -14982,7 +15015,9 @@ return new Parser;
};
// Create DB if necessary //
request.onupgradeneeded = handleUpgradeNeeded;
request.onupgradeneeded = function (evt) {
handleUpgradeNeeded(evt, storage._index_key_list);
};
request.onversionchange = function () {
canceller();
......@@ -15086,7 +15121,7 @@ return new Parser;
function pushIncludedMetadata(cursor) {
result_list.push({
"id": cursor.key,
"id": cursor.primaryKey,
"value": {},
"doc": cursor.value.doc
});
......@@ -15094,24 +15129,25 @@ return new Parser;
function pushMetadata(cursor) {
result_list.push({
"id": cursor.key,
"id": cursor.primaryKey,
"value": {}
});
}
return new RSVP.Queue()
.push(function () {
return waitForOpenIndexedDB(context._database_name, function (db) {
return waitForOpenIndexedDB(context, function (db) {
return waitForTransaction(db, ["metadata"], "readonly",
function (tx) {
var key = "_id";
if (options.include_docs === true) {
return waitForAllSynchronousCursor(
tx.objectStore("metadata").index("_id").openCursor(),
tx.objectStore("metadata").index(key).openCursor(),
pushIncludedMetadata
);
}
return waitForAllSynchronousCursor(
tx.objectStore("metadata").index("_id").openKeyCursor(),
tx.objectStore("metadata").index(key).openKeyCursor(),
pushMetadata
);
});
......@@ -15126,7 +15162,7 @@ return new Parser;
var context = this;
return new RSVP.Queue()
.push(function () {
return waitForOpenIndexedDB(context._database_name, function (db) {
return waitForOpenIndexedDB(context, function (db) {
return waitForTransaction(db, ["metadata"], "readonly",
function (tx) {
return waitForIDBRequest(tx.objectStore("metadata").get(id));
......@@ -15154,7 +15190,7 @@ return new Parser;
return new RSVP.Queue()
.push(function () {
return waitForOpenIndexedDB(context._database_name, function (db) {
return waitForOpenIndexedDB(context, function (db) {
return waitForTransaction(db, ["metadata", "attachment"], "readonly",
function (tx) {
return RSVP.all([
......@@ -15183,7 +15219,7 @@ return new Parser;
};
IndexedDBStorage.prototype.put = function (id, metadata) {
return waitForOpenIndexedDB(this._database_name, function (db) {
return waitForOpenIndexedDB(this, function (db) {
return waitForTransaction(db, ["metadata"], "readwrite",
function (tx) {
return waitForIDBRequest(tx.objectStore("metadata").put({
......@@ -15195,7 +15231,7 @@ return new Parser;
};
IndexedDBStorage.prototype.remove = function (id) {
return waitForOpenIndexedDB(this._database_name, function (db) {
return waitForOpenIndexedDB(this, function (db) {
return waitForTransaction(db, ["metadata", "attachment", "blob"],
"readwrite", function (tx) {
......@@ -15239,10 +15275,10 @@ return new Parser;
if (options === undefined) {
options = {};
}
var db_name = this._database_name,
start,
var start,
end,
array_buffer_list = [];
array_buffer_list = [],
context = this;
start = options.start || 0;
end = options.end;
......@@ -15263,7 +15299,7 @@ return new Parser;
return new RSVP.Queue()
.push(function () {
return waitForOpenIndexedDB(db_name, function (db) {
return waitForOpenIndexedDB(context, function (db) {
return waitForTransaction(db, ["blob"], "readonly",
function (tx) {
var key_path = buildKeyPath([id, name]),
......@@ -15285,8 +15321,7 @@ return new Parser;
var index = parseInt(
cursor.primaryKey.slice(key_path.length + 1),
10
),
i;
);
if ((start !== 0) && (index < start_index)) {
// No need to fetch blobs at the start
......@@ -15297,12 +15332,6 @@ return new Parser;
return;
}
i = index - start_index;
// Extend array size
while (i > promise_list.length) {
promise_list.push(null);
i -= 1;
}
// Sort the blob by their index
promise_list.splice(
index - start_index,
......@@ -15336,7 +15365,7 @@ return new Parser;
{type: "application/octet-stream"});
index = Math.floor(start / UNITE) * UNITE;
if (end === undefined) {
end = blob.length;
end = blob.size;
} else {
end = end - index;
}
......@@ -15348,7 +15377,7 @@ return new Parser;
// Request the full blob
return new RSVP.Queue()
.push(function () {
return waitForOpenIndexedDB(db_name, function (db) {
return waitForOpenIndexedDB(context, function (db) {
return waitForTransaction(db, ["attachment", "blob"], "readonly",
function (tx) {
var key_path = buildKeyPath([id, name]),
......@@ -15359,13 +15388,8 @@ return new Parser;
var index = parseInt(
cursor.primaryKey.slice(key_path.length + 1),
10
),
i = index;
// Extend array size
while (i > array_buffer_list.length) {
array_buffer_list.push(null);
i -= 1;
}
);
// Sort the blob by their index
array_buffer_list.splice(
index,
......@@ -15407,7 +15431,7 @@ return new Parser;
blob = new Blob(array_buffer_list,
{type: attachment.info.content_type});
if (blob.length !== attachment.info.total_length) {
if (blob.size !== attachment.info.length) {
throw new jIO.util.jIOError(
"IndexedDB: attachment '" +
buildKeyPath([id, name]) +
......@@ -15420,7 +15444,7 @@ return new Parser;
};
IndexedDBStorage.prototype.putAttachment = function (id, name, blob) {
var db_name = this._database_name;
var context = this;
return new RSVP.Queue()
.push(function () {
// Split the blob first
......@@ -15438,7 +15462,7 @@ return new Parser;
handled_size += UNITE;
}
return waitForOpenIndexedDB(db_name, function (db) {
return waitForOpenIndexedDB(context, function (db) {
return waitForTransaction(db, ["attachment", "blob"], "readwrite",
function (tx) {
var blob_store,
......@@ -15505,7 +15529,7 @@ return new Parser;
};
IndexedDBStorage.prototype.removeAttachment = function (id, name) {
return waitForOpenIndexedDB(this._database_name, function (db) {
return waitForOpenIndexedDB(this, function (db) {
return waitForTransaction(db, ["attachment", "blob"], "readwrite",
function (tx) {
var promise_list = [],
......@@ -15537,7 +15561,8 @@ return new Parser;
};
jIO.addStorage("indexeddb", IndexedDBStorage);
}(indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest, DOMError));
}(indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest, DOMError,
Set));
/*
* Copyright 2015, Nexedi SA
*
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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