Commit 0e2a5334 authored by Jim Nelson's avatar Jim Nelson

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.
parent bbc0da0b
......@@ -7,6 +7,7 @@ build/
/gearyd
/geary-mailer
/geary-console
/geary-db-test
*.xz
*.swp
vapi/gmime-2.6/gmime-2.6.gi
......@@ -3,7 +3,7 @@
# Copyright 2012 Yorba Foundation
BUILD_DIR := build
BINARIES := geary gearyd geary-console geary-mailer
BINARIES := geary gearyd geary-console geary-mailer geary-db-test
BUILD_BINARIES := $(addprefix $(BUILD_DIR)/,$(BINARIES))
......
......@@ -13,7 +13,7 @@ Build-Depends: debhelper (>= 7),
libgmime-2.6-dev (>= 2.6.0),
valac-0.18 (>= 0.17.2),
cmake (>= 2.8.0),
libsqlheavy0.1-dev (>= 0.1.1),
libsqlite3-dev (>= 3.7.4)
libgnome-keyring-dev (>= 3.2.0)
Standards-Version: 3.8.3
Homepage: http://www.yorba.org
......@@ -29,7 +29,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends},
libcanberra0 (>= 0.28),
libwebkitgtk-3.0-0 (>= 1.4.3),
libxml2 (>= 2.6.32),
libsqlheavy0.1-0 (>= 0.1.1)
libsqlite3 (>= 3.7.4)
Description: Email client
Geary is an email client built for the GNOME desktop environment. It
allows you to read and write email with a simple, modern interface.
......
set(SQL_DEST share/geary/sql)
install(FILES Create.sql DESTINATION ${SQL_DEST})
install(FILES Version-002.sql DESTINATION ${SQL_DEST})
install(FILES Version-003.sql DESTINATION ${SQL_DEST})
install(FILES version-001.sql DESTINATION ${SQL_DEST})
install(FILES version-002.sql DESTINATION ${SQL_DEST})
install(FILES version-003.sql DESTINATION ${SQL_DEST})
install(FILES version-004.sql DESTINATION ${SQL_DEST})
--
-- Migrate ImapFolderPropertiesTable into FolderTable
--
ALTER TABLE FolderTable ADD COLUMN last_seen_total INTEGER;
ALTER TABLE FolderTable ADD COLUMN uid_validity INTEGER;
ALTER TABLE FolderTable ADD COLUMN uid_next INTEGER;
ALTER TABLE FolderTable ADD COLUMN attributes TEXT;
UPDATE FolderTable
SET
last_seen_total = (SELECT ImapFolderPropertiesTable.last_seen_total FROM ImapFolderPropertiesTable WHERE ImapFolderPropertiesTable.folder_id = FolderTable.id),
uid_validity = (SELECT ImapFolderPropertiesTable.uid_validity FROM ImapFolderPropertiesTable WHERE ImapFolderPropertiesTable.folder_id = FolderTable.id),
uid_next = (SELECT ImapFolderPropertiesTable.uid_next FROM ImapFolderPropertiesTable WHERE ImapFolderPropertiesTable.folder_id = FolderTable.id),
attributes = (SELECT ImapFolderPropertiesTable.attributes FROM ImapFolderPropertiesTable WHERE ImapFolderPropertiesTable.folder_id = FolderTable.id)
WHERE EXISTS
(SELECT * FROM ImapFolderPropertiesTable WHERE ImapFolderPropertiesTable.folder_id = FolderTable.id);
DROP TABLE ImapFolderPropertiesTable;
--
-- Migrate ImapMessagePropertiesTable into MessageTable
--
ALTER TABLE MessageTable ADD COLUMN flags TEXT;
ALTER TABLE MessageTable ADD COLUMN internaldate TEXT;
ALTER TABLE MessageTable ADD COLUMN rfc822_size INTEGER;
CREATE INDEX MessageTableInternalDateIndex ON MessageTable(internaldate);
CREATE INDEX MessageTableRfc822SizeIndex ON MessageTable(rfc822_size);
UPDATE MessageTable
SET
flags = (SELECT ImapMessagePropertiesTable.flags FROM ImapMessagePropertiesTable WHERE ImapMessagePropertiesTable.message_id = MessageTable.id),
internaldate = (SELECT ImapMessagePropertiesTable.internaldate FROM ImapMessagePropertiesTable WHERE ImapMessagePropertiesTable.message_id = MessageTable.id),
rfc822_size = (SELECT ImapMessagePropertiesTable.rfc822_size FROM ImapMessagePropertiesTable WHERE ImapMessagePropertiesTable.message_id = MessageTable.ID)
WHERE EXISTS
(SELECT * FROM ImapMessagePropertiesTable WHERE ImapMessagePropertiesTable.message_id = MessageTable.id);
DROP TABLE ImapMessagePropertiesTable;
......@@ -13,6 +13,7 @@ common/common-yorba-application.vala
set(ENGINE_SRC
engine/api/geary-account.vala
engine/api/geary-account-information.vala
engine/api/geary-account-settings.vala
engine/api/geary-attachment.vala
engine/api/geary-batch-operations.vala
engine/api/geary-composed-email.vala
......@@ -42,6 +43,19 @@ engine/api/geary-special-folder-type.vala
engine/common/common-message-data.vala
engine/db/database-error.vala
engine/db/db.vala
engine/db/db-connection.vala
engine/db/db-context.vala
engine/db/db-database.vala
engine/db/db-result.vala
engine/db/db-statement.vala
engine/db/db-synchronous-mode.vala
engine/db/db-transaction-async-job.vala
engine/db/db-transaction-outcome.vala
engine/db/db-transaction-type.vala
engine/db/db-versioned-database.vala
engine/imap/api/imap-account.vala
engine/imap/api/imap-email-flags.vala
engine/imap/api/imap-email-identifier.vala
......@@ -87,6 +101,15 @@ engine/imap/transport/imap-mailbox.vala
engine/imap/transport/imap-serializable.vala
engine/imap/transport/imap-serializer.vala
engine/imap-db/imap-db-account.vala
engine/imap-db/imap-db-database.vala
engine/imap-db/imap-db-folder.vala
engine/imap-db/imap-db-message-row.vala
engine/imap-db/outbox/smtp-outbox-email-identifier.vala
engine/imap-db/outbox/smtp-outbox-email-properties.vala
engine/imap-db/outbox/smtp-outbox-folder.vala
engine/imap-db/outbox/smtp-outbox-folder-root.vala
engine/impl/geary-abstract-account.vala
engine/impl/geary-abstract-folder.vala
engine/impl/geary-email-flag-watcher.vala
......@@ -104,9 +127,6 @@ engine/impl/geary-replay-queue.vala
engine/impl/geary-send-replay-operations.vala
engine/impl/geary-yahoo-account.vala
engine/impl/geary-yahoo-folder.vala
engine/impl/outbox/smtp-outbox-folder.vala
engine/impl/outbox/smtp-outbox-email-identifier.vala
engine/impl/outbox/smtp-outbox-email-properties.vala
engine/nonblocking/nonblocking-abstract-semaphore.vala
engine/nonblocking/nonblocking-batch.vala
......@@ -138,29 +158,6 @@ engine/smtp/smtp-response.vala
engine/smtp/smtp-response-code.vala
engine/smtp/smtp-response-line.vala
engine/sqlite/abstract/sqlite-database.vala
engine/sqlite/abstract/sqlite-row.vala
engine/sqlite/abstract/sqlite-table.vala
engine/sqlite/abstract/sqlite-transaction.vala
engine/sqlite/api/sqlite-account.vala
engine/sqlite/api/sqlite-folder.vala
engine/sqlite/email/sqlite-folder-row.vala
engine/sqlite/email/sqlite-folder-table.vala
engine/sqlite/email/sqlite-mail-database.vala
engine/sqlite/email/sqlite-message-attachment-row.vala
engine/sqlite/email/sqlite-message-attachment-table.vala
engine/sqlite/email/sqlite-message-location-row.vala
engine/sqlite/email/sqlite-message-location-table.vala
engine/sqlite/email/sqlite-message-row.vala
engine/sqlite/email/sqlite-message-table.vala
engine/sqlite/imap/sqlite-imap-database.vala
engine/sqlite/imap/sqlite-imap-folder-properties-row.vala
engine/sqlite/imap/sqlite-imap-folder-properties-table.vala
engine/sqlite/imap/sqlite-imap-message-properties-row.vala
engine/sqlite/imap/sqlite-imap-message-properties-table.vala
engine/sqlite/smtp/sqlite-smtp-outbox-row.vala
engine/sqlite/smtp/sqlite-smtp-outbox-table.vala
engine/state/state-machine-descriptor.vala
engine/state/state-machine.vala
engine/state/state-mapping.vala
......@@ -224,6 +221,10 @@ set(MAILER_SRC
mailer/main.vala
)
set(DBTEST_SRC
db-test/main.vala
)
set(DBUSSERVICE_SRC
dbusservice/controller.vala
dbusservice/database.vala
......@@ -251,14 +252,13 @@ pkg_check_modules(DEPS REQUIRED
libnotify>=0.7.5
libcanberra>=0.28
sqlite3>=3.7.4
sqlheavy-0.1>=0.1.1
gmime-2.6>=2.6.0
gnome-keyring-1>=2.32.0
webkitgtk-3.0>=1.4.3
)
set(ENGINE_PACKAGES
glib-2.0 gee-1.0 gio-2.0 sqlheavy-0.1 gmime-2.6 unique-3.0 posix
glib-2.0 gee-1.0 gio-2.0 gmime-2.6 unique-3.0 posix sqlite3
)
set(CLIENT_PACKAGES
......@@ -397,6 +397,31 @@ add_custom_command(
${CMAKE_COMMAND} -E copy geary-mailer ${CMAKE_BINARY_DIR}/
)
# db-test app
#################################################
vala_precompile(DBTEST_VALA_C
${DBTEST_SRC}
PACKAGES
${ENGINE_PACKAGES}
geary-static
OPTIONS
--vapidir=${CMAKE_SOURCE_DIR}/vapi
--vapidir=${CMAKE_BINARY_DIR}/src
--thread
--enable-checking
--fatal-warnings
)
add_executable(geary-db-test ${DBTEST_VALA_C})
target_link_libraries(geary-db-test ${DEPS_LIBRARIES} gthread-2.0 geary-static)
add_custom_command(
TARGET
geary-db-test
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E copy geary-db-test ${CMAKE_BINARY_DIR}/
)
# DBus Service
#################################################
vala_precompile(DBUS_VALA_C
......
......@@ -373,7 +373,7 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
case Geary.Account.Problem.LOGIN_FAILED:
debug("Login failed.");
Geary.Credentials old_credentials = account.get_account_information().credentials;
Geary.Credentials old_credentials = account.settings.credentials;
account.report_problem.disconnect(on_report_problem);
open_account(old_credentials.user, old_credentials.pass);
break;
......
......@@ -298,7 +298,7 @@ public class GearyController {
account.folders_added_removed.connect(on_folders_added_removed);
account.email_sent.connect(on_sent);
if (account.get_account_information().service_provider == Geary.ServiceProvider.YAHOO)
if (account.settings.service_provider == Geary.ServiceProvider.YAHOO)
main_window.title = GearyApplication.NAME + "!";
main_window.folder_list.set_user_folders_root_name(_("Labels"));
......@@ -1243,8 +1243,7 @@ public class GearyController {
error("Unable to get username. Error: %s", e.message);
}
Geary.AccountInformation acct_info = account.get_account_information();
return new Geary.RFC822.MailboxAddress(acct_info.real_name, username);
return new Geary.RFC822.MailboxAddress(account.settings.real_name, username);
}
private Geary.RFC822.MailboxAddresses get_from() {
......
/* 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.
*/
class DbTest : MainAsync {
public const string DB_FILENAME="db-test.db";
public DbTest(string[] args) {
base (args);
}
protected async override int exec_async() throws Error {
if (args.length < 2) {
stderr.printf("usage: db-test <data-dir>\n");
return 1;
}
Geary.Logging.log_to(stdout);
File schema_dir =
File.new_for_commandline_arg(args[0]).get_parent().get_child("src").get_child("db-test");
File data_file = File.new_for_commandline_arg(args[1]).get_child(DB_FILENAME);
debug("schema_dir=%s data_file=%s\n", schema_dir.get_path(), data_file.get_path());
Geary.Db.VersionedDatabase db = new Geary.Db.VersionedDatabase(data_file, schema_dir);
debug("Opening %s...", db.db_file.get_path());
db.open(Geary.Db.DatabaseFlags.CREATE_DIRECTORY | Geary.Db.DatabaseFlags.CREATE_FILE,
on_prepare_connection);
Geary.Db.Connection cx = db.open_connection();
debug("Sync select...");
Geary.Db.TransactionOutcome outcome = cx.exec_transaction(Geary.Db.TransactionType.RO, (cx) => {
Geary.Db.Result result = cx.prepare("SELECT str FROM AnotherTable").exec();
int ctr = 0;
while (!result.finished) {
stdout.printf("[%d] %s\n", ctr++, result.string_at(0));
result.next();
}
return Geary.Db.TransactionOutcome.COMMIT;
});
debug("Sync select: %s", outcome.to_string());
outcome = cx.exec_transaction(Geary.Db.TransactionType.WO, (cx) => {
for (int ctr = 0; ctr < 10; ctr++)
cx.prepare("INSERT INTO AnotherTable (str) VALUES (?)").bind_string(0, ctr.to_string()).exec();
return Geary.Db.TransactionOutcome.COMMIT;
});
debug("Async select");
outcome = yield db.exec_transaction_async(Geary.Db.TransactionType.RO, (cx) => {
Geary.Db.Result result = cx.prepare("SELECT str FROM AnotherTable").exec();
int ctr = 0;
while (!result.finished) {
stdout.printf("[%d]a %s\n", ctr++, result.string_at(0));
result.next();
}
return Geary.Db.TransactionOutcome.COMMIT;
}, null);
debug("Async select finished");
debug("Multi async write");
db.exec("DELETE FROM MultiTable");
db.exec_transaction_async.begin(Geary.Db.TransactionType.RW, (cx) => {
return do_insert_async(cx, 0);
}, null, on_async_completed);
db.exec_transaction_async.begin(Geary.Db.TransactionType.RW, (cx) => {
return do_insert_async(cx, 100);
}, null, on_async_completed);
db.exec_transaction_async.begin(Geary.Db.TransactionType.RW, (cx) => {
return do_insert_async(cx, 1000);
}, null, on_async_completed);
yield;
debug("Exiting...");
return 0;
}
private Geary.Db.TransactionOutcome do_insert_async(Geary.Db.Connection cx, int start) throws Error {
for (int ctr = start; ctr < (start + 10); ctr++) {
cx.prepare("INSERT INTO MultiTable (str) VALUES (?)").bind_int(0, ctr).exec();
debug("%d sleeping...", start);
Thread.usleep(10);
debug("%d woke up", start);
}
return Geary.Db.TransactionOutcome.COMMIT;
}
private void on_async_completed(Object? source, AsyncResult result) {
Geary.Db.Database db = (Geary.Db.Database) source;
try {
stdout.printf("Completed: %s\n", db.exec_transaction_async.end(result).to_string());
} catch (Error err) {
stdout.printf("Completed w/ err: %s\n", err.message);
}
}
private void on_prepare_connection(Geary.Db.Connection cx) throws Error {
cx.set_busy_timeout_msec(1000);
cx.set_synchronous(Geary.Db.SynchronousMode.OFF);
}
}
int main(string[] args) {
return new DbTest(args).exec();
}
CREATE TABLE TestTable (
id INTEGER PRIMARY KEY,
str TEXT,
num INTEGER
);
CREATE INDEX TestTableIntIndex ON TestTable(num);
CREATE TABLE AnotherTable (
id INTEGER PRIMARY KEY,
str TEXT
);
CREATE INDEX AnotherTableIndex ON AnotherTable(str)
CREATE TABLE MultiTable (
str TEXT
);
......@@ -74,10 +74,10 @@ public class Geary.AccountInformation : Object {
}
public async bool validate_async(Cancellable? cancellable = null) throws EngineError {
Geary.Endpoint endpoint = get_imap_endpoint();
AccountSettings settings = new AccountSettings(this);
Geary.Imap.ClientSessionManager client_session_manager =
new Geary.Imap.ClientSessionManager(endpoint, credentials, this, 0);
Geary.Imap.ClientSessionManager client_session_manager = new Geary.Imap.ClientSessionManager(
settings, 0);
Geary.Imap.ClientSession? client_session = null;
try {
client_session = yield client_session_manager.get_authorized_session_async(cancellable);
......@@ -87,8 +87,7 @@ public class Geary.AccountInformation : Object {
if (client_session != null) {
string current_mailbox;
Geary.Imap.ClientSession.Context context = client_session.get_context(out current_mailbox);
return context == Geary.Imap.ClientSession.Context.AUTHORIZED;
return client_session.get_context(out current_mailbox) == Geary.Imap.ClientSession.Context.AUTHORIZED;
}
return false;
......@@ -139,26 +138,23 @@ public class Geary.AccountInformation : Object {
}
public Geary.EngineAccount get_account() throws EngineError {
Geary.Sqlite.Account sqlite_account =
new Geary.Sqlite.Account(credentials.user);
Endpoint imap_endpoint = get_imap_endpoint();
Endpoint smtp_endpoint = get_smtp_endpoint();
AccountSettings settings = new AccountSettings(this);
ImapDB.Account local_account = new ImapDB.Account(settings);
Imap.Account remote_account = new Imap.Account(settings);
switch (service_provider) {
case ServiceProvider.GMAIL:
return new GmailAccount("Gmail account %s".printf(credentials.to_string()),
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(imap_endpoint,
smtp_endpoint, credentials, this), sqlite_account);
return new GmailAccount("Gmail account %s".printf(credentials.to_string()), settings,
remote_account, local_account);
case ServiceProvider.YAHOO:
return new YahooAccount("Yahoo account %s".printf(credentials.to_string()),
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(imap_endpoint,
smtp_endpoint, credentials, this), sqlite_account);
return new YahooAccount("Yahoo account %s".printf(credentials.to_string()), settings,
remote_account, local_account);
case ServiceProvider.OTHER:
return new OtherAccount("Other account %s".printf(credentials.to_string()),
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(imap_endpoint,
smtp_endpoint, credentials, this), sqlite_account);
return new OtherAccount("Other account %s".printf(credentials.to_string()), settings,
remote_account, local_account);
default:
throw new EngineError.NOT_FOUND("Service provider of type %s not known",
......
/* 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.
*/
/**
* AccountSettings is a complement to AccountInformation. AccountInformation stores these settings
* as well as defaults and provides validation and persistence functionality. Settings is simply
* the values loaded from a backing store, perhaps chosen from defaults, and validated filtered
* down to a set of working settings for the Account to use.
*/
public class Geary.AccountSettings {
public string real_name { get; private set; }
public Geary.Credentials credentials { get; private set; }
public Geary.ServiceProvider service_provider { get; private set; }
public bool imap_server_pipeline { get; private set; }
public Endpoint imap_endpoint { get; private set; }
public Endpoint smtp_endpoint { get; private set; }
internal AccountSettings(AccountInformation info) throws EngineError {
real_name = info.real_name;
credentials = info.credentials;
service_provider = info.service_provider;
imap_server_pipeline = info.imap_server_pipeline;
imap_endpoint = info.get_imap_endpoint();
smtp_endpoint = info.get_smtp_endpoint();
}
}
......@@ -12,13 +12,13 @@
* is stored in the created property.
*/
private class Geary.CreateLocalEmailOperation : Geary.NonblockingBatchOperation {
public Geary.Sqlite.Folder folder { get; private set; }
public ImapDB.Folder folder { get; private set; }
public Geary.Email email { get; private set; }
public Geary.Email.Field required_fields { get; private set; }
public bool created { get; private set; default = false; }
public Geary.Email? merged { get; private set; default = null; }
public CreateLocalEmailOperation(Geary.Sqlite.Folder folder, Geary.Email email,
public CreateLocalEmailOperation(ImapDB.Folder folder, Geary.Email email,
Geary.Email.Field required_fields) {
this.folder = folder;
this.email = email;
......@@ -26,12 +26,12 @@ private class Geary.CreateLocalEmailOperation : Geary.NonblockingBatchOperation
}
public override async Object? execute_async(Cancellable? cancellable) throws Error {
created = yield folder.create_email_async(email, cancellable);
created = yield folder.create_or_merge_email_async(email, cancellable);
if (email.fields.fulfills(required_fields)) {
merged = email;
} else {
merged = yield folder.fetch_email_async(email.id, required_fields, Sqlite.Folder.ListFlags.NONE,
merged = yield folder.fetch_email_async(email.id, required_fields, ImapDB.Folder.ListFlags.NONE,
cancellable);
}
......@@ -47,16 +47,19 @@ private class Geary.CreateLocalEmailOperation : Geary.NonblockingBatchOperation
* returned value.
*/
private class Geary.RemoveLocalEmailOperation : Geary.NonblockingBatchOperation {
public Geary.Sqlite.Folder folder { get; private set; }
public ImapDB.Folder folder { get; private set; }
public Geary.EmailIdentifier email_id { get; private set; }
public RemoveLocalEmailOperation(Geary.Sqlite.Folder folder, Geary.EmailIdentifier email_id) {
public RemoveLocalEmailOperation(ImapDB.Folder folder, Geary.EmailIdentifier email_id) {
this.folder = folder;
this.email_id = email_id;
}
public override async Object? execute_async(Cancellable? cancellable) throws Error {
yield folder.remove_single_email_async(email_id, cancellable);
Gee.List<Geary.EmailIdentifier> list = new Gee.ArrayList<Geary.EmailIdentifier>();
list.add(email_id);
yield folder.remove_email_async(list, cancellable);
return null;
}
......
......@@ -242,7 +242,11 @@ public class Geary.Email : Object {
public void add_attachment(Geary.Attachment attachment) {
attachments.add(attachment);
}
public void add_attachments(Gee.Collection<Geary.Attachment> attachments) {
this.attachments.add_all(attachments);
}
/**
* This method requires Geary.Email.Field.HEADER and Geary.Email.Field.BODY be present.
* If not, EngineError.INCOMPLETE_MESSAGE is thrown.
......
......@@ -5,28 +5,21 @@
*/
public abstract class Geary.EngineAccount : Geary.AbstractAccount {
private AccountInformation account_information;
public virtual Geary.AccountSettings settings { get; private set; }
public virtual signal void email_sent(Geary.RFC822.Message rfc822) {
}
public EngineAccount(string name, string username, AccountInformation account_information,
File user_data_dir) {
internal EngineAccount(string name, AccountSettings settings) {
base (name);
this.account_information = account_information;
this.settings = settings;
}
protected virtual void notify_email_sent(Geary.RFC822.Message rfc822) {
email_sent(rfc822);
}
public virtual AccountInformation get_account_information() {
return account_information;
}
public abstract bool delete_is_archive();
public abstract async void send_email_async(Geary.ComposedEmail composed, Cancellable? cancellable = null)
throws Error;
}
......@@ -5,19 +5,22 @@
*/
public class Geary.Engine {
private static bool gmime_inited = false;
public static File? user_data_dir { get; private set; default = null; }
public static File? resource_dir { get; private set; default = null; }
private static bool inited = false;
public static void init(File _user_data_dir, File _resource_dir) {
if (inited)
return;
user_data_dir = _user_data_dir;
resource_dir = _resource_dir;
// Initialize GMime
if (!gmime_inited) {
GMime.init(0);
gmime_inited = true;
}
GMime.init(0);
inited = true;
}
// Returns a list of usernames associated with Geary.
......
/* 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.
*/
public errordomain DatabaseError {
GENERAL,
OPEN_REQUIRED,
BUSY,
BACKING,
MEMORY,
ABORT,
INTERRUPT,
LIMITS,
TYPESPEC,
FINISHED
}
/* 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.
*/
/**
* A Connection represents a connection to an open database. Because SQLite uses a
* synchronous interface, all calls are blocking. Db.Database offers asynchronous queries by
* pooling connections and invoking queries from background threads.
*
* Connections are associated with a Database. Use Database.open_connection() to create
* one.
*
* A Connection will close when its last reference is dropped.
*/
public class Geary.Db.Connection : Geary.Db.Context {
public const int DEFAULT_BUSY_TIMEOUT_MSEC = 0;
private const string PRAGMA_FOREIGN_KEYS = "foreign_keys";
private const string PRAGMA_RECURSIVE_TRIGGERS = "recursive_triggers";
private const string PRAGMA_USER_VERSION = "user_version";
private const string PRAGMA_SCHEMA_VERSION = "schema_version";
private const string PRAGMA_SECURE_DELETE = "secure_delete";
private const string PRAGMA_SYNCHRONOUS = "synchronous";
/**
* See http://www.sqlite.org/c3ref/last_insert_rowid.html
*/
public int64 last_insert_rowid { get {
return db.last_insert_rowid();
} }
/**
* See http://www.sqlite.org/c3ref/changes.html
*/
public int last_modified_rows { get {
return db.changes();
} }