Commit Graph

312 Commits

Author SHA1 Message Date
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
Jeff Brown
5a05c23f3d Clean up database tests a little bit.
Change-Id: Ib05c699bf59187cb51627b5f352c2a15ad2c28bb
2012-01-12 14:37:57 -08:00
Elliott Hughes
6746499f12 Fix Music import for Turkish locales.
For non-localized strings like the keywords in SQL statements, we shouldn't use
locale-specific case transformations.

(Cherry pick of 03f8f84c345e7c861a6de889d434b9d82cf04c8d.)

Bug: 4284951
Change-Id: Ib5180daf7892af7b645c906fdfeacf9da87bd667
2012-01-03 17:20:38 -08:00
Jeff Brown
6754ba24f1 Add plumbing for dumping database info using dumpsys.
Change-Id: I51b0364c3d3d41aa38a759fbce48e625fff1b2dd
2011-12-16 04:01:00 -08:00
Jeff Brown
d5064be3b5 Make SQLiteQuery and SQLiteProgram final.
We can do this because the classes already cannot be subclassed
by applications due to the fact they only have package private
constructors.

One very nice consequence of this observation is that we can hide or
delete several @deprecated protected members which are effectively
inaccessible because applications cannot create subclasses!

Change-Id: I2d3a0d2ad72b9289ebcdf907e4e4e6caf27f9076
2011-12-16 03:59:26 -08:00
Jeff Brown
603f97f324 Fix JavaDoc typos.
Change-Id: Ieabcd5b89c89440f425917319225735445324765
2011-11-08 20:24:21 -08:00
Jeff Brown
fa59cfbc85 resolved conflicts for merge of bce45617 to master
Change-Id: Ieb966e674dca3ec46cd3cd25e4de281f1be747c2
2011-10-31 15:10:10 -07:00
Jeff Brown
bce4561708 resolved conflicts for merge of 2d280f75 to ics-mr1
Change-Id: I459e1cb0b60fb94dfb12862fedb9f8d949c226a7
2011-10-30 14:24:02 -07:00
Jeff Brown
2d280f754e Merge "Improve the slow query instrumentation." into ics-mr0 2011-10-28 18:21:05 -07:00
Jeff Brown
89101cd9d9 Improve the slow query instrumentation.
On user-debug and eng builds, you can set the
"db.log.slow_query_threshold" system property to queries that
take longer than the specified number of milliseconds.
Set it to 0 to log all queries.

This property has been around for a while but it was implemented
poorly.  In particular, it *changed* the behavior of the query
by calling getCount() while holding the Db connection.
In normal operation, the query will not actually run until later.

By putting the timing logic into fillWindow() instead, we ensure
that we only measure queries that actually ran.  We also capture
cases where the cursor window gets filled multiple times.

Bug: 5520301
Change-Id: I174f5e1ea15831a1d22a36e9a804d7755f230b38
2011-10-28 14:58:39 -07:00
Jeff Brown
650de3dcfc Optimize fillWindow to improve reverse-seek performance.
Bug: 5520301

When an application requests a row from a SQLiteCursor that
is not in the window, instead of filling from the requested
row position onwards, fill from a little bit ahead of the
requested row position.

This fixes a problem with applications that seek backwards
in large cursor windows.  Previously the application could
end up refilling the window every time it moved back
one position.

We try to fill about 1/3 before the requested position and
2/3 after which substantially improves scrolling responsiveness
when the list is bound to a data set that does not fit
entirely within one cursor window.

Change-Id: I168ff1d3aed1a41ac96267be34a026c108590e52
2011-10-28 01:46:18 -07:00
Jeff Brown
ce6578acc5 am 84bee4f8: Merge "Fix copyStringToBuffer row index calculation. Bug: 5515552" into ics-mr0
* commit '84bee4f8746a19428e0ddfd10df1130324dc39fa':
  Fix copyStringToBuffer row index calculation. Bug: 5515552
2011-10-28 08:20:20 +00:00
Jeff Brown
0772007b61 Fix copyStringToBuffer row index calculation.
Bug: 5515552

Change-Id: I60aa25d2becd3195d6997d23ef5654a31e93bf71
2011-10-27 19:27:11 -07:00
Jeff Sharkey
7978a414bb Only populate stack when StrictMode will use it.
When the StrictMode VM flag is changed mid-lifecycle, pass along at
least a basic trace.

Bug: 5516561
Change-Id: I6c922ba20f34349c35624cfc04d1c71ee56ad6ef
2011-10-26 10:43:51 -07:00
Michael Chan
cf0ca99a22 Fix typos
Change-Id: I6406b33f52bd8fb126a9b346d1bfe30ca2c2144b
http://code.google.com/p/android/issues/detail?id=14614
http://code.google.com/p/android/issues/detail?id=3563
http://code.google.com/p/android/issues/detail?id=5960
2011-10-20 15:32:37 -07:00
Jeff Brown
825c5132bf Add a CrossProcessCursorWrapper.
Bug: 5220669

The CrossProcessCursorWrapper is a useful building block
for wrapping cursors that will be sent to processes remotely.
It can also transform normal Cursors into CrossProcessCursors
transparently.

The new class fixes common performance problems and bugs
that applications have encountered when implementing
ContentProviders.

Change-Id: Icc59fec10add3f7d8cfbd0495447860c1872c752
2011-10-13 14:24:26 -07:00
Jeff Brown
b4009c7381 AbstractWindowedCursor is not special.
Use the CrossProcessCursor interface in the way it was intended
without introducing special cases for AbstractWindowedCursor.
This is possible now that we do not distinguish between local-only
and remotable CursorWindows so we don't need to provide a window
to the AbstractWindowedCursor for it to fill; it can provide one
for itself if it wants one.

This logic makes it possible to create CrossProcessCursor
implementations that perform just as well as AbstractWindowedCursors.

Change-Id: I764b25ee6311d28c50d1930705346b265faec86a
2011-10-13 14:17:24 -07:00
Jeff Brown
80e7b80fa6 Make default implementation of fillWindow typesafe.
Bug: 5218310

This change fixes problems calling the default fillWindow
on Cursors that contain BLOBs.  It should also be more efficient
by avoiding redundant string conversions for numeric datatypes.

Change-Id: Ied515bf6299bc8d3c14e76055d85fd35e7c05952
2011-10-12 22:19:42 -07:00
Jeff Brown
5e5d6d8ba0 Deprecate local-only CursorWindows.
There is no difference and has never really been a difference
between local-only and remotable CursorWindows.  By removing the
distinction officially in the API, we will make it easier to
implement CrossProcessCursor correctly.  CrossProcessCursor
is problematic currently because it's not clear whether a call
to getWindow() will return a local-only window or a remotable window.
As a result, the bulk cursor adaptor has special case handling
for AbstractWindowedCursors vs. ordinary CrossProcessCursors
so that it can set a remotable window before the cursor fills it.
All these problems go away if we just forget about local-only
windows being special in any way.

Change-Id: Ie59f517968e33d0ecb239c3c4f60206495e8f376
2011-10-12 22:19:41 -07:00
Jeff Brown
0cde89f5f0 Use ashmem for CursorWindows.
Bug: 5332296

The memory dealer introduces additional delays for reclaiming
the memory owned by CursorWindows because the Binder object must
be finalized.  Using ashmem instead gives CursorWindow more
direct control over the lifetime of the shared memory region.

The provider now allocates the CursorWindows and returns them
to clients with a read-only protection bit set on the ashmem
region.

Improved the encapsulation of CursorWindow.  Callers shouldn't
need to care about details like how string fields are allocated.

Removed the compile-time configuration of string and numeric
storage modes to remove some dead weight.

Change-Id: I07c2bc2a9c573d7e435dcaecd269d25ea9807acd
2011-10-11 11:03:19 -07:00
Jeff Brown
d2183654e0 Fix ownership of CursorWindows across processes.
Bug: 5332296

Ensure that there is always an owner for each CursorWindow
and that references to each window are acquired/released
appropriately at all times.

Added synchronization to CursorToBulkCursorAdaptor to
prevent the underlying Cursor and CursorWindow from being
remotely accessed in ways that might violate invariants,
resulting in leaks or other problems.

Ensured that CursorToBulkCursorAdaptor promptly releases
its references to the Cursor and CursorWindow when closed
so they don't stick around longer than they should, even
if the remote end hangs onto the IBulkCursor for some reason.

CursorWindow respects Parcelable.FLAG_WRITE_RETURN_VALUE
as an indication that one reference to the CursorWindow is
being released.  Correspondingly, CursorToBulkCursorAdaptor
acquires a reference to the CursorWindow before returning
it to the caller.  This change also prevents races from
resulting in the transfer of an invalid CursorWindow over
the wire.

Ensured that BulkCursorToCursorAdaptor promptly releases
its reference to the IBulkCursor when closed and throws
on attempts to access the cursor while closed.

Modified ContentProviderNative to handle both parts of
the wrapping and unwrapping of Cursors into IBulkCursors.
This makes it a lot easier to ensure that the right
things happen on both ends.  Also, it turns out that
the only caller of IContentProvider.bulkQuery was
ContentProviderNative itself so there was no need
to support bulkQuery on ContentProviderProxy and it was
just getting in the way.

Implement CloseGuard on CursorWindow.

Change-Id: Ib3c8305d3cc62322f38a06698d404a2989bb6ef9
2011-10-09 22:10:36 -07:00
Jeff Brown
df6611d8c0 Clean up handrolled Binder proxies.
Bug: 5332296

We can't replace these with AIDL generated proxies just yet, but
at least we can make them a little more conformant.

Change-Id: I1814f76d0f9c5e44a7fd85a12b2e3c2b7e3c9daa
2011-10-09 13:00:35 -07:00
Jeff Brown
270928bd4a Merge changes Idbfeb3cc,I03e8e2e7,Iff9eed78
* changes:
  Fix regression in CursorWindow.getString() Bug: 5332296
  Clean up CursorWindow lifetime. Bug: 5332296
  Fix regression in CursorWindow.copyStingToBuffer. Bug: 5332296
2011-10-07 15:08:24 -07:00
Jeff Brown
7ce745248d Clean up CursorWindow lifetime.
Bug: 5332296

Removed dead code in SQLiteCursor related to the use of a background
query thread.  This code could result in CursorWindows being modified
concurrently or used after free.  This code is broken, unused and
is just in the way.

Added comments to explain how CursorWindow ownership is
supposed to work for AbstractWindowedCursors.  (There are still cases
where cursor windows get dropped on the floor without being closed.
Those will be taken care of in a subsequent patch.)

Cleaned up SQLiteQuery.fillWindow to eliminate duplicate code and
remove bits that were only needed for background loading, like
returning -1.

Change-Id: I03e8e2e73ff0c11df76d63f57df4c5ada06ae1cb
2011-10-07 13:31:00 -07:00
Jeff Brown
f0a9181d09 Merge "Clean up CursorWindow code. Bug: 5332296" 2011-10-06 16:28:15 -07:00
Jeff Brown
3bc6bbc92c Clean up CursorWindow code.
Bug: 5332296

The code is functionally equivalent, but a little more efficient
and much easier to maintain.

Change-Id: I90670a13799df05831843a5137ab234929281b7c
2011-10-06 14:40:13 -07:00
Christopher Tate
ad9e8b1a87 Disable db_sample logging
db_sample logging is thrashing the event log hard, and is currently
neither maintained nor heeded by anybody on the current release.  It
can be re-enabled simply by throwing the appropriate static boolean
to 'true', but for now this should greatly improve the utility of our
event logs.  (We were seeing a rollover period of 20 minutes or less;
ideally we want to see the event log run at least half a day before
rolling.)

Bug 5419627
Bug 5104300

Change-Id: I2125544130aae142974102dbad3b557e49fcd494
2011-10-05 17:49:26 -07:00
Makoto Onuki
630f6b1cf8 Add AbstractCursor.setExtras()
This allows providers to return SQLiteCursor with a bundle, without wrapping
it in a CursorWrapper, which has performance penalty on cross-process
queries.

Bug 5220669

Change-Id: I46b9dfb3d8e01e9caf080bb24acfd97551441e25
2011-08-31 14:17:55 -07:00
Dianne Hackborn
661cd52e0e Add progress dialog for booting after an upgrade.
This introduces a new facility for code during the boot process
to display messages to the user through a progress dialog.  This
is only for use when performing longer-than-usual post-upgrade
operations such as running dexopt on applications or upgrading
databases.

Change-Id: I0e78439ccec3850fb67872c22f235bf12a158dae
2011-08-22 13:42:05 -07:00
Todd Kennedy
783123f79d Add getBlob() to MatrixCursor
Change-Id: I1abfd2fd117a2a31f99e77bd0b395c4ad0cfc6d2
2011-07-19 10:33:41 -07:00
Daniel Lehmann
9f66c650b0 Remove the obsolete function that is not used anymore
Change-Id: I749d4bdba68edb87fe7eb24095e70b544da00c71
2011-06-01 20:40:50 -07:00
Daniel Lehmann
50b1f8d3fc Enable strict mode as a public api to catch sql injections
Bug: 4368912
Change-Id: Ia4919f58cc5264da8758d6cd61d93e031676b74a
2011-06-01 15:24:23 -07:00
Joe Onorato
43a17654cf Remove the deprecated things from Config.java. These haven't been working since before 1.0.
Change-Id: Ic2e8fa68797ea9d486f4117f3d82c98233cdab1e
2011-04-07 19:23:05 -07:00
Vasu Nori
cc1eaf6f7b bug:4090903 allow bindargs on attach database statement
code incorrectly assumed that certain statements (like ATTACH DATABASE)
will never have bindargs.

Change-Id: I62eddbdf8e15947e8debf5052c7248113a3b9b57
2011-03-21 16:02:25 -07:00
Vasu Nori
16057fad00 fix broken logTimeStat stuff
log time in the following 2 situations
1. all transactions. time measured = wall time between begin-commit
2. queries (which are not in tranactions)

Change-Id: I67be9487a96072695aff3529ba4a257f4c8ec596
2011-03-18 16:10:39 -07:00
Vasu Nori
d6c367f424 cosmetic fixes: removing unused members/imports
Change-Id: I307e5d5c7c1270d2590ba66f4c3d3b1a96646344
2011-03-01 18:37:52 -08:00
Vasu Nori
8a358a7eed bug:3497143 don't print warning if it is a bug in platform - not in app.
fixing a couple of very confusing warnings..

Change-Id: I3c91fa53fc73a2fb4bee213e33af56c4bdb75fd8
2011-03-01 18:22:31 -08:00
Jesse Wilson
32c80a27da Handle rename of LruCache.entryEvicted to entryRemoved
Change-Id: I50e5a8d8c35c4431f42c7483172447ba0e4e125b
http://b/3461302
2011-02-25 17:28:41 -08:00
Paul Westbrook
dae6d3705d Revert "turn off sqlite WAL until bugs bug:3024421 and bug:3353077 are fixed"
This reverts commit d67dbeeb32.

This reenables WAL in the framework.  We are tracking down the cause of
the problems with WAL
2011-02-17 10:59:56 -08:00
Dmitri Plotnikov
06f992c6b0 Merge "Setting copiedSize to 0 when value is null" 2011-02-16 13:15:15 -08:00
Dmitri Plotnikov
9480efeff7 Setting copiedSize to 0 when value is null
Bug: 3457998
Change-Id: I01f6d02e76884639600c679518c5817ce73e0f23
2011-02-16 12:03:10 -08:00
Vasu Nori
c5d0fbbfdf Merge "add more debug info to help (bug:3446432)" 2011-02-11 16:57:40 -08:00
Vasu Nori
e9714e6c74 add more debug info to help (bug:3446432)
Change-Id: I4a690297ae7f18d5f6928ac5c67d8d4164453fa0
2011-02-11 16:50:51 -08:00
Jesse Wilson
dfe515e49a Remove LruCache.setMaxSize().
Dynamically changing a max cache size is clumsy; almost everyone
should set this when they create the cache.

Fix SQLiteDatabase to copy entries into a new cache when the size
is changed. In pratice this will always be immediately after the
SQLiteDatabase is created. Since the cache field is no longer
final, change the guard on the cache field to the SQLiteDatabase
instance itself.

Change-Id: I4e325f06edc551636723568a52770c0982e2d945
2011-02-11 11:35:22 -08:00
Jesse Wilson
c2c9a2492c Don't add setMaxSize() to the LruCache API. But do add maxSize().
Change-Id: I9697ab29491dabe85c2400defdde16b9abcd003a
2011-02-10 19:20:31 -08:00
Jesse Wilson
9b5a93550f Adopt LRU cache in SQLite.
Change-Id: I6b43dd8843d41726254bea3a175fe28f5f061ed7
http://b/3184897
2011-02-10 18:26:39 -08:00
Vasu Nori
d67dbeeb32 turn off sqlite WAL until bugs bug:3024421 and bug:3353077 are fixed
they are becoming pretty disruptive bugs.
many more instances of gmail crashing with locking protocol error.
and a positive identification of WAL as the problem in Music app
AND one instance of gmail crash that I know of.
who knows how many folks are NOT reporting the gmail crash.

too bad we relied on pre-released version sqlite feature
without seeing it complettly tested in the field.

not a safe feature to turn on at this point in time.
maybe more testing and debugging in Ice timeframe.

Change-Id: I283ad26ba7e1793772a372aa8e24df0cb96ce2ef
2011-02-09 10:52:51 -08:00
Vasu Nori
d4608a35e8 while waiting for lock, try in 30sec intervals and print warnings if no lock
should help a little bit in debugging deadlocks in the process.
especially when the an application does this:
  thread1: begin transaction
  thread2: synchronized void blahMethod { do some code; begintransaction;}
  thread1: with lock ion the database, it now tries to get into the above
           synchronized method
   thread2 has synchronized monitor and thred1 has db lock.
   each wants the other lock
 deadlock.
and our stacktraces will not tell us that thread1 has the database lock.

with this CL, we will know WHO owns the database lock and which thread
dies waiting for the lock.

Change-Id: If51578e7fa0a70ee3d762eb2233d1fddd98a2e86
2011-02-07 11:08:41 -08:00
Vasu Nori
83ff97d840 bug:3385018 don't print finalizer warnings under certain conditions
Change-Id: I06c49a464f61c26d3e6645a95f2dd38d444bf384
2011-01-30 14:42:36 -08:00
Vasu Nori
a017edace7 bug:3398527 return List insttead of ArrayList from public API
Change-Id: Idbdcb59fe860a9168c9ef6c00eb128b05fce84ff
2011-01-27 11:47:28 -08:00