[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Simon Slavin

On 15 Jan 2016, at 4:20pm, Olivier Mascia  wrote:

> I'm only left with the case of a row returning query which the programmer 
> would not want to step() up to the end. In this case, it is very reasonable 
> to have the programmer think of "freeing" the query in some way through 
> either the Statement class going out of scope or the call of some "reset()" 
> method.

This is a common problem when you're writing a library.

Assuming that you can provide a _dispose() method which is automatically called 
when your object slips out of scope, you're fine: just call _finalize() in it.

If you cannot depend on this then you are going to have to provide a disposal 
method and rely on your programmer calling it.

Simon.


[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Olivier Mascia
Richard, Simon,

> Le 15 janv. 2016 ? 16:30, Richard Hipp  a ?crit :
> 
>> But the finalize of a
>> statement (using the C++ wrapper we build for our use over C SQLite API) is
>> currently differed until another prepare is done using the same Statement
>> object, or until the Statement object goes out of scope (destructor).
> 
> That's a problem.  Until a prepared statement is either finalized or
> reset, SQLite must assume that you might call sqlite3_step() on it
> again.  And so it has to continue holding various locks and other
> state that will be needed by that subsequent sqlite3_step() call.

I think this is well understood now.   Thanks Richard.

> A better approach would be to invoke sqlite3_reset() as soon as you
> know that the prepared statement will not be stepped again.  That will
> release locks (and other resources) and help other operations to
> proceed unimpeded.

> Le 15 janv. 2016 ? 16:31, Simon Slavin  a ?crit :
> 
> Immediately after doing your first _step() you should be thinking to do your 
> _finalize() or _reset() as soon as practical.  It should weigh on your mind 
> like an open door in a high-crime area.  Having done either of those, you can 
> keep the statement around as long as you like: all it will use up is a little 
> memory.

Thanks Richard and Simon.

We indeed need to design the Statement class differently to sqlite3_reset() it 
as soon as possible. And I now realize that I overlooked one detail, which will 
help a lot.  For select-kind queries I can capitalize on sqlite3_step() having 
to be called until it returns SQLITE_DONE (so one more time than there are 
rows).  When that happens, I can sqlite3_reset() immediately. The programmer 
has been done with the previous (last row) since before the last call to 
step().  Same thing for SQLITE_OK, which would be returned for successful 
non-row returning queries, it can call reset() right away.

I'm only left with the case of a row returning query which the programmer would 
not want to step() up to the end. In this case, it is very reasonable to have 
the programmer think of "freeing" the query in some way through either the 
Statement class going out of scope or the call of some "reset()" method.  You 
see, the whole purpose of using a thin set of classes over the C API is to make 
it as easy as possible to merge SQL statements within the C++ code of the 
application.  I have done this exercise for some other databases, but I'm new 
at SQLite.

Again thank you very much for the very valuable input this mailing list 
provides. When we will be code-complete and able to decide for SQLite in our 
next releases, we will happily contract one of the paid professional support 
options HWACI offers.

-- 
Meilleures salutations, Met vriendelijke groeten, Best Regards,
Olivier Mascia, integral.be/om




[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Olivier Mascia

> Le 15 janv. 2016 ? 13:08, Hick Gunter  a ?crit :
> 
> I think you may mean "database connection" instead of "statement handle".
> 
> When you are finished with processing a statement, you should either reset 
> (if you intead to use it again later) or finalize it. Otherwise SQLite must 
> assume that you want to continue later and needs to keep around whatever 
> locks it acquired during processing. Which is also the cause for 
> sqlite3_wal_checkpoint returning SQLITE_LOCKED.
> 
> You should not be reusing a statement handle before calling finalize on it, 
> as this would cause a memory leak.

Thanks Hick,

Be sure I'm not reusing any statement handle without finalizing it.  No leaks, 
we have a checker in place to detect.  But the finalize of a statement (using 
the C++ wrapper we build for our use over C SQLite API) is currently differed 
until another prepare is done using the same Statement object, or until the 
Statement object goes out of scope (destructor).  We might have to add a method 
to 'clear' our Statement objects as soon as not needed anymore.  Though that 
probably is not very important in our real programming, the configuration I had 
in the test which returned LOCKED on the wal_checkpoint is 'synthetic' and not 
really representative. A Statement is generally re-used for successive 
different queries while a method is doing whatever its job is, then the local 
Statement goes out of scope (so its last instance gets finalized).

What remains in a multiple consumer set of processes or threads is that at any 
point in time while there exist a single not-yet-finalized statement, 
wal_checkpoint is bound to return LOCKED very easily, drastically reducing the 
windows of time where it could be called successfully.

Would it make sense (or even be valid) to use the sqlite3_unlock_notify() 
mechanism on attempts to wal_checkpoint as we do it successfully on prepare or 
step?

-- 
Meilleures salutations, Met vriendelijke groeten, Best Regards,
Olivier Mascia, integral.be/om




[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Simon Slavin

On 15 Jan 2016, at 3:18pm, Olivier Mascia  wrote:

> Be sure I'm not reusing any statement handle without finalizing it.  No 
> leaks, we have a checker in place to detect.  But the finalize of a statement 
> (using the C++ wrapper we build for our use over C SQLite API) is currently 
> differed until another prepare is done using the same Statement object, or 
> until the Statement object goes out of scope (destructor).  We might have to 
> add a method to 'clear' our Statement objects as soon as not needed anymore.  
> Though that probably is not very important in our real programming, the 
> configuration I had in the test which returned LOCKED on the wal_checkpoint 
> is 'synthetic' and not really representative. A Statement is generally 
> re-used for successive different queries while a method is doing whatever its 
> job is, then the local Statement goes out of scope (so its last instance gets 
> finalized).

Please don't do this.  Until you have done your _finalize() or _reset() that 
statement can be taking up a lot of memory and/or have temporary files created 
and/or have locks on files.  You want to release all this stuff as soon as 
possible to prevent your program from being a memory/disk/resource/handle hog.

Remember that the only reason _prepare, _step, _finalize/_reset are not all one 
command is that not all operating systems allow SQLite to callback your program 
to tell it that the next row is ready.

Immediately after doing your first _step() you should be thinking to do your 
_finalize() or _reset() as soon as practical.  It should weigh on your mind 
like an open door in a high-crime area.  Having done either of those, you can 
keep the statement around as long as you like: all it will use up is a little 
memory.

Simon.


[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Olivier Mascia
> Le 15 janv. 2016 ? 11:54, Olivier Mascia  a ?crit :
> 
> What are the circumstances leading to:
> 
> int status = sqlite3_wal_checkpoint_v2(conn, "main", 
> SQLITE_CHECKPOINT_PASSIVE, 0, 0);
> 
> returning SQLITE_LOCKED immediately?
> 
> 
> It looks like that the simple fact of having a select statement prepared, 
> then ran, but not yet finalized, on that same connection, induces the 
> SQLITE_LOCKED return. I can get it to go away by simply finalizing the last 
> statement before trying checkpoint. I just did not expected LOCKED to be 
> returned. Reading https://www.sqlite.org/c3ref/wal_checkpoint_v2.html I 
> expected to get SQLITE_BUSY. My misunderstanding probably.

I probably should have been more descriptive about the conditions:

For the purpose of the test, there are some (at least one) transactions 
committed waiting to be checkpointed and those transactions did inserts on a 
table, which is the one selected (outside of any explicit transaction).

In pseudo code, this means:

With one statement handle:
begin transaction
insert into T(C) values(xyz)
commit transaction

With the same statement handle:
begin transaction
select ... from T
commit transaction

Again with the same statement handle:
select ... from T

(*)

And finally:
sqlite3_wal_checkpoint_v2 as above, returning SQLITE_LOCKED.

Merely finalizing the statement at point (*) right after the (out of explicit 
transaction) select and the wal_checkpoint returns SQLITE_OK.

Is this perfectly expected?
In a somehow more complex configuration where multiple threads or processes 
(all using distinct connections and private cache) could be running quite any 
query at any time, it could become quite hard to find an appropriate slot of 
time to call sqlite3_wal_chekcpoint not returning LOCKED.
Should it be valuable to use the sqlite3_unlock_notify mechanism on attempts to 
wal_checkpoint returning SQLITE_LOCKED? (I understand that in this simple test, 
if the mere un-finalized statement is the reason of the LOCKED, it won't help, 
but I'm thinking more general in a multi-consumer processes or threads model.)

It might very well be much easier then to leave it to the automated 
checkpointing mode of SQLite, eventually changing its default of 1000 pages 
before trigger, if it better fit my needs.

-- 
Meilleures salutations, Met vriendelijke groeten, Best Regards,
Olivier Mascia, integral.be/om





[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Hick Gunter
I think you may mean "database connection" instead of "statement handle".

When you are finished with processing a statement, you should either reset (if 
you intead to use it again later) or finalize it. Otherwise SQLite must assume 
that you want to continue later and needs to keep around whatever locks it 
acquired during processing. Which is also the cause for sqlite3_wal_checkpoint 
returning SQLITE_LOCKED.

You should not be reusing a statement handle before calling finalize on it, as 
this would cause a memory leak.

-Urspr?ngliche Nachricht-
Von: sqlite-users-bounces at mailinglists.sqlite.org 
[mailto:sqlite-users-bounces at mailinglists.sqlite.org] Im Auftrag von Olivier 
Mascia
Gesendet: Freitag, 15. J?nner 2016 12:18
An: SQLite mailing list
Betreff: Re: [sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in 
what circumstances?

> Le 15 janv. 2016 ? 11:54, Olivier Mascia  a ?crit :
>
> What are the circumstances leading to:
>
> int status = sqlite3_wal_checkpoint_v2(conn, "main",
> SQLITE_CHECKPOINT_PASSIVE, 0, 0);
>
> returning SQLITE_LOCKED immediately?
>
>
> It looks like that the simple fact of having a select statement prepared, 
> then ran, but not yet finalized, on that same connection, induces the 
> SQLITE_LOCKED return. I can get it to go away by simply finalizing the last 
> statement before trying checkpoint. I just did not expected LOCKED to be 
> returned. Reading https://www.sqlite.org/c3ref/wal_checkpoint_v2.html I 
> expected to get SQLITE_BUSY. My misunderstanding probably.

I probably should have been more descriptive about the conditions:

For the purpose of the test, there are some (at least one) transactions 
committed waiting to be checkpointed and those transactions did inserts on a 
table, which is the one selected (outside of any explicit transaction).

In pseudo code, this means:

With one statement handle:
begin transaction
insert into T(C) values(xyz)
commit transaction

With the same statement handle:
begin transaction
select ... from T
commit transaction

Again with the same statement handle:
select ... from T

(*)

And finally:
sqlite3_wal_checkpoint_v2 as above, returning SQLITE_LOCKED.

Merely finalizing the statement at point (*) right after the (out of explicit 
transaction) select and the wal_checkpoint returns SQLITE_OK.

Is this perfectly expected?
In a somehow more complex configuration where multiple threads or processes 
(all using distinct connections and private cache) could be running quite any 
query at any time, it could become quite hard to find an appropriate slot of 
time to call sqlite3_wal_chekcpoint not returning LOCKED.
Should it be valuable to use the sqlite3_unlock_notify mechanism on attempts to 
wal_checkpoint returning SQLITE_LOCKED? (I understand that in this simple test, 
if the mere un-finalized statement is the reason of the LOCKED, it won't help, 
but I'm thinking more general in a multi-consumer processes or threads model.)

It might very well be much easier then to leave it to the automated 
checkpointing mode of SQLite, eventually changing its default of 1000 pages 
before trigger, if it better fit my needs.

--
Meilleures salutations, Met vriendelijke groeten, Best Regards, Olivier Mascia, 
integral.be/om



___
sqlite-users mailing list
sqlite-users at mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


___
 Gunter Hick
Software Engineer
Scientific Games International GmbH
FN 157284 a, HG Wien
Klitschgasse 2-4, A-1130 Vienna, Austria
Tel: +43 1 80100 0
E-Mail: hick at scigames.at

This communication (including any attachments) is intended for the use of the 
intended recipient(s) only and may contain information that is confidential, 
privileged or legally protected. Any unauthorized use or dissemination of this 
communication is strictly prohibited. If you have received this communication 
in error, please immediately notify the sender by return e-mail message and 
delete all copies of the original communication. Thank you for your cooperation.




[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Olivier Mascia
Dear all,

What are the circumstances leading to:

int status = sqlite3_wal_checkpoint_v2(conn, "main", SQLITE_CHECKPOINT_PASSIVE, 
0, 0);

returning SQLITE_LOCKED immediately?


It looks like that the simple fact of having a select statement prepared, then 
ran, but not yet finalized, on that same connection, induces the SQLITE_LOCKED 
return. I can get it to go away by simply finalizing the last statement before 
trying checkpoint. I just did not expected LOCKED to be returned. Reading 
https://www.sqlite.org/c3ref/wal_checkpoint_v2.html I expected to get 
SQLITE_BUSY. My misunderstanding probably.

I have no problem with that, I'm merely gathering knowledge of how to best use 
it.

-- 
Meilleures salutations, Met vriendelijke groeten, Best Regards,
Olivier Mascia, integral.be/o=m




[sqlite] sqlite3_wal_checkpoint_v2() returning SQLITE_LOCKED: in what circumstances?

2016-01-15 Thread Richard Hipp
On 1/15/16, Olivier Mascia  wrote:
> But the finalize of a
> statement (using the C++ wrapper we build for our use over C SQLite API) is
> currently differed until another prepare is done using the same Statement
> object, or until the Statement object goes out of scope (destructor).

That's a problem.  Until a prepared statement is either finalized or
reset, SQLite must assume that you might call sqlite3_step() on it
again.  And so it has to continue holding various locks and other
state that will be needed by that subsequent sqlite3_step() call.

A better approach would be to invoke sqlite3_reset() as soon as you
know that the prepared statement will not be stepped again.  That will
release locks (and other resources) and help other operations to
proceed unimpeded.

-- 
D. Richard Hipp
drh at sqlite.org