notify.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. ** 2009 March 3
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. *************************************************************************
  12. **
  13. ** This file contains the implementation of the sqlite3_unlock_notify()
  14. ** API method and its associated functionality.
  15. */
  16. #include "sqliteInt.h"
  17. #include "btreeInt.h"
  18. /* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */
  19. #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  20. /*
  21. ** Public interfaces:
  22. **
  23. ** sqlite3ConnectionBlocked()
  24. ** sqlite3ConnectionUnlocked()
  25. ** sqlite3ConnectionClosed()
  26. ** sqlite3_unlock_notify()
  27. */
  28. #define assertMutexHeld() \
  29. assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) )
  30. /*
  31. ** Head of a linked list of all sqlite3 objects created by this process
  32. ** for which either sqlite3.pBlockingConnection or sqlite3.pUnlockConnection
  33. ** is not NULL. This variable may only accessed while the STATIC_MASTER
  34. ** mutex is held.
  35. */
  36. static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0;
  37. #ifndef NDEBUG
  38. /*
  39. ** This function is a complex assert() that verifies the following
  40. ** properties of the blocked connections list:
  41. **
  42. ** 1) Each entry in the list has a non-NULL value for either
  43. ** pUnlockConnection or pBlockingConnection, or both.
  44. **
  45. ** 2) All entries in the list that share a common value for
  46. ** xUnlockNotify are grouped together.
  47. **
  48. ** 3) If the argument db is not NULL, then none of the entries in the
  49. ** blocked connections list have pUnlockConnection or pBlockingConnection
  50. ** set to db. This is used when closing connection db.
  51. */
  52. static void checkListProperties(sqlite3 *db){
  53. sqlite3 *p;
  54. for(p=sqlite3BlockedList; p; p=p->pNextBlocked){
  55. int seen = 0;
  56. sqlite3 *p2;
  57. /* Verify property (1) */
  58. assert( p->pUnlockConnection || p->pBlockingConnection );
  59. /* Verify property (2) */
  60. for(p2=sqlite3BlockedList; p2!=p; p2=p2->pNextBlocked){
  61. if( p2->xUnlockNotify==p->xUnlockNotify ) seen = 1;
  62. assert( p2->xUnlockNotify==p->xUnlockNotify || !seen );
  63. assert( db==0 || p->pUnlockConnection!=db );
  64. assert( db==0 || p->pBlockingConnection!=db );
  65. }
  66. }
  67. }
  68. #else
  69. # define checkListProperties(x)
  70. #endif
  71. /*
  72. ** Remove connection db from the blocked connections list. If connection
  73. ** db is not currently a part of the list, this function is a no-op.
  74. */
  75. static void removeFromBlockedList(sqlite3 *db){
  76. sqlite3 **pp;
  77. assertMutexHeld();
  78. for(pp=&sqlite3BlockedList; *pp; pp = &(*pp)->pNextBlocked){
  79. if( *pp==db ){
  80. *pp = (*pp)->pNextBlocked;
  81. break;
  82. }
  83. }
  84. }
  85. /*
  86. ** Add connection db to the blocked connections list. It is assumed
  87. ** that it is not already a part of the list.
  88. */
  89. static void addToBlockedList(sqlite3 *db){
  90. sqlite3 **pp;
  91. assertMutexHeld();
  92. for(
  93. pp=&sqlite3BlockedList;
  94. *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
  95. pp=&(*pp)->pNextBlocked
  96. );
  97. db->pNextBlocked = *pp;
  98. *pp = db;
  99. }
  100. /*
  101. ** Obtain the STATIC_MASTER mutex.
  102. */
  103. static void enterMutex(void){
  104. sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  105. checkListProperties(0);
  106. }
  107. /*
  108. ** Release the STATIC_MASTER mutex.
  109. */
  110. static void leaveMutex(void){
  111. assertMutexHeld();
  112. checkListProperties(0);
  113. sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  114. }
  115. /*
  116. ** Register an unlock-notify callback.
  117. **
  118. ** This is called after connection "db" has attempted some operation
  119. ** but has received an SQLITE_LOCKED error because another connection
  120. ** (call it pOther) in the same process was busy using the same shared
  121. ** cache. pOther is found by looking at db->pBlockingConnection.
  122. **
  123. ** If there is no blocking connection, the callback is invoked immediately,
  124. ** before this routine returns.
  125. **
  126. ** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate
  127. ** a deadlock.
  128. **
  129. ** Otherwise, make arrangements to invoke xNotify when pOther drops
  130. ** its locks.
  131. **
  132. ** Each call to this routine overrides any prior callbacks registered
  133. ** on the same "db". If xNotify==0 then any prior callbacks are immediately
  134. ** cancelled.
  135. */
  136. int sqlite3_unlock_notify(
  137. sqlite3 *db,
  138. void (*xNotify)(void **, int),
  139. void *pArg
  140. ){
  141. int rc = SQLITE_OK;
  142. sqlite3_mutex_enter(db->mutex);
  143. enterMutex();
  144. if( xNotify==0 ){
  145. removeFromBlockedList(db);
  146. db->pBlockingConnection = 0;
  147. db->pUnlockConnection = 0;
  148. db->xUnlockNotify = 0;
  149. db->pUnlockArg = 0;
  150. }else if( 0==db->pBlockingConnection ){
  151. /* The blocking transaction has been concluded. Or there never was a
  152. ** blocking transaction. In either case, invoke the notify callback
  153. ** immediately.
  154. */
  155. xNotify(&pArg, 1);
  156. }else{
  157. sqlite3 *p;
  158. for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){}
  159. if( p ){
  160. rc = SQLITE_LOCKED; /* Deadlock detected. */
  161. }else{
  162. db->pUnlockConnection = db->pBlockingConnection;
  163. db->xUnlockNotify = xNotify;
  164. db->pUnlockArg = pArg;
  165. removeFromBlockedList(db);
  166. addToBlockedList(db);
  167. }
  168. }
  169. leaveMutex();
  170. assert( !db->mallocFailed );
  171. sqlite3Error(db, rc, (rc?"database is deadlocked":0));
  172. sqlite3_mutex_leave(db->mutex);
  173. return rc;
  174. }
  175. /*
  176. ** This function is called while stepping or preparing a statement
  177. ** associated with connection db. The operation will return SQLITE_LOCKED
  178. ** to the user because it requires a lock that will not be available
  179. ** until connection pBlocker concludes its current transaction.
  180. */
  181. void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
  182. enterMutex();
  183. if( db->pBlockingConnection==0 && db->pUnlockConnection==0 ){
  184. addToBlockedList(db);
  185. }
  186. db->pBlockingConnection = pBlocker;
  187. leaveMutex();
  188. }
  189. /*
  190. ** This function is called when
  191. ** the transaction opened by database db has just finished. Locks held
  192. ** by database connection db have been released.
  193. **
  194. ** This function loops through each entry in the blocked connections
  195. ** list and does the following:
  196. **
  197. ** 1) If the sqlite3.pBlockingConnection member of a list entry is
  198. ** set to db, then set pBlockingConnection=0.
  199. **
  200. ** 2) If the sqlite3.pUnlockConnection member of a list entry is
  201. ** set to db, then invoke the configured unlock-notify callback and
  202. ** set pUnlockConnection=0.
  203. **
  204. ** 3) If the two steps above mean that pBlockingConnection==0 and
  205. ** pUnlockConnection==0, remove the entry from the blocked connections
  206. ** list.
  207. */
  208. void sqlite3ConnectionUnlocked(sqlite3 *db){
  209. void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */
  210. int nArg = 0; /* Number of entries in aArg[] */
  211. sqlite3 **pp; /* Iterator variable */
  212. void **aArg; /* Arguments to the unlock callback */
  213. void **aDyn = 0; /* Dynamically allocated space for aArg[] */
  214. void *aStatic[16]; /* Starter space for aArg[]. No malloc required */
  215. aArg = aStatic;
  216. enterMutex(); /* Enter STATIC_MASTER mutex */
  217. /* This loop runs once for each entry in the blocked-connections list. */
  218. for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){
  219. sqlite3 *p = *pp;
  220. /* Step 1. */
  221. if( p->pBlockingConnection==db ){
  222. p->pBlockingConnection = 0;
  223. }
  224. /* Step 2. */
  225. if( p->pUnlockConnection==db ){
  226. assert( p->xUnlockNotify );
  227. if( p->xUnlockNotify!=xUnlockNotify && nArg!=0 ){
  228. xUnlockNotify(aArg, nArg);
  229. nArg = 0;
  230. }
  231. sqlite3BeginBenignMalloc();
  232. assert( aArg==aDyn || (aDyn==0 && aArg==aStatic) );
  233. assert( nArg<=(int)ArraySize(aStatic) || aArg==aDyn );
  234. if( (!aDyn && nArg==(int)ArraySize(aStatic))
  235. || (aDyn && nArg==(int)(sqlite3MallocSize(aDyn)/sizeof(void*)))
  236. ){
  237. /* The aArg[] array needs to grow. */
  238. void **pNew = (void **)sqlite3Malloc(nArg*sizeof(void *)*2);
  239. if( pNew ){
  240. memcpy(pNew, aArg, nArg*sizeof(void *));
  241. sqlite3_free(aDyn);
  242. aDyn = aArg = pNew;
  243. }else{
  244. /* This occurs when the array of context pointers that need to
  245. ** be passed to the unlock-notify callback is larger than the
  246. ** aStatic[] array allocated on the stack and the attempt to
  247. ** allocate a larger array from the heap has failed.
  248. **
  249. ** This is a difficult situation to handle. Returning an error
  250. ** code to the caller is insufficient, as even if an error code
  251. ** is returned the transaction on connection db will still be
  252. ** closed and the unlock-notify callbacks on blocked connections
  253. ** will go unissued. This might cause the application to wait
  254. ** indefinitely for an unlock-notify callback that will never
  255. ** arrive.
  256. **
  257. ** Instead, invoke the unlock-notify callback with the context
  258. ** array already accumulated. We can then clear the array and
  259. ** begin accumulating any further context pointers without
  260. ** requiring any dynamic allocation. This is sub-optimal because
  261. ** it means that instead of one callback with a large array of
  262. ** context pointers the application will receive two or more
  263. ** callbacks with smaller arrays of context pointers, which will
  264. ** reduce the applications ability to prioritize multiple
  265. ** connections. But it is the best that can be done under the
  266. ** circumstances.
  267. */
  268. xUnlockNotify(aArg, nArg);
  269. nArg = 0;
  270. }
  271. }
  272. sqlite3EndBenignMalloc();
  273. aArg[nArg++] = p->pUnlockArg;
  274. xUnlockNotify = p->xUnlockNotify;
  275. p->pUnlockConnection = 0;
  276. p->xUnlockNotify = 0;
  277. p->pUnlockArg = 0;
  278. }
  279. /* Step 3. */
  280. if( p->pBlockingConnection==0 && p->pUnlockConnection==0 ){
  281. /* Remove connection p from the blocked connections list. */
  282. *pp = p->pNextBlocked;
  283. p->pNextBlocked = 0;
  284. }else{
  285. pp = &p->pNextBlocked;
  286. }
  287. }
  288. if( nArg!=0 ){
  289. xUnlockNotify(aArg, nArg);
  290. }
  291. sqlite3_free(aDyn);
  292. leaveMutex(); /* Leave STATIC_MASTER mutex */
  293. }
  294. /*
  295. ** This is called when the database connection passed as an argument is
  296. ** being closed. The connection is removed from the blocked list.
  297. */
  298. void sqlite3ConnectionClosed(sqlite3 *db){
  299. sqlite3ConnectionUnlocked(db);
  300. enterMutex();
  301. removeFromBlockedList(db);
  302. checkListProperties(db);
  303. leaveMutex();
  304. }
  305. #endif