Commit Graph

362 Commits

Author SHA1 Message Date
Christopher Tate
afccaa84c8 Use myUserId() only in registerContentObserver()
The reason for this is a bit subtle: we want to guarantee that
when a content observer is registered using the public API, it
is *always* bound to the host user's view of the data behind the
observed Uri, never the calling user's.  Now, the reason it was
the calling user in the first place is that the Settings provider
(and potentially any singleton provider) needs the observers
underlying Cursors returned from query() to be tied to the caller's
user, not the provider's host user.

In order to accomplish that now that the public-facing behavior is
always tied to the host user, the concrete class that implements
the Cursor type handled by the Settings provider has been extended
with a new hidden API for setting a notification observer tied to
an arbitrary user; and then the provider explicitly downcasts the
query result's Cursor to that class in order to register the
notification observer.  We can do this safely because this is platform
code; if we change the way that these underlying cursors are constructed,
we can just fix this point of call to follow along.  If they get out
of sync in the future, the Settings provider will scream bloody
murder in the log and throw a crashing exception.

Bug 7231549

Change-Id: I0aaceebb8b4108c56f8b9964ca7f9e698ddd91c8
2012-10-03 17:41:51 -07:00
Jean-Baptiste Queru
de9d40d445 am 64ed6b2c: am d77d17c2: Merge "Fix cursor memory leak"
* commit '64ed6b2cfa6a4bb58f3f8a9b59d840cdce049c80':
  Fix cursor memory leak
2012-08-08 10:55:46 -07:00
Jean-Baptiste Queru
d77d17c28d Merge "Fix cursor memory leak" 2012-08-08 10:44:50 -07:00
Catherine Liu
3f824c0e72 Fix cursor memory leak
In current code, if an application opens a cursor to access a
provider, and doesn't close that cursor, later, when this cursor
is garbage collected, it won't get closed. This will cause a memory
leak in the provider. The leaked memory can only be reclaimed when
the application with the leaked cursor was dead.

The solution is, close the cursor when it's garbage collected.

Change-Id: I786915c46d4672b6b1b37414b3bc1ff8cea2e00b
2012-07-09 16:34:58 -05:00
Jeff Brown
b33eb4e32a Deprecate DatabaseUtils.InsertHelper.
This class does not offer any advantages over SQLiteStatement
and just makes code more complex and error-prone.

Documented that the class is not thread-safe.

Removed a potential deadlock in insert() and replace() caused
by the insertInternal() method being synchronized in the case
where the class was being used concurrently (woe to you!).

Thread A would start a transaction.
Thread B would call insertInternal() and acquire the object monitor,
but block because it could not obtain the db connection because
thread A is holding onto it.
Thread A would call insertInternal() and block because Thread B
was holding the object monitor.
Deadlock.

Changed this code to use a transaction instead of a lock,
which provides the necessary mutual exclusion guarantee without
the potential for a deadlock.  Even so, the class really isn't
thread safe.

Bug: 6625094
Change-Id: I51d9a15567a6f2bad6f25e550b48f8f6ffcab2a7
2012-06-22 15:24:26 -07:00
Jeff Brown
888da152ec Enable SQLite configuration to be set with system properties.
This change does not alter the behavior of the system except to
enable the use of system properties to override SQLite configuration
options for debugging.

Bug: 6484633
Change-Id: I8908a3ba07910a1193396e2e45791e9faa7be349
2012-05-11 16:36:24 -07:00
Jeff Brown
7873d5b3ff Deprecate certain AbstractCursor fields.
Bug: 6353797
Change-Id: I52b67f35c867378849ceb77356d0065161157ac9
2012-05-09 14:32:14 -07:00
Jeff Brown
a7771df369 Move CancellationSignal to android.os package.
Bug: 6427830
Change-Id: I39451bb1e1d4a8d976ed1c671234f0c8c61658dd
2012-05-07 20:06:46 -07:00
Jeff Brown
aeee2f5d75 Fix CancellationSignal deadlock.
Bug: 6398945
Change-Id: I5a3d4dce74009d6f1d284a8cc54c9f68daa6a9c2
2012-04-26 20:12:44 -07:00
Jeff Brown
76070d1690 Ensure that db connection reconfiguration can change the db.
If the db connection had been marked read-only, then certain
operations performed during reconfiguration, such as setting the
locale, could fail.  So we need to make sure to clear the
read-only flag ahead of time.

Bug: 6296752
Change-Id: I98e19aff6386497b7fc321e04ca560fc1817a781
2012-04-19 11:30:33 -07:00
Makoto Onuki
72eebb6b6d Add # of changed rows to executeForChangedRowCount log
Change-Id: I240849f8e90490bbb6f73bbf7047e71254c83f0c
2012-04-16 14:24:37 -07:00
Jeff Brown
d19ff5f95d YieldTransaction should actually commit the transaction.
Bug: 6239243
Change-Id: I2e0dfb0c8f0b062674cc2a1c14955eba9a4b9df3
2012-03-27 18:13:11 -07:00
Jeff Brown
96496adb61 Provide an API for enabling foreign key constraints.
Also provide a lifecycle method on SQLiteOpenHelper so that
applications can configure things like this before the onCreate,
onUpgrade, onDowngrade and onOpen callbacks run.

Change-Id: If3d1396720bd2e032dd9e034733fb1ff9a9733dd
2012-03-23 14:49:39 -07:00
Jeff Brown
47847f3f4d Support enabling WAL using a flag when DB is opened.
Using enableWriteAheadLogging() to enable WAL is inefficient because
we previously disabled WAL mode when the database was opened.
Switching from WAL to PERSIST then back to WAL is inefficient
and could slow down application launch time.  It would be better
to leave the database in WAL mode when we open it to begin with.

To do that, we need to know ahead of time whether we will want to
have WAL enabled for the newly opened database.

Using this flag also reduces the chance that we will encounter
an error enabling WAL mode due to there being other open connections
to the database.

Bug: 6124556
Change-Id: I38ec7a528baeda9f1ef77e25e88b3ca4b6296200
2012-03-23 13:26:26 -07:00
Jeff Brown
df78cd5ee9 Merge "Work around problems changing the database journal mode." 2012-03-22 15:07:48 -07:00
Jeff Brown
d67c8c6789 Work around problems changing the database journal mode.
Because we always disable WAL mode when a database is first opened
(even if we intend to re-enable it), we can encounter problems if
there is another open connection to the database somewhere.
This can happen for a variety of reasons such as an application opening
the same database in multiple processes at the same time or if there is a
crashing content provider service that the ActivityManager has
removed from its registry but whose process hasn't quite died yet
by the time it is restarted in a new process.

If we don't change the journal mode, nothing really bad happens.
In the worst case, an application that enables WAL might not actually
get it, although it can still use connection pooling.

Bug: 6124556
Change-Id: Ia2ffdbbc8f82721b170f3bf71bd5242dfd56d9ac
2012-03-22 14:53:01 -07:00
Jean-Baptiste Queru
7364477528 Fix typo... and build
Change-Id: Ifc3c99c1e43423d0419031c7a389738b2232c6bd
2012-03-21 19:24:32 -07:00
Jeff Brown
e67ca420e4 Throw if WAL enabled/disabled when connections are in use.
Changing WAL mode requires obtaining an exclusive lock on the
database and can only be done when there are NO other active
database connections.

Check that this is really the case, and bail with a useful
error message if an application attempts to change WAL mode while
transactions are in progress.

Expose disableWriteAheadLogging() in the API.

Change-Id: I87599de3b88c53dcd75677aefd72e40de216c2c1
2012-03-21 18:08:09 -07:00
Jeff Brown
1d9f742e00 Port the SQLite locale setting code to Java.
Make the database opening code more robust in the case of
read-only database connections.

Check whether a PRAGMA needs to be issues before doing it.
Mostly it's harmless but it can grab a transaction on the
database unnecessarily.

Change-Id: Iab2cdc96c785e767f82966b00597e19337163f2f
2012-03-15 16:02:58 -07:00
Jeff Brown
fb5a4964b8 Prefetch column names in bulk cursor adaptor.
If the remote end of a bulk cursor died, then it was possible
for getColumnNames() to return null, violating the invariant
that it never returns null.  As a result, the application could
crash in strange ways due to an NPE.

Since we are often interested in the column names anyhow, prefetch
them when setting up the bulk cursor adaptor.  This way, a
remote cursor will never return null even if the remote end died.

It is possible for an application to continue to use a remote cursor
even after the provider has died unless it needs to requery it
for some reason.  Of course at that point, bad things will
happen... but usually the app is better prepared for it than
if it just randomly encounters a null array of column names.

This change also optimizes the bulk cursor adaptor to return the
initial cursor window back to the client, potentially saving
an extra RPC.  Because the communication protocol between
the CursorToBulkCursorAdaptor and BulkCursorToCursorAdaptor was
getting a little hard to follow, introduced a new type called
BulkCursorDescriptor to hold all of the necessary parameters.

Deleted several unnecessary IBulkCursor methods that are never
actually called remotely.

Bug: 6168809
Change-Id: I9aaf6f067c6434a575e2fdbf678243d5ad10755f
2012-03-14 18:51:07 -07:00
Jeff Brown
b2679481b5 Fix potential NPE in SQLiteProgram.
Bug: 6122537
Change-Id: I76a12f58f08b708065dfdd11c78f54701d90873b
2012-03-12 15:35:28 -07:00
Jeff Brown
03bd302aeb Don't close the database until all references released.
SQLiteDatabase.close() should call releaseReference() rather than
closing the database immediately.  SQLiteDatabase should also hold
a reference to itself while performing certain operations to
ensure that they complete normally even if another thread closes
the database at the same time.

Fixed a couple of missing or redundant uses of acquireReference()
related to CursorWindows.

To be honest, the reference counting performed by SQLiteClosable should
not be needed, but we're stuck with it in the API.

Bug: 6104842
Change-Id: I3444a697409905d4a36b56418dc7766f5ba76b59
2012-03-06 16:42:56 -08:00
Jeff Brown
baefdfad6e Make SQLiteDatabase final.
The SQLiteDatabase constructor is inaccessible so it is not
possible for applications to subclass it.  To remove all possible
remaining temptation to do so, make the class final.

Change-Id: I4148e9b06f0661ec22aab8e45afde38498d2375a
2012-03-05 13:24:02 -08:00
Jeff Brown
8dc3cc2e13 Allow the SQLite sync mode to be set independently for WAL.
This change leaves the sync mode at FULL for both WAL and non-WAL
but makes it easy to change it for one but not the other.

To reduce the number of synchronous writes, it might make sense to
change the sync mode for non-WAL to NORMAL instead of FULL which
should be just as safe.

On the other hand, the sync mode for WAL should probably remain FULL
because there may be an impact on transaction durability otherwise.

Initial experiments show that there might not be a significant
performance benefit to using NORMAL, but we may revisit this later.

Change-Id: Ifcd55bedcfefa6600974c2295ca5d4163b408cbf
2012-03-02 11:17:16 -08:00
Jeff Brown
79087e4b96 Add an API for deleting databases.
Add SQLiteDatabase.deleteDatabase to delete a database and all
of its auxiliary files.

This method is also used by Context.deleteDatabase and resolves issues
where auxiliary files would get left behind.

Bug: 5972489
Change-Id: I3633b9b4978972a1d240ac0a9861420ecf989149
2012-03-01 19:56:53 -08:00
Jeff Brown
638eff7ee1 Improve documentation of SQLite debugging options.
Change-Id: Id3b4d9e4e9dd62d2a1e6188477225af7717788f4
2012-03-01 10:21:29 -08:00
Jeff Brown
5936ff097e Externalize more SQLite configuration options.
Moved more configuration into config.xml so we can tweak settings
like the default journal mode, WAL auto-checkpoint interval and
so on.

This change itself should not introduce any functional differences.

Change-Id: Id6c95fa25b116ce47e8ae49cd8a80d52b1c0dd80
2012-02-29 21:03:20 -08:00
Jeff Brown
559d0645ac Refactor SQLiteOpenHelper.
Combine the code for opening readable and writable databases.
This improves the handling of the case where a database cannot
be opened because it cannot be upgraded.  Previously we would
open the database twice: first read-write, then read-only, each
time failing due to the version check.  Now only open it once.

Removed the goofy locking logic related to upgrading a read-only
database to read-write.  We now do it in place by reopening the
necessary connections in the connection pool.

Change-Id: I6deca3fb90e43f4ccb944d4715307fd6fc3e1383
2012-02-29 17:02:04 -08:00
Jeff Brown
4c1241df8f Rename CancellationSignal using preferred spelling.
Bug: 5943637
Change-Id: I12a339f285f4db58e79acb5fd8ec2fc1acda5265
2012-02-02 18:02:16 -08:00
Jeff Brown
b19a71a20a Support automatic cancellation of Loaders.
Change-Id: I18d3f49e413f48fcdd519d15e99c238ad54d35b9
2012-02-01 16:30:14 -08:00
Jeff Brown
2d2d7d6f42 Merge "Implement a cancelation mechanism for queries." 2012-01-27 17:37:24 -08:00
Jeff Brown
75ea64fc54 Implement a cancelation mechanism for queries.
Added new API to enable cancelation of SQLite and content provider
queries by means of a CancelationSignal object.  The application
creates a CancelationSignal object and passes it as an argument
to the query.  The cancelation signal can then be used to cancel
the query while it is executing.

If the cancelation signal is raised before the query is executed,
then it is immediately terminated.

Change-Id: If2c76e9a7e56ea5e98768b6d4f225f0a1ca61c61
2012-01-27 17:33:21 -08:00
Dianne Hackborn
43ea4e10dc Merge "Added JELLY_BEAN version name; update some targetSdkVersion docs." 2012-01-25 12:29:17 -08:00
Dianne Hackborn
81e9276a47 Added JELLY_BEAN version name; update some targetSdkVersion docs.
Change-Id: Ia38ff5b9ad2b63c2cf667260881222d9ff168052
2012-01-25 11:16:57 -08:00
Jeff Brown
ebc016c01e Fix an inconsistent comment.
Change-Id: Iae40dfcca091c9886a05e483f51596c96014e57f
2012-01-25 10:43:04 -08:00
Jeff Brown
d4e34d61d0 Merge "Inform ContentObservers about the changed content Uri." 2012-01-23 17:36:06 -08:00
Jeff Brown
b934a82139 Merge "Clean up content observer code." 2012-01-23 17:35:50 -08:00
Jeff Brown
655e66bceb Inform ContentObservers about the changed content Uri.
Added a new method ContentObserver.onChange(boolean, Uri) that
receives the changed content Uri.  This can help applications make
better decisions about how to interpret a change notification.

Change-Id: I8e35378b6485fe22c5bc240ba07557d269af0836
2012-01-23 17:28:29 -08:00
Jeff Brown
86de0590b9 Clean up content observer code.
Improved the documentation a little bit.

Fixed a bug in ContentService wherein if a ContentObserver was
passed as an argument and its deliverSelfNotifications() method
returned true, then notifyChange would tell all observers that
the change was a self-change even though it was only a self-change
from the perspective of the provided observer.

Deprecated ContentObservable.notifyChange since it is never
used and in general it shouldn't be because we want the notification
to be posted to the handler.

Change-Id: Idde49eb40777e011a068f2adae8a32f779dfb923
2012-01-23 13:01:18 -08:00
Jeff Brown
8bef9cb6b7 Merge "Delete dead code." 2012-01-20 16:20:24 -08:00
Jeff Brown
bd4c9f1302 Delete dead code.
This API has never been used or exposed, time for it to go away.

Change-Id: Ie199ed0731d0a620d6608b2adbea1083f87276cd
2012-01-20 16:18:46 -08:00
Jeff Brown
1bf599a01e Merge "Initialize SQLite as part of the android runtime." 2012-01-20 14:07:59 -08:00
Jeff Brown
4b57553e69 Initialize SQLite as part of the android runtime.
This ensures that the SQLite library is always correctly configured
and initialized before other framework or application code has
a chance to use it.  This is important because initialization has
to happen at most once so we need to get it right and prevent races.

This change makes it possible to omit the SQLite auto-initialization
workaround from the SQLite library, potentially saving a few cycles
here and there.

Change-Id: Ifbed8685ee44aa1e9c0b391e233b0257fa738e4f
2012-01-20 13:08:03 -08:00
Pin Ting
f17e7c272e Merge "Fixes some javadoc." 2012-01-20 01:37:12 -08:00
Jeff Brown
254fba8960 Clean up SQLiteDebug natives.
In particular, ensure that the database is initialized.

Change-Id: Ifa69a9dfa9d008af79beadbd1a25e90d0d29e66c
2012-01-19 18:13:18 -08:00
Jeff Brown
48a4789686 Remove custom SQLITE_UNCLOSED error code.
This error code was introduced at some point to help track when
a database could not be closed because a statement was not finalized.
Now that the DB wrappers have been rewritten, it is technically no longer
poossible for this to happen, so we can remove this.

Change-Id: Ibbd55debbf390af436d6533aebff9726b1ff29e7
2012-01-19 16:39:03 -08:00
Jeff Brown
2a293b61cb Clean up SQLite debugging code.
Deleted a bunch of dead / useless code.
Raised number of logged operations in dumpsys dbinfo to 20.

Change-Id: I88344ff57a978f200c1f0172141d91e430caa1a9
2012-01-19 14:02:22 -08:00
Jeff Brown
a9be4154e8 Fix issues with reentrant SQLite triggers.
Modified SQLiteConnection and SQLiteSession to support
reentrant execution of SQLite operations, as might occur
when a custom function is invoked by a trigger.

Bug: 5884809
Change-Id: I253d828b2801bd06b1bbda7caa7da3f040a642bb
2012-01-18 18:29:20 -08:00
Pin Ting
1c423b81de Fixes some javadoc.
Change-Id: I4ad1f1452e2c8e004865853247e0b34b78bb1616
2012-01-18 11:21:06 +08:00
Jeff Brown
e5360fbf3e Rewrite SQLite database wrappers.
The main theme of this change is encapsulation.  This change
preserves all existing functionality but the implementation
is now much cleaner.

Instead of a "database lock", access to the database is treated
as a resource acquisition problem.  If a thread's owns a database
connection, then it can access the database; otherwise, it must
acquire a database connection first, and potentially wait for other
threads to give up theirs.  The SQLiteConnectionPool encapsulates
the details of how connections are created, configured, acquired,
released and disposed.

One new feature is that SQLiteConnectionPool can make scheduling
decisions about which thread should next acquire a database
connection when there is contention among threads.  The factors
considered include wait queue ordering (fairness among peers),
whether the connection is needed for an interactive operation
(unfairness on behalf of the UI), and whether the primary connection
is needed or if any old connection will do.  Thus one goal of the
new SQLiteConnectionPool is to improve the utilization of
database connections.

To emulate some quirks of the old "database lock," we introduce
the concept of the primary database connection.  The primary
database connection is the one that is typically used to perform
write operations to the database.  When a thread holds the primary
database connection, it effectively prevents other threads from
modifying the database (although they can still read).  What's
more, those threads will block when they try to acquire the primary
connection, which provides the same kind of mutual exclusion
features that the old "database lock" had.  (In truth, we
probably don't need to be requiring use of the primary database
connection in as many places as we do now, but we can seek to refine
that behavior in future patches.)

Another significant change is that native sqlite3_stmt objects
(prepared statements) are fully encapsulated by the SQLiteConnection
object that owns them.  This ensures that the connection can
finalize (destroy) all extant statements that belong to a database
connection when the connection is closed.  (In the original code,
this was very complicated because the sqlite3_stmt objects were
managed by SQLiteCompiledSql objects which had different lifetime
from the original SQLiteDatabase that created them.  Worse, the
SQLiteCompiledSql finalizer method couldn't actually destroy the
sqlite3_stmt objects because it ran on the finalizer thread and
therefore could not guarantee that it could acquire the database
lock in order to do the work.  This resulted in some rather
tortured logic involving a list of pending finalizable statements
and a high change of deadlocks or leaks.)

Because sqlite3_stmt objects never escape the confines of the
SQLiteConnection that owns them, we can also greatly simplify
the design of the SQLiteProgram, SQLiteQuery and SQLiteStatement
objects.  They no longer have to wrangle a native sqlite3_stmt
object pointer and manage its lifecycle.  So now all they do
is hold bind arguments and provide a fancy API.

All of the JNI glue related to managing database connections
and performing transactions is now bound to SQLiteConnection
(rather than being scattered everywhere).  This makes sense because
SQLiteConnection owns the native sqlite3 object, so it is the
only class in the system that can interact with the native
SQLite database directly.  Encapsulation for the win.

One particularly tricky part of this change is managing the
ownership of SQLiteConnection objects.  At any given time,
a SQLiteConnection is either owned by a SQLiteConnectionPool
or by a SQLiteSession.  SQLiteConnections should never be leaked,
but we handle that case too (and yell about it with CloseGuard).

A SQLiteSession object is responsible for acquiring and releasing
a SQLiteConnection object on behalf of a single thread as needed.
For example, the session acquires a connection when a transaction
begins and releases it when finished.  If the session cannot
acquire a connection immediately, then the requested operation
blocks until a connection becomes available.

SQLiteSessions are thread-local.  A SQLiteDatabase assigns a
distinct session to each thread that performs database operations.
This is very very important.  First, it prevents two threads
from trying to use the same SQLiteConnection at the same time
(because two threads can't share the same session).
Second, it prevents a single thread from trying to acquire two
SQLiteConnections simultaneously from the same database (because
a single thread can't have two sessions for the same database which,
in addition to being greedy, could result in a deadlock).

There is strict layering between the various database objects,
objects at lower layers are not aware of objects at higher layers.
Moreover, objects at higher layers generally own objects at lower
layers and are responsible for ensuring they are properly disposed
when no longer needed (good for the environment).

API layer: SQLiteDatabase, SQLiteProgram, SQLiteQuery, SQLiteStatement.
Session layer: SQLiteSession.
Connection layer: SQLiteConnectionPool, SQLiteConnection.
Native layer: JNI glue.

By avoiding cyclic dependencies between layers, we make the
architecture much more intelligible, maintainable and robust.

Finally, this change adds a great deal of new debugging information.
It is now possible to view a list of the most recent database
operations including how long they took to run using
"adb shell dumpsys dbinfo".  (Because most of the interesting
work happens in SQLiteConnection, it is easy to add debugging
instrumentation to track all database operations in one place.)

Change-Id: Iffb4ce72d8bcf20b4e087d911da6aa84d2f15297
2012-01-12 14:56:18 -08:00