geary/src/engine/db/db.vala
Jim Nelson 0e2a533438 Remove SQLHeavy: Closes #5034
It is done.

Initial implementation of the new database subsystem

These pieces represent the foundation for ticket #5034

Expanded transactions, added VersionedDatabase

Further expansions of the async code.

Moved async pool logic into Database, where it realistically
belongs.

Further improvements.  Introduced geary-db-test.

Added SQL create and update files for Geary.Db

version-001 to version-003 are exact copies of the SQLHeavy scripts
to ensure no slight changes when migrating.  version-004 upgrades
the database to remove the ImapFolderPropertiesTable and
ImapMessagePropertiesTable, now that the database code is pure
IMAP.

When we support other messaging systems (such as POP3), those
subsystems will need to code their own database layers OR rely on
the IMAP schema and simply ignore the IMAP-specific fields.

ImapDB.Account fleshed out

ImapDB.Folder is commented out, however.  Need to port next.

ImapDB.Folder fleshed out

MessageTable, MessageLocationTable, and AttachementTable are now
handled inside ImapDB.Folder.

chmod -x imap-db-database.vala

OutboxEmailIdentifier/Properties -> SmtpOutboxEmailIdentifier/Properties

Moved SmtpOutboxFolderRoot into its own source file

SmtpOutboxFolder ported to new database code

Move Engine implementations to ImapDB.

Integration and cleanup of new database code with main source

This commit performs the final integration steps to move Geary
completely over to the new database model.  This also cleans out
the old SQLHeavy-based code and fixes a handful of small bugs that
were detected during basic test runs.

Moved Outbox to ImapDB

As the Outbox is tied to the database that ImapDB runs, move the
Outbox code into that folder.

Outbox fixes and better parameter checking

Bumped Database thread pool count and made them exclusive

My reasoning is that there may be a need for a lot of threads at
once (when a big batch of commands comes in, especially at
startup).  If performance looks ok, we might consider relaxing
this later.
2012-07-11 15:40:39 -07:00

147 lines
4.3 KiB
Vala

/* Copyright 2012 Yorba Foundation
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
* Geary.Db is a simple wrapper around SQLite to make it more GObject-ish and easier to code in
* Vala. It also uses threads and some concurrency features of SQLite to allow for asynchronous
* access to the database.
*
* There is no attempt here to hide or genericize the backing database library; this is designed with
* SQLite in mind. As such, many of the calls are merely direct front-ends to the underlying
* SQLite call.
*
* The design of the classes and interfaces owes a debt to SQLHeavy (http://code.google.com/p/sqlheavy/).
*/
namespace Geary.Db {
public const int64 INVALID_ROWID = -1;
[Flags]
public enum DatabaseFlags {
NONE = 0,
CREATE_DIRECTORY,
CREATE_FILE,
READ_ONLY
}
public enum ResetScope {
SAVE_BINDINGS,
CLEAR_BINDINGS
}
/*
* PrepareConnection is called from Database when a Connection is created. Database may pool
* Connections, especially for asynchronous queries, so this is only called when a new
* Connection is created and not when its reused.
*
* PrepareConnection may be used as an opportunity to modify or configure the Connection.
* This callback is called prior to the Connection being used, either internally or handed off to
* a caller for normal use.
*
* This callback may be called in the context of a background thread.
*/
public delegate void PrepareConnection(Connection cx, bool master) throws Error;
/**
* See Connection.exec_transaction() for more information on how this delegate is used.
*/
public delegate TransactionOutcome TransactionMethod(Connection cx, Cancellable? cancellable) throws Error;
/**
* See http://www.sqlite.org/c3ref/threadsafe.html
*/
public bool threadsafe() {
return Sqlite.threadsafe() != 0;
}
/**
* See http://www.sqlite.org/c3ref/libversion.html
*/
public unowned string sqlite_version() {
return Sqlite.libversion();
}
/**
* See http://www.sqlite.org/c3ref/libversion.html
*/
public int sqlite_version_number() {
return Sqlite.libversion_number();
}
private void check_cancelled(string? method, Cancellable? cancellable) throws IOError {
if (cancellable != null && cancellable.is_cancelled())
throw new IOError.CANCELLED("%s cancelled", !String.is_empty(method) ? method : "Operation");
}
// Returns result if exception is not thrown
private int throw_on_error(Context ctx, string? method, int result, string? raw = null) throws DatabaseError {
// fast-fail
switch (result) {
case Sqlite.OK:
case Sqlite.DONE:
case Sqlite.ROW:
return result;
}
string location = !String.is_empty(method) ? "(%s) ".printf(method) : "";
string errmsg = (ctx.get_connection() != null) ? " - %s".printf(ctx.get_connection().db.errmsg()) : "";
string sql;
if (ctx.get_statement() != null)
sql = " (%s)".printf(ctx.get_statement().sql);
else if (!String.is_empty(raw))
sql = " (%s)".printf(raw);
else
sql = "";
string msg = "%s[err=%d]%s%s".printf(location, result, errmsg, sql);
switch (result) {
case Sqlite.BUSY:
throw new DatabaseError.BUSY(msg);
case Sqlite.PERM:
case Sqlite.READONLY:
case Sqlite.IOERR:
case Sqlite.CORRUPT:
case Sqlite.CANTOPEN:
case Sqlite.NOLFS:
case Sqlite.AUTH:
case Sqlite.FORMAT:
case Sqlite.NOTADB:
throw new DatabaseError.BACKING(msg);
case Sqlite.NOMEM:
throw new DatabaseError.MEMORY(msg);
case Sqlite.ABORT:
case Sqlite.LOCKED:
throw new DatabaseError.ABORT(msg);
case Sqlite.INTERRUPT:
throw new DatabaseError.INTERRUPT(msg);
case Sqlite.FULL:
case Sqlite.EMPTY:
case Sqlite.TOOBIG:
case Sqlite.CONSTRAINT:
case Sqlite.RANGE:
throw new DatabaseError.LIMITS(msg);
case Sqlite.SCHEMA:
case Sqlite.MISMATCH:
throw new DatabaseError.TYPESPEC(msg);
case Sqlite.ERROR:
case Sqlite.INTERNAL:
case Sqlite.MISUSE:
default:
throw new DatabaseError.GENERAL(msg);
}
}
}