21
21
public const int64 INVALID_ROWID = -1;
23
private const int MAX_RETRY_SLEEP_MSEC = 1000;
24
private const int MIN_RETRY_SLEEP_MSEC = 200;
25
private const int RETRY_SLEEP_DEC_MSEC = 200;
24
28
public enum DatabaseFlags {
52
56
public delegate TransactionOutcome TransactionMethod(Connection cx, Cancellable? cancellable) throws Error;
58
// Used by exec_retry_locked().
59
private delegate int SqliteExecOperation();
55
62
* See http://www.sqlite.org/c3ref/threadsafe.html
77
84
throw new IOError.CANCELLED("%s cancelled", !String.is_empty(method) ? method : "Operation");
87
// This method is useful for dealing with BUSY retries in a consistent manner.
88
private int exec_retry_locked(Context ctx, string? method, SqliteExecOperation op, string? raw = null)
91
int sleep_msec = MAX_RETRY_SLEEP_MSEC;
93
int max_retry_msec = ctx.get_max_retry_msec();
96
return throw_on_error(ctx, method, op(), raw);
97
} catch (DatabaseError derr) {
98
// if not BUSY, then immediately throw
99
if (!(derr is DatabaseError.BUSY))
102
// if BUSY and total time has elapsed, throw
103
if ((max_retry_msec > 0) && (total_msec >= max_retry_msec))
108
Thread.usleep(sleep_msec * 1000);
110
total_msec += sleep_msec;
111
sleep_msec = Numeric.int_floor(sleep_msec - RETRY_SLEEP_DEC_MSEC, MIN_RETRY_SLEEP_MSEC);
113
debug("%s retrying: [%d] total_msec=%d %s", method, ++count, total_msec,
114
(raw != null) ? raw : "");
80
118
// Returns result if exception is not thrown
81
119
private int throw_on_error(Context ctx, string? method, int result, string? raw = null) throws DatabaseError {