ydn.db
Version:
Javascript database library for IndexedDB, WebDatabase (WebSQL) and WebStorage (localStorage) storage mechanisms supporting version migration, advanced query and transaction workflow.
260 lines (216 loc) • 6.42 kB
JavaScript
// Copyright 2012 YDN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Transaction thread.
*
* @author kyawtun@yathit.com (Kyaw Tun)
*/
goog.provide('ydn.db.tr.Thread');
goog.provide('ydn.db.tr.Thread.Policy');
goog.require('ydn.db.Request');
goog.require('goog.log');
/**
* Create transaction queue providing methods to run in non-overlapping
* transactions.
*
* @param {!ydn.db.tr.Storage} storage base storage.
* @param {number} ptx_no transaction queue number.
* @param {ydn.db.tr.Thread.Policy=} opt_policy
* @param {!Array.<string>=} opt_store_names store names as scope.
* @param {ydn.db.base.TransactionMode=} opt_mode mode as scope.
* @param {number=} opt_max_tx_no limit number of transaction created.
* @constructor
* @struct
*/
ydn.db.tr.Thread = function(storage, ptx_no, opt_policy,
opt_store_names, opt_mode, opt_max_tx_no) {
/**
* @final
* @type {!ydn.db.tr.Storage}
* @private
*/
this.storage_ = storage;
/**
* Transaction thread number.
* @final
*/
this.q_no_ = ptx_no;
/**
* Transaction number, increase one as a transaction created from this thread.
* @type {number}
*/
this.tx_no_ = 0;
/**
* Request number, increase one as a request created from this thread. Reset
* to 0 on each transaction.
* @type {number}
*/
this.r_no_ = 0;
/**
* @final
* @protected
*/
this.scope_store_names = opt_store_names;
/**
* @final
* @protected
*/
this.scope_mode = opt_mode;
/**
* @final
* @protected
* @type {ydn.db.tr.Thread.Policy}
*/
this.policy = opt_policy || ydn.db.tr.Thread.Policy.SINGLE;
/**
* @final
* @protected
* @type {number}
*/
this.max_tx_no = opt_max_tx_no || 0;
/**
* Set break the active transaction by commit method.
* @type {boolean}
* @private
*/
this.break_tx_ = false;
/**
* @type {number}
* @private
*/
this.yield_no_ = 0;
};
/**
* @protected
* @type {goog.debug.Logger} logger.
*/
ydn.db.tr.Thread.prototype.logger = goog.log.getLogger('ydn.db.tr.Thread');
/**
* Create an request.
* @param {ydn.db.Request.Method} method request method.
* @param {!Array.<string>} store_names store name involved in the transaction.
* @param {ydn.db.base.TransactionMode=} opt_mode mode, default to 'readonly'.
* @param {function(ydn.db.base.TxEventTypes, *)=} opt_oncompleted handler.
* @return {!ydn.db.Request}
*/
ydn.db.tr.Thread.prototype.request = goog.abstractMethod;
/**
* @param {!goog.async.Deferred} df deferred object to intersect the request.
* @param {?function((ydn.db.base.Transaction),
* string, ?function(*, boolean=))} callback
* callback when executor is ready.
* @param {!Array.<string>} store_names store name involved in the transaction.
* @param {ydn.db.base.TransactionMode} mode mode, default to 'readonly'.
* @param {function(ydn.db.base.TxEventTypes, *)=} opt_oncompleted handler.
*/
ydn.db.tr.Thread.prototype.exec = goog.abstractMethod;
/**
* Abort an active transaction.
*/
ydn.db.tr.Thread.prototype.abort = goog.abstractMethod;
/**
*
* @return {number} transaction count.
*/
ydn.db.tr.Thread.prototype.getTxNo = function() {
return this.tx_no_;
};
/**
*
* @return {string|undefined} mechansim type.
*/
ydn.db.tr.Thread.prototype.type = function() {
return this.storage_.getType();
};
/**
*
* @return {number} transaction queue number.
*/
ydn.db.tr.Thread.prototype.getQueueNo = function() {
return this.q_no_;
};
/**
* Add or update a store issuing a version change event.
* @protected
* @param {!StoreSchema|!ydn.db.schema.Store} store schema.
* @return {!goog.async.Deferred} promise.
*/
ydn.db.tr.Thread.prototype.addStoreSchema = function(store) {
return this.storage_.addStoreSchema(store);
};
/**
* @protected
* @return {!ydn.db.tr.Storage} storage.
*/
ydn.db.tr.Thread.prototype.getStorage = function() {
return this.storage_;
};
/**
*
* @return {string} label.
*/
ydn.db.tr.Thread.prototype.getLabel = function() {
return 'B' + this.q_no_ + 'T' + this.tx_no_;
};
/**
* Create a new isolated transaction. After creating a transaction, use
* {@link #getTx} to received an active transaction. If transaction is not
* active, it return null. In this case a new transaction must re-create.
* @param {Function} trFn function that invoke in the transaction.
* @param {!Array.<string>} store_names list of keys or
* store name involved in the transaction.
* @param {ydn.db.base.TransactionMode=} opt_mode mode, default to 'readonly'.
* @param {function(ydn.db.base.TxEventTypes, *)=} opt_oncompleted handler.
*/
ydn.db.tr.Thread.prototype.processTx = goog.abstractMethod;
/**
* Request type.
* @enum {string}
*/
ydn.db.tr.Thread.Policy = {
MULTI: 'multi',
REPEAT: 'repeat',
ALL: 'all',
ATOMIC: 'atomic',
SINGLE: 'single'
};
/**
* Abort an active transaction.
* @param {ydn.db.base.Transaction} tx transaction to be aborted.
*/
ydn.db.tr.Thread.abort = function(tx) {
if (tx) {
if (goog.isFunction(tx.abort)) {
tx.abort();
} else if (goog.isFunction(tx.executeSql)) {
/**
* @param {SQLTransaction} tr transaction.
* @param {SQLError} error error.
* @return {boolean} true to roll back.
*/
var error_callback = function(tr, error) {
// console.log(error);
return true; // roll back
};
tx.executeSql('ABORT', [], null, error_callback);
// this will cause error on SQLTransaction and WebStorage.
// the error is wanted because there is no way to abort a transaction in
// WebSql. It is somehow recommanded workaround to abort a transaction.
} else {
throw new ydn.debug.error.NotSupportedException();
}
} else {
throw new ydn.db.InvalidStateError('No active transaction');
}
};