[sqlite] ESC_BAD_ACCESS when using a background thread

2015-09-01 Thread Jeff M
I'm the OP, just closing the loop on this thread.  I solved the crashing and 
the memory allocation issues.  The crashing was due to NSMutableDictionary not 
being thread safe (can't do setObject:forKey on a background thread).  The 
memory allocation issue (memory kept increasing) was due to a proliferation of 
un-finalized prepared statements.

All my bad -- I'm fessing up.  Thank you for your suggestions.

Jeff



[sqlite] ESC_BAD_ACCESS when using a background thread

2015-08-25 Thread Jeff M
On Aug 24, 2015, at 11:50 AM, Roger Binns  wrote:
> On 08/24/2015 03:08 AM, Jeff M wrote:
>> I've checked all of your suggestions and nothing is amiss.
> 
> You ran valgrind and it said everything is fine?  That would be shocking.

You caught me.  I wasn't familiar with valgrind, so I passed over that 
suggestion.  I tried to install valgrind (on Mac OS Yosemite), but I can't get 
it to compile.  I don't have the fortitude to work out the install issues.

Looking at Xcode's memory report (and using Instruments), I see that memory 
does ratchet up, despite my being very careful matching alloc/releases (this 
app is pre-ARC).  I need to relearn Instruments.  Among other things, I see 
many persistent 4K memory blocks resulting from sqlite3MemRealloc, but I 
haven't figured out the call tree to get there.

On Aug 24, 2015, at 11:50 AM, Roger Binns  wrote:
> ... there is [likely] a bug in [your] code related to object/pointer 
> lifetimes or similar.  [C]hanging things changes where collateral damage 
> happens, but doesn't actually fix the issue.

Yup.

Jeff




[sqlite] ESC_BAD_ACCESS when using a background thread

2015-08-24 Thread Jeff M
Simon, Roger:

I've checked all of your suggestions and nothing is amiss.

The background thread fetches the image data and caches it by adding the data 
to an NSMutableDictionary.  The main thread checks the dictionary and does the 
lazy-load only if the desired image data is not in the cache.

When the exception occurs on the main thread, execution stops where the 
dictionary is being checked (via objectForKey:), and the lazy-load background 
thread is executing inside of sqlite_step (sqlite_step has not returned when 
the exception occurs on the main thread).

This perplexes me.  I don't understand how the main thread can run before the 
background task has completed -- and specifically while sqlite_step is still 
executing.  Apparently, sqlite_step() can relinquish control to the main 
thread.  I'd appreciate some enlightenment on this implementation issue.

My solution -- The problem goes away if I move the caching step 
(setObject:forKey:) to the main thread (via 
dispatch_async(dispatch_get_main_queue() ).  It was intermittent so I can't be 
certain, but I've not been able to force a crash since making that change.

Jeff


> On Aug 23, 2015, at 7:05 AM, Simon Slavin  wrote:
> 
> Are you checking the values returned by sqlite3_prepare, sqlite3_bind, and 
> sqlite3_step, to make sure they return SQLITE_OK ?

> On Aug 23, 2015, at 7:00 PM, Roger Binns  wrote:
> 
> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA1
> 
> On 08/23/2015 03:31 AM, Jeff M wrote:
>> sqlite3_step();   // occasionally crashes here (showing
>> ESC_BAD_ACCESS on main thread)
> 
> That has three very likely causes.  The first is that your internal
> state gets messed up, and the statement has actually been
> finalized/freed.  ie it is junk memory.  You can add assertions that
> check it is still a known statement pointer by checking this returns it:
> 
>  http://sqlite.org/c3ref/next_stmt.html
> 
> The second is that the memory where you stored the statement pointer
> is what is trashed.
> 
> The final cause is that some other code has memory bugs, causing
> damage to SQLite's data structures.
> 
>> It's not a zombie object issue (tested with NSZombieEnabled).
> 
> Sadly that only checks Objective C objects, and not all memory.
> 
>> Any ideas on how to debug this?
> 
> I used valgrind running the app in the simulator.  (I also configure
> valgrind to never actually reuse memory.)
> 
> Roger
> -BEGIN PGP SIGNATURE-
> Version: GnuPG v1
> 
> iEYEARECAAYFAlXaXpEACgkQmOOfHg372QRKZACfWyT6pEyNQ9sEKPbhFQ4pI/5G
> Nh0AniO5ESx9CIbB484/gYqjtfCsGUrM
> =Op+8
> -END PGP SIGNATURE-
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users



[sqlite] ESC_BAD_ACCESS when using a background thread

2015-08-23 Thread Jeff M
My iOS app displays a gallery of thumbnails in a tableView (four to a row).  To 
allow smooth scrolling, I lazy-load the image data on a background thread using 
dispatch_async().

sqlite3_threadsafe() returns true.
sqlite3_open_v2() uses SQLITE_OPEN_FULLMUTEX.
queue is a serial queue from dispatch_queue_create(...).
There is only one connection to the database.

lazy load summary logic:
   dispatch_async(queue, ^{
done once:  sqlite3_prepare_v2( "SELECT ..." ... );

sqlite3_bind_int(...);
sqlite3_bind_int(...);
sqlite3_step();   // occasionally crashes here (showing ESC_BAD_ACCESS 
on main thread)
... sqlite3_column_blob(...);
... sqlite3_column_bytes(...);
// ...
// occasionally crashes here (showing ESC_BAD_ACCESS on main thread) 
not inside SQLite
// ...
sqlite3_reset();
   });

The main thread is not doing anything with the DB when the crash occurs (it has 
previously loaded an array with all the id values needed for the lazy-load's 
SELECT statement).  It doesn't crash very often (might take 10, 20 or 30 
trials), but when it happens, it crashes while loading one of the first few 
thumbnails.

It's not a zombie object issue (tested with NSZombieEnabled).

Any ideas on how to debug this?

Jeff




[sqlite] When sqlite3_close() returns SQL_BUSY

2015-08-22 Thread Jeff M
The doc page for SQLITE_BUSY covers SQLITE_BUSY when there are multiple 
connections to the database.

SQLite Result Codes (SQLITE_BUSY)
http://www.sqlite.org/rescode.html#busy

But, I have only one connection.  I believe the case where SQLITE_BUSY is 
returned by sqlite_close() due to unfinalized prepared statements should be 
mentioned there.

Jeff


> On Aug 21, 2015, at 3:51 AM, R.Smith  wrote:
> 
> Hi Jeff,
> 
> On 2015-08-21 07:30 AM, Jeff M wrote:
>> Sometimes my iOS app creates an unreasonable number of prepared statements 
>> (perhaps 1,000, an app bug that I'm fixing).  These prepared statements are 
>> later finalized just prior to doing sqlite3_close(), which sometimes returns 
>> SQL_BUSY.  The docs say SQL_BUSY will be returned if I haven't finalized all 
>> prepared statements, but I believe I have done so.  My iOS app has only one 
>> connection to the DB and I'm doing all this work on the main thread.
>> 
>> 1.  The docs don't say what to do in the case of SQL_BUSY.  Does that mean 
>> I've certainly failed to finalize one or more prepared statements, or does 
>> SQLite just need more time (in which case can I loop on sqlite3_close() 
>> until I get SQLITE_OK)?
> 
> SQL_BUSY does not mean anything bad except that you are trying to do some 
> work on a query (read: prepared statement) while another is still not done 
> with its duties. These duties may in your case simply mean that the "closing" 
> of a previous prepared statement is still under way, so yes, it just needs a 
> moment. You can wait a moment and try again.
> 
> I will mention (as Simon is likely to point out soon!) that the good news is: 
> SQLite will do this waiting-and-retrying for you if you simply set a suitable 
> time-out, perhaps in the order of a minute or more, using the pragma:
> 
> http://www.sqlite.org/pragma.html#pragma_busy_timeout
> 
> or, if you prefer using the C-interface:
> http://www.sqlite.org/c3ref/busy_timeout.html
> 



[sqlite] When sqlite3_close() returns SQL_BUSY

2015-08-21 Thread Jeff M
Sometimes my iOS app creates an unreasonable number of prepared statements 
(perhaps 1,000, an app bug that I'm fixing).  These prepared statements are 
later finalized just prior to doing sqlite3_close(), which sometimes returns 
SQL_BUSY.  The docs say SQL_BUSY will be returned if I haven't finalized all 
prepared statements, but I believe I have done so.  My iOS app has only one 
connection to the DB and I'm doing all this work on the main thread.

1.  The docs don't say what to do in the case of SQL_BUSY.  Does that mean I've 
certainly failed to finalize one or more prepared statements, or does SQLite 
just need more time (in which case can I loop on sqlite3_close() until I get 
SQLITE_OK)?

2.  Does SQLite keep a record of prepared statements?  If so, is there a way I 
can ask SQLite to close them all, or are there any tricks to debugging which 
statements have not been finalized?

Jeff



[sqlite] Extending VFS documentation

2015-05-24 Thread Jeff M
I searched stack overflow for "sqlite3_vfs_register" and got a few hits.  For 
example, this was a good starting point on which I based my own VFS.

 http://stackoverflow.com/a/3842409/236415

Jeff


> On May 24, 2015, at 4:39 AM, Philip Bennefall  wrote:
> 
> Hi all,
> 
> I have been interested in the VFS layer of SqLite for a while, and found the 
> following article to be very useful:
> 
> http://www.sqlite.org/vfs.html
> 
> However, it ends right when it is about to go into the actual details of how 
> to implement a VFS. It would be great if that essay could be completed. I
> have looked at the example VFS implementations, but it is hard to determine 
> which parts of the code that are implementation details as opposed to being
> part of the stable public API so to speak.
> 
> Kind regards,
> 
> Philip Bennefall
> 



[sqlite] Copying an open DB file (iOS)

2015-05-08 Thread Jeff M
I'm using SQLite (via FMDB) with an on-disk database in several iOS apps.  In 
each case, the DB file is only used by the one app and there's no DB activity 
on background threads.  The apps have a backup feature (initiated by the user) 
that simply copies the database file.  There is no other activity (in my app) 
when the backup is started (all reads and writes would have been completed at 
least a few seconds earlier), and I'm not concerned about a power or system 
failure during the copy.  For a restore, the current DB is closed, then a 
backup file is copied in and opened.

I've been using this scheme for years without a problem.  But, should I flush, 
or close, or lock before the copy?

Jeff



[sqlite] Integrating sqlite with Core Data and iCloud

2015-04-25 Thread Jeff M

> On Apr 24, 2015, at 2:44 AM, Simon Slavin  wrote:
> 
> On 24 Apr 2015, at 6:59am, Jeff M  wrote:
> 
>> I don't need to map SQLite to iCloud -- I only need to map SQLite to Core 
>> Data.  Core Data then takes care of the iCloud issues.
> 
> I imagine you'd do that by writing a VFS which used Core Data for storage.  
> Core Data could store your data in any of the formats it has drivers for, 
> including plaintext files and SQLite.  And Core Data could store your data in 
> any medium it has drivers for, including local storage and iCloud.
> 
> The result might be slow and inefficient, since you're building a DBMS 
> (SQLite) on top of a DBMS (Core Data) on top of a DBMS (SQLite).
> 
> If you use Core Data the resulting file wouldn't look like a normal SQLite 
> database.  Core Data stores objects.  It doesn't store the rows and columns 
> you refer to with SQL commands.  Maybe your objects would be table rows.
> 
> Simon.

Originally, I wanted to map my tables, rows, and columns to similarly-named 
Core Data entities and attributes so I could continue to use the SQL language.  
I was hoping to hook into the SQL parser to get the benefits of where.c, but I 
realize now that's impractical.

Your suggestion of working at the file system level is interesting, but my 
objects would be disk blocks.  I could use a simple Core Data model: one entity 
(representing the entire database file) and create one object per block (each 
having a binary attribute containing one block of data).  It would be easy to 
map each file system read() and write() to the corresponding objects.  Using 
Core Data as a memory array would earn me the Kludge of The Year Award.  But, I 
see data corruption in my future.

Can you point me to some sample source code (outside of SQLite itself) that 
implements sqlite3_vfs_register()?

Jeff







[sqlite] Integrating sqlite with Core Data and iCloud

2015-04-24 Thread Jeff M
On Apr 23, 2015, at 3:51 PM, Simon Slavin  wrote:
> 
> On 23 Apr 2015, at 9:29pm, Jeff M  wrote:
> 
>> Has there been any discussion about integrating sqlite with Apple's iCloud, 
>> either by using Apple's Core Data as the Virtual Machine's database engine 
>> (so the VM would operate on Core Data objects) or by otherwise modifying the 
>> existing backend?
> 
> Apple has already tightly integrated SQLite with iCloud.

It's precisely that tight integration that I want to take advantage of, but 
without using Core Data directly and losing the ability to write queries using 
SQL.  Core Data's use of SQLite is just coincidental and would not change.  
SQLite would be in the path twice:

My app --> my special SQLite --> Core Data backend --> Core Data's normal 
SQLite and iCloud.

Such a version of SQLite might be useful for people upgrading legacy apps for 
the cloud and who (like me) much prefer using the SQL language instead of Core 
Data objects.


> You might instead be asking whether you could write an app which makes SQLite 
> calls to have data stores in iCloud.

Yes, almost...

> This could be done by writing a SQLite VFS which stored data in iCloud.  I 
> don't know how well this would work, especially if more than one user was 
> trying to use a database.  It might be difficult to implement because the 
> iCloud API doesn't map neatly onto the SQLite VFS API.

I don't need to map SQLite to iCloud -- I only need to map SQLite to Core Data. 
 Core Data then takes care of the iCloud issues.

Also, I have no multi-user issues -- one app, one user, one database.

> What would be easier is to use SQLite to store a database on your iCloud 
> Drive, as available in OS X 10.10 and above and some versions of Windows.  
> But there's nothing to do here: the drive is just a mounted volume like a 
> Flash drive or an AFP mount.  Just use the right path in sqlite3_open().  And 
> experiment with concurrent multi-user use before you promise it, since iCloud 
> Drive locking is, I think, implemented with using SMB2.

It the database file was small, iCloud Drive or Dropbox might work.  But that 
fails with large files -- the user's device would be constantly syncing the 
entire database, even for small changes.  This is why Core Data works -- it 
only syncs transactions.

Jeff



[sqlite] Integrating sqlite with Core Data and iCloud

2015-04-23 Thread Jeff M
Has there been any discussion about integrating sqlite with Apple's iCloud, 
either by using Apple's Core Data as the Virtual Machine's database engine (so 
the VM would operate on Core Data objects) or by otherwise modifying the 
existing backend?

My motivation is to allow existing apps that using the SQL language (via FMDB 
or the sqlite API) to gain Core Data features such as iCloud integration for 
syncing data between devices.  Refactoring apps to use Core Data is often 
impractical.

My dream architecture is:
SQL Language <--> FMDB <--> CD_sqlite (using Core Data (sqlite)) <--> 
iCloud.

What is the feasibility of making sqlite a wrapper for Core Data, or 
integrating iCloud directly into sqlite?  Crazy?

Jeff