parent
71d8c8b1a4
commit
aa223d103d
8 changed files with 92 additions and 63 deletions
|
|
@ -513,9 +513,9 @@ public class Accounts.Manager : GLib.Object {
|
|||
string? goa_id = metadata_config.get_string(METADATA_GOA, null);
|
||||
bool is_goa = (goa_id != null);
|
||||
|
||||
// This exists purely for people were running master with GOA
|
||||
// This exists purely for people were running mainline with GOA
|
||||
// accounts before the new accounts editor landed and 0.13 was
|
||||
// released. It can be removed once 0.14 is out.
|
||||
// released. It can be removed once 3.34 is out.
|
||||
if (goa_id == null && id.has_prefix(GOA_ID_PREFIX)) {
|
||||
goa_id = to_goa_id(id);
|
||||
is_goa = true;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
* Each database supports multiple {@link Connection}s that allow SQL
|
||||
* queries to be executed, however if a single connection is required
|
||||
* by an app, this class also provides convenience methods to execute
|
||||
* queries against a common ''master'' connection.
|
||||
* queries against a common ''primary'' connection.
|
||||
*
|
||||
* This class offers a number of asynchronous methods, however since
|
||||
* SQLite only supports a synchronous API, these are implemented using
|
||||
|
|
@ -62,7 +62,7 @@ public class Geary.Db.Database : Geary.Db.Context {
|
|||
}
|
||||
}
|
||||
|
||||
private Connection? master_connection = null;
|
||||
private Connection? primary = null;
|
||||
private int outstanding_async_jobs = 0;
|
||||
private ThreadPool<TransactionAsyncJob>? thread_pool = null;
|
||||
private unowned PrepareConnection? prepare_cb = null;
|
||||
|
|
@ -176,19 +176,21 @@ public class Geary.Db.Database : Geary.Db.Context {
|
|||
}
|
||||
|
||||
/**
|
||||
* Closes the Database, releasing any resources it may hold, including the master connection.
|
||||
* Closes the database, releasing any resources it may hold.
|
||||
*
|
||||
* Note that closing a Database does not close or invalidate Connections it has spawned nor does
|
||||
* it cancel any scheduled asynchronous jobs pending or in execution. All Connections,
|
||||
* Statements, and Results will be able to communicate with the database. Only when they are
|
||||
* destroyed is the Database object finally destroyed.
|
||||
* Note that closing a Database does not close or invalidate
|
||||
* Connections it has spawned nor does it cancel any scheduled
|
||||
* asynchronous jobs pending or in execution. All Connections,
|
||||
* Statements, and Results will be able to communicate with the
|
||||
* database. Only when they are destroyed is the Database object
|
||||
* finally destroyed.
|
||||
*/
|
||||
public virtual void close(Cancellable? cancellable = null) throws Error {
|
||||
if (!is_open)
|
||||
return;
|
||||
|
||||
// drop the master connection, which holds a ref back to this object
|
||||
master_connection = null;
|
||||
// drop the primary connection, which holds a ref back to this object
|
||||
this.primary = null;
|
||||
|
||||
// As per the contract above, can't simply drop the thread and connection pools; that would
|
||||
// be bad.
|
||||
|
|
@ -216,7 +218,9 @@ public class Geary.Db.Database : Geary.Db.Context {
|
|||
return cx;
|
||||
}
|
||||
|
||||
private Connection internal_open_connection(bool master, Cancellable? cancellable) throws Error {
|
||||
private Connection internal_open_connection(bool is_primary,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
check_open();
|
||||
|
||||
int sqlite_flags = (flags & DatabaseFlags.READ_ONLY) != 0
|
||||
|
|
@ -232,69 +236,93 @@ public class Geary.Db.Database : Geary.Db.Context {
|
|||
|
||||
Connection cx = new Connection(this, sqlite_flags, cancellable);
|
||||
if (prepare_cb != null)
|
||||
prepare_cb(cx, master);
|
||||
prepare_cb(cx, is_primary);
|
||||
|
||||
return cx;
|
||||
}
|
||||
|
||||
/**
|
||||
* The master connection is a general-use connection many of the calls in Database (including
|
||||
* exec(), exec_file(), query(), prepare(), and exec_trnasaction()) use to perform their work.
|
||||
* It can also be used by the caller if a dedicated Connection is not required.
|
||||
* Returns the primary connection for the database.
|
||||
*
|
||||
* Throws DatabaseError.OPEN_REQUIRED if not open.
|
||||
* The primary connection is a general-use connection many of the
|
||||
* calls in Database (including exec(), exec_file(), query(),
|
||||
* prepare(), and exec_transaction()) use to perform their work.
|
||||
* It can also be used by the caller if a dedicated Connection is
|
||||
* not required.
|
||||
*
|
||||
* Throws {@link DatabaseError.OPEN_REQUIRED} if not open.
|
||||
*/
|
||||
public Connection get_master_connection() throws Error {
|
||||
if (master_connection == null)
|
||||
master_connection = internal_open_connection(true, null);
|
||||
public Connection get_primary_connection() throws GLib.Error {
|
||||
if (this.primary == null)
|
||||
this.primary = internal_open_connection(true, null);
|
||||
|
||||
return master_connection;
|
||||
return this.primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Connection.exec() on the master connection.
|
||||
* Executes a statement from a string using the primary connection.
|
||||
*
|
||||
* Throws DatabaseError.OPEN_REQUIRED if not open.
|
||||
* This is a convenience method for calling {@link
|
||||
* Connection.exec} on the connection returned by {@link
|
||||
* get_primary_connection}. Throws {@link
|
||||
* DatabaseError.OPEN_REQUIRED} if not open.
|
||||
*/
|
||||
public void exec(string sql, Cancellable? cancellable = null) throws Error {
|
||||
get_master_connection().exec(sql, cancellable);
|
||||
public void exec(string sql, GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
get_primary_connection().exec(sql, cancellable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Connection.exec_file() on the master connection.
|
||||
* Executes a statement from a file using the primary connection.
|
||||
*
|
||||
* Throws DatabaseError.OPEN_REQUIRED if not open.
|
||||
* This is a convenience method for calling {@link
|
||||
* Connection.exec_file} on the connection returned by {@link
|
||||
* get_primary_connection}. Throws {@link
|
||||
* DatabaseError.OPEN_REQUIRED} if not open.
|
||||
*/
|
||||
public void exec_file(File file, Cancellable? cancellable = null) throws Error {
|
||||
get_master_connection().exec_file(file, cancellable);
|
||||
public void exec_file(File file, GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
get_primary_connection().exec_file(file, cancellable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Connection.prepare() on the master connection.
|
||||
* Prepares a statement from a string using the primary connection.
|
||||
*
|
||||
* Throws DatabaseError.OPEN_REQUIRED if not open.
|
||||
* This is a convenience method for calling {@link
|
||||
* Connection.prepare} on the connection returned by {@link
|
||||
* get_primary_connection}. Throws {@link
|
||||
* DatabaseError.OPEN_REQUIRED} if not open.
|
||||
*/
|
||||
public Statement prepare(string sql) throws Error {
|
||||
return get_master_connection().prepare(sql);
|
||||
public Statement prepare(string sql) throws GLib.Error {
|
||||
return get_primary_connection().prepare(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Connection.query() on the master connection.
|
||||
* Executes a query using the primary connection.
|
||||
*
|
||||
* Throws DatabaseError.OPEN_REQUIRED if not open.
|
||||
* This is a convenience method for calling {@link
|
||||
* Connection.query} on the connection returned by {@link
|
||||
* get_primary_connection}. Throws {@link
|
||||
* DatabaseError.OPEN_REQUIRED} if not open.
|
||||
*/
|
||||
public Result query(string sql, Cancellable? cancellable = null) throws Error {
|
||||
return get_master_connection().query(sql, cancellable);
|
||||
public Result query(string sql, GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
return get_primary_connection().query(sql, cancellable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Connection.exec_transaction() on the master connection.
|
||||
* Executes a transaction using the primary connection.
|
||||
*
|
||||
* Throws DatabaseError.OPEN_REQUIRED if not open.
|
||||
* This is a convenience method for calling {@link
|
||||
* Connection.exec_transaction} on the connection returned by
|
||||
* {@link get_primary_connection}. Throws {@link
|
||||
* DatabaseError.OPEN_REQUIRED} if not open.
|
||||
*/
|
||||
public TransactionOutcome exec_transaction(TransactionType type, TransactionMethod cb,
|
||||
Cancellable? cancellable = null) throws Error {
|
||||
return get_master_connection().exec_transaction(type, cb, cancellable);
|
||||
public TransactionOutcome exec_transaction(TransactionType type,
|
||||
TransactionMethod cb,
|
||||
GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
return get_primary_connection().exec_transaction(type, cb, cancellable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -311,8 +339,8 @@ public class Geary.Db.Database : Geary.Db.Context {
|
|||
*/
|
||||
public async TransactionOutcome exec_transaction_async(TransactionType type,
|
||||
TransactionMethod cb,
|
||||
Cancellable? cancellable)
|
||||
throws Error {
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
TransactionAsyncJob job = new TransactionAsyncJob(
|
||||
null, type, cb, cancellable
|
||||
);
|
||||
|
|
@ -339,7 +367,7 @@ public class Geary.Db.Database : Geary.Db.Context {
|
|||
|
||||
// This method must be thread-safe.
|
||||
private void on_async_job(owned TransactionAsyncJob job) {
|
||||
// *never* use master connection for threaded operations
|
||||
// *never* use primary connection for threaded operations
|
||||
Connection? cx = job.cx;
|
||||
Error? open_err = null;
|
||||
if (cx == null) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class Geary.Db.VersionedDatabase : Geary.Db.Database {
|
|||
/** Returns the current schema version number of this database. */
|
||||
public int get_schema_version()
|
||||
throws GLib.Error {
|
||||
return get_master_connection().get_user_version_number();
|
||||
return get_primary_connection().get_user_version_number();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ public enum ResetScope {
|
|||
*
|
||||
* This callback may be called in the context of a background thread.
|
||||
*/
|
||||
public delegate void PrepareConnection(Connection cx, bool master) throws Error;
|
||||
public delegate void PrepareConnection(Connection cx, bool is_primary)
|
||||
throws GLib.Error;
|
||||
|
||||
/**
|
||||
* See Connection.exec_transaction() for more information on how this delegate is used.
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
* feature (via WeakPointers), but Vala does not implement the weak keyword in this way currently
|
||||
* and does not (today) have semantics to be notified when the weak reference has turned to null.
|
||||
*
|
||||
* Additionally, there are situations where an Object may be held in some master table inside an
|
||||
* object and references to it are handed out to one or more callers. The master class would like
|
||||
* Additionally, there are situations where an Object may be held in some primary table inside an
|
||||
* object and references to it are handed out to one or more callers. The primary class would like
|
||||
* to know when all those references have been dropped although (of course) Object has not been
|
||||
* destroyed (even with a proper weak ref) because it's held in a table. Even if a
|
||||
* WeakReferenceTable is somehow implemented and used, there are situations where it's necessary to
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class Geary.Db.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
}
|
||||
|
||||
public void open_existing() throws Error {
|
||||
|
|
@ -47,7 +47,7 @@ class Geary.Db.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
|
||||
tmp_file.delete();
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ class Geary.Db.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
|
||||
db.file.delete();
|
||||
tmp_dir.delete();
|
||||
|
|
@ -92,7 +92,7 @@ class Geary.Db.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
|
||||
db.file.delete();
|
||||
db.file.get_parent().delete();
|
||||
|
|
@ -117,7 +117,7 @@ class Geary.Db.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
|
||||
db.file.delete();
|
||||
tmp_dir.delete();
|
||||
|
|
@ -141,7 +141,7 @@ class Geary.Db.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
|
||||
db.file.delete();
|
||||
tmp_dir.delete();
|
||||
|
|
@ -166,7 +166,7 @@ class Geary.Db.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
|
||||
db.file.delete();
|
||||
db.file.get_parent().delete();
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ CREATE TABLE MessageAttachmentTable (
|
|||
GMime.Part part = new_part(null, ENCODED_BODY.data);
|
||||
|
||||
Gee.List<Attachment> attachments = Attachment.save_attachments(
|
||||
this.db.get_master_connection(),
|
||||
this.db.get_primary_connection(),
|
||||
this.tmp_dir,
|
||||
1,
|
||||
new Gee.ArrayList<Geary.RFC822.Part>.wrap({
|
||||
|
|
@ -210,7 +210,7 @@ CREATE TABLE MessageAttachmentTable (
|
|||
));
|
||||
|
||||
Gee.List<Attachment> attachments = Attachment.save_attachments(
|
||||
this.db.get_master_connection(),
|
||||
this.db.get_primary_connection(),
|
||||
this.tmp_dir,
|
||||
1,
|
||||
new Gee.ArrayList<Geary.RFC822.Part>.wrap({
|
||||
|
|
@ -271,7 +271,7 @@ abriquent pour te la vendre une =C3=A2me vulgaire.""";
|
|||
);
|
||||
|
||||
Gee.List<Attachment> attachments = Attachment.save_attachments(
|
||||
this.db.get_master_connection(),
|
||||
this.db.get_primary_connection(),
|
||||
this.tmp_dir,
|
||||
1,
|
||||
new Gee.ArrayList<Geary.RFC822.Part>.wrap({
|
||||
|
|
@ -299,7 +299,7 @@ VALUES (2, 'text/plain');
|
|||
""");
|
||||
|
||||
Gee.List<Attachment> loaded = Attachment.list_attachments(
|
||||
this.db.get_master_connection(),
|
||||
this.db.get_primary_connection(),
|
||||
GLib.File.new_for_path("/tmp"),
|
||||
1,
|
||||
null
|
||||
|
|
@ -313,7 +313,7 @@ VALUES (2, 'text/plain');
|
|||
GMime.Part part = new_part(null, ENCODED_BODY.data);
|
||||
|
||||
Gee.List<Attachment> attachments = Attachment.save_attachments(
|
||||
this.db.get_master_connection(),
|
||||
this.db.get_primary_connection(),
|
||||
this.tmp_dir,
|
||||
1,
|
||||
new Gee.ArrayList<Geary.RFC822.Part>.wrap({
|
||||
|
|
@ -331,7 +331,7 @@ VALUES (2, 'text/plain');
|
|||
""");
|
||||
|
||||
Attachment.delete_attachments(
|
||||
this.db.get_master_connection(), this.tmp_dir, 1, null
|
||||
this.db.get_primary_connection(), this.tmp_dir, 1, null
|
||||
);
|
||||
|
||||
Geary.Db.Result result = this.db.query(
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class Geary.ImapDB.DatabaseTest : TestCase {
|
|||
|
||||
// Need to get a connection since the database doesn't
|
||||
// actually get created until then
|
||||
db.get_master_connection();
|
||||
db.get_primary_connection();
|
||||
|
||||
// Need to close it again to stop the GC process running
|
||||
db.close();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue