|
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object com.almworks.sqlite4java.SQLiteQueue
public class SQLiteQueue
SQLiteQueue is a basic implementation of job queue for an SQLite connection. It provides multi-threaded
or GUI application with asynchronous execution of database tasks in a single separate thread with a single
SQLiteConnection
.
start()
and stop(boolean)
methods correspondingly.
Each database task is represented by a subclass of SQLiteJob
. A task is scheduled for execution
by execute(J)
method. Tasks are served on first-come, first-serve basis.
Public methods of SQLiteQueue are thread-safe, unless noted otherwise.
When writing tasks, it's a good practice to keep transaction boundaries within single task. That is, if you
BEGIN TRANSACTION in the task, make sure you COMMIT or ROLLBACK in the end. Otherwise, your transaction will
remain unfinished, locks held, and you possible wouldn't know which job will execute next in the context of
this unfinished transaction.
SQLiteQueue may be subclassed in order to change certain behavior. If you need some things to be done
differently, look for a protected method to override. For example, you can implement a priority queue
instead of FIFO queue.
SQLiteQueue and SQLiteJob are written to handle exceptions and errors in a controlled way. In particular,
if the queue thread terminates abnormally, SQLiteQueue will try to "reincarnate" by starting another thread
and opening another connection to the database. All queued tasks (except for the one that caused the problem)
should survive the reincarnation and execute in the new thread.
Reincarnation is not possible for in-memory database, since the database is lost after connection closes.
Some examples:
void start() { myQueue = new SQLiteQueue(myDatabaseFile); myQueue.start(); } int getTableRowCount(final String tableName) { return myQueue.execute(new SQLiteJob<Integer>() { protected Integer job(SQLiteConnection connection) throws SQLiteException { SQLiteStatement st = connection.prepare("SELECT COUNT(*) FROM " + tableName); try { st.step(); return st.columnInt(0); } finally { st.dispose(); } } }).complete(); }
SQLiteJob
Field Summary | |
---|---|
static long |
DEFAULT_REINCARNATE_TIMEOUT
Default timeout for reincarnating database thread. |
protected java.util.Collection<SQLiteJob> |
myJobs
Stores queued jobs. |
Constructor Summary | |
---|---|
SQLiteQueue()
Constructs the queue, which will use an in-memory database. |
|
SQLiteQueue(java.io.File databaseFile)
Constructs the queue. |
|
SQLiteQueue(java.io.File databaseFile,
java.util.concurrent.ThreadFactory threadFactory)
Constructs the queue and allows to specify a factory for the queue thread. |
Method Summary | ||
---|---|---|
protected void |
addJob(SQLiteJob job)
Adds a job to the job collection. |
|
protected void |
afterExecute(SQLiteJob job)
Do some work after job.execute() finished. |
|
protected java.util.Collection<SQLiteJob> |
createJobCollection()
Creates a new collection for storing pending jobs. |
|
protected void |
disposeConnection(SQLiteConnection connection)
Disposes the connection. |
|
|
execute(J job)
Places a job in the queue for asynchronous execution in database thread. |
|
protected void |
executeJob(SQLiteJob job)
Runs the job with the current connection. |
|
SQLiteQueue |
flush()
Waits until all jobs in the queue are executed. |
|
java.io.File |
getDatabaseFile()
Get the underlying database file. |
|
protected long |
getReincarnationTimeout()
Provides reincarnation timeout (the period to wait before reincarnating abnormally stopped queue thread). |
|
protected void |
handleJobException(SQLiteJob job,
java.lang.Throwable e)
Do some work if job threw an exception. |
|
protected void |
initConnection(SQLiteConnection connection)
Initialize a new connection. |
|
boolean |
isDatabaseThread()
Checks if the current thread is the thread that runs the queue's database connection. |
|
protected boolean |
isJobQueueEmpty()
Checks if there are no more pending jobs. |
|
protected boolean |
isReincarnationPossible()
Checks if reincarnation should be attempted after queue thread terminates abnormally. |
|
boolean |
isStopped()
Checks if the queue is stopped. |
|
SQLiteQueue |
join()
Waits for the queue to stop. |
|
protected SQLiteConnection |
openConnection()
Creates and opens a connection to the database. |
|
protected void |
reincarnate(long reincarnateTimeout)
Reincarnates the queue. |
|
protected java.util.List<SQLiteJob> |
removeJobsClearQueue()
Clears the queue and returned removed jobs. |
|
protected void |
rollback()
Rolls back current transaction. |
|
protected SQLiteJob |
selectJob()
Selects the next job from pending jobs to be executed. |
|
SQLiteQueue |
start()
Starts the queue by creating a new thread, opening connection in that thread and executing all jobs there. |
|
SQLiteQueue |
stop(boolean gracefully)
Stops the queue. |
|
java.lang.String |
toString()
|
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
public static final long DEFAULT_REINCARNATE_TIMEOUT
protected java.util.Collection<SQLiteJob> myJobs
Constructor Detail |
---|
public SQLiteQueue()
start()
public SQLiteQueue(java.io.File databaseFile)
SQLiteConnection.open(boolean)
method to create a connection within
queue thread.
The queue must be started in order for jobs to be executed.
databaseFile
- database file to connect to, or null to open an in-memory databasestart()
public SQLiteQueue(java.io.File databaseFile, java.util.concurrent.ThreadFactory threadFactory)
databaseFile
- database file to connect to, or null to open an in-memory databasethreadFactory
- the factory for thread(s), cannot be nullMethod Detail |
---|
public java.lang.String toString()
toString
in class java.lang.Object
public java.io.File getDatabaseFile()
public SQLiteQueue start()
stop(boolean)
method is called, or until it is terminated by non-recoverable error.
Calling this method second time does not have any effect. A queue cannot be started after it has stopped.
Any jobs added to the queue prior to start() will be carried out.
This method is thread-safe: it may be called from any thread.
java.lang.IllegalStateException
- if threadFactory failed to produce a new threadpublic SQLiteQueue stop(boolean gracefully)
execute(J)
method. The thread
and connection are finished and disposed.
If gracefully
parameter is true, the currently queued jobs will be executed before queue stops.
Otherwise, any pending jobs are cancelled, and the currently running job may be cancelled to. (If the currently
running job is ignorant of job.isCancelled() status and does not run a long SQL statement, it still may finish
normally.)
After call to stop(true)
you can call stop(false)
to force non-gracefull shutdown.
Other than that, calling stop()
second time has no effect.
If the queue hasn't been started, it will not be able to start later.
This method is thread-safe: it may be called from any thread. It finishes immediately, while actual stopping
of the queue happening asynchronously. If you need to wait until queue is fully stopped, use join()
method
after you called stop().
gracefully
- if true, jobs already queued will be executed, then the queue will stop
public SQLiteQueue join() throws java.lang.InterruptedException
Thread.join(long)
method to join with the queue thread.
Note that this method does not stop the queue. You need to call stop(boolean)
explicitly.
If queue has not been started, the method returns immediately.
java.lang.InterruptedException
- if the current thread is interrupted
java.lang.IllegalStateException
- if called from the queue threadpublic <T,J extends SQLiteJob<T>> J execute(J job)
SQLiteJob.job(com.almworks.sqlite4java.SQLiteConnection)
method will be called from the database thread with an instance of
SQLiteConnection
. Job may provide a return value, which will be treated as the job result.
The queue must be started in order for jobs to start executing. Jobs may be added to the queue before or after
the queue is started. However, if the queue is already stopped, the job will be immediately cancelled. (It will
receive SQLiteJob.jobCancelled()
and SQLiteJob.jobFinished(T)
callbacks before this method finishes.)
Because this method returns the argument, you can chain this method with other methods in SQLiteJob or in its
subclass:
MyResult r = myQueue.execute(new SQLiteJob<MyResult>() { ... }).complete();
T
- class of the job's result; use Object or Void if no result is neededJ
- job classjob
- the job to be executed on this queue's database connection, must not be null
SQLiteJob
public SQLiteQueue flush() throws java.lang.InterruptedException
java.lang.InterruptedException
- if the current thread is interruptedpublic boolean isStopped()
public boolean isDatabaseThread()
protected void addJob(SQLiteJob job)
job
- the job to be added to myJobs, the latter possible being nullprotected java.util.Collection<SQLiteJob> createJobCollection()
protected boolean isJobQueueEmpty()
protected java.util.List<SQLiteJob> removeJobsClearQueue()
isJobQueueEmpty()
must return true.
This method is called under synchronized lock and must not call any listeners or alien code.
protected SQLiteJob selectJob()
protected SQLiteConnection openConnection() throws SQLiteException
SQLiteException
- if connection cannot be createdinitConnection(com.almworks.sqlite4java.SQLiteConnection)
protected void initConnection(SQLiteConnection connection) throws SQLiteException
connection
- freshly opened database connection
SQLiteException
- if any initialization code failsprotected void disposeConnection(SQLiteConnection connection)
connection
- database connection no longer in use by the queueprotected void rollback()
protected void executeJob(SQLiteJob job) throws java.lang.Throwable
job
- next job from the queue
java.lang.Throwable
- any kind of problemprotected void afterExecute(SQLiteJob job) throws java.lang.Throwable
job
- finished job
java.lang.Throwable
- any kind of problemprotected void handleJobException(SQLiteJob job, java.lang.Throwable e) throws java.lang.Throwable
job
- erred jobe
- exception thrown by the job
java.lang.Throwable
- any kind of problemprotected long getReincarnationTimeout()
protected boolean isReincarnationPossible()
protected void reincarnate(long reincarnateTimeout)
reincarnateTimeout
- time to wait
|
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |