Skip to content

Commit

Permalink
Use per-db state to properly handle transactions requested on a datab…
Browse files Browse the repository at this point in the history
…ase that is being opened (#184).

Document related txLocks & openDBs map objects.

Mark other bugs to be fixed (#204/#209/#210).
  • Loading branch information
Chris Brody committed Mar 18, 2015
1 parent 47cb1ce commit b316586
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 33 deletions.
70 changes: 57 additions & 13 deletions SQLitePlugin.coffee.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@

READ_ONLY_REGEX = /^\s*(?:drop|delete|insert|update|create)\s/i

# per-db state
DB_STATE_INIT = "INIT"
DB_STATE_OPEN = "OPEN"

## global(s):

# per-db map of locking and queueing
# XXX NOTE: This is NOT cleaned up when a db is closed and/or deleted.
# If the record is simply removed when a db is closed or deleted,
# it will cause some test failures and may break large-scale
# applications that repeatedly open and close the database.
# [BUG #210] TODO: better to abort and clean up the pending transaction state.
# XXX TBD this will be renamed and include some more per-db state.
txLocks = {}

## utility functions:
Expand Down Expand Up @@ -65,6 +76,8 @@

## SQLite plugin db-connection handle

#### NOTE: there can be multipe SQLitePlugin db-connection handles per open db.

#### SQLite plugin db connection handle object is defined by a constructor function and prototype member functions:

SQLitePlugin = (openargs, openSuccess, openError) ->
Expand Down Expand Up @@ -95,17 +108,21 @@
return

SQLitePlugin::databaseFeatures = isSQLitePluginDatabase: true

# Keep track of state of open db connections
# XXX TBD this will be moved and renamed or
# combined with txLocks.
SQLitePlugin::openDBs = {}

SQLitePlugin::addTransaction = (t) ->

if !txLocks[@dbname]
txLocks[@dbname] = {
queue: []
inProgress: false
}
txLocks[@dbname].queue.push t
@startNextTransaction()
if @dbname of @openDBs && @openDBs[@dbname] isnt DB_STATE_INIT
@startNextTransaction()
return

SQLitePlugin::transaction = (fn, error, success) ->
Expand All @@ -129,25 +146,46 @@

nextTick () ->
txLock = txLocks[self.dbname]
if txLock.queue.length > 0 && !txLock.inProgress
if !txLock
# XXX TBD TODO (BUG #210/??): abort all pending transactions with error cb
return

else if txLock.queue.length > 0 && !txLock.inProgress
txLock.inProgress = true
txLock.queue.shift().start()
return

return

SQLitePlugin::open = (success, error) ->
onSuccess = () => success this

if @dbname of @openDBs
###
for a re-open run onSuccess async so that the openDatabase return value
can be used in the success handler as an alternative to the handler's
db argument
###
nextTick () -> onSuccess()
# for a re-open run the success cb async so that the openDatabase return value
# can be used in the success handler as an alternative to the handler's
# db argument
nextTick =>
success @
return

else
@openDBs[@dbname] = true
cordova.exec onSuccess, error, "SQLitePlugin", "open", [ @openargs ]
opensuccesscb = =>
# NOTE: the db state is NOT stored (in @openDBs) if the db was closed or deleted.

# XXX TODO [BUG #210]:
#if !@openDBs[@dbname] then call open error cb, and abort pending tx if any

if @dbname of @openDBs
@openDBs[@dbname] = DB_STATE_OPEN
success @

txLock = txLocks[@dbname]
if !!txLock && txLock.queue.length > 0 && !txLock.inProgress
@startNextTransaction()
return

# store initial DB state:
@openDBs[@dbname] = DB_STATE_INIT

cordova.exec opensuccesscb, error, "SQLitePlugin", "open", [ @openargs ]

return

Expand All @@ -157,8 +195,10 @@
error newSQLError 'database cannot be closed while a transaction is in progress'
return

# XXX [BUG #209] closing one db handle disables other handles to same db
delete @openDBs[@dbname]

# XXX [BUG #210] TODO: when closing or deleting a db, abort any pending transactions (with error callback)
cordova.exec success, error, "SQLitePlugin", "close", [ { path: @dbname } ]

else
Expand All @@ -167,6 +207,9 @@
return

SQLitePlugin::executeSql = (statement, params, success, error) ->
# XXX TODO: better to capture the result, and report it once
# the transaction has completely finished.
# This would fix BUG #204 (cannot close db in db.executeSql() callback).
mysuccess = (t, r) -> if !!success then success r
myerror = (t, e) -> if !!error then error e

Expand Down Expand Up @@ -463,6 +506,7 @@
dblocation = if !!first.location then dblocations[first.location] else null
args.dblocation = dblocation || dblocations[0]

# XXX [BUG #210] TODO: when closing or deleting a db, abort any pending transactions (with error callback)
delete SQLitePlugin::openDBs[args.path]
cordova.exec success, error, "SQLitePlugin", "delete", [ args ]

Expand Down
52 changes: 32 additions & 20 deletions www/SQLitePlugin.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b316586

Please sign in to comment.