qam_method.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: qam_method.c,v 11.55 2002/08/26 17:52:19 margo Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #endif
  15. #include "db_int.h"
  16. #include "dbinc/db_page.h"
  17. #include "dbinc/db_shash.h"
  18. #include "dbinc/db_am.h"
  19. #include "dbinc/fop.h"
  20. #include "dbinc/lock.h"
  21. #include "dbinc/qam.h"
  22. #include "dbinc/txn.h"
  23. static int __qam_set_extentsize __P((DB *, u_int32_t));
  24. struct __qam_cookie {
  25. DB_LSN lsn;
  26. QUEUE_FILELIST *filelist;
  27. };
  28. /*
  29.  * __qam_db_create --
  30.  * Queue specific initialization of the DB structure.
  31.  *
  32.  * PUBLIC: int __qam_db_create __P((DB *));
  33.  */
  34. int
  35. __qam_db_create(dbp)
  36. DB *dbp;
  37. {
  38. QUEUE *t;
  39. int ret;
  40. /* Allocate and initialize the private queue structure. */
  41. if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(QUEUE), &t)) != 0)
  42. return (ret);
  43. dbp->q_internal = t;
  44. dbp->set_q_extentsize = __qam_set_extentsize;
  45. t->re_pad = ' ';
  46. return (0);
  47. }
  48. /*
  49.  * __qam_db_close --
  50.  * Queue specific discard of the DB structure.
  51.  *
  52.  * PUBLIC: int __qam_db_close __P((DB *));
  53.  */
  54. int
  55. __qam_db_close(dbp)
  56. DB *dbp;
  57. {
  58. DB_MPOOLFILE *mpf;
  59. MPFARRAY *array;
  60. QUEUE *t;
  61. struct __qmpf *mpfp;
  62. u_int32_t i;
  63. int ret, t_ret;
  64. ret = 0;
  65. if ((t = dbp->q_internal) == NULL)
  66. return (0);
  67. array = &t->array1;
  68. again:
  69. mpfp = array->mpfarray;
  70. if (mpfp != NULL) {
  71. for (i = array->low_extent;
  72.     i <= array->hi_extent; i++, mpfp++) {
  73. mpf = mpfp->mpf;
  74. mpfp->mpf = NULL;
  75. if (mpf != NULL &&
  76.     (t_ret = mpf->close(mpf, 0)) != 0 && ret == 0)
  77. ret = t_ret;
  78. }
  79. __os_free(dbp->dbenv, array->mpfarray);
  80. }
  81. if (t->array2.n_extent != 0) {
  82. array = &t->array2;
  83. array->n_extent = 0;
  84. goto again;
  85. }
  86. if (t->path != NULL)
  87. __os_free(dbp->dbenv, t->path);
  88. __os_free(dbp->dbenv, t);
  89. dbp->q_internal = NULL;
  90. return (ret);
  91. }
  92. static int
  93. __qam_set_extentsize(dbp, extentsize)
  94. DB *dbp;
  95. u_int32_t extentsize;
  96. {
  97. DB_ILLEGAL_AFTER_OPEN(dbp, "set_extentsize");
  98. if (extentsize < 1) {
  99. __db_err(dbp->dbenv, "Extent size must be at least 1");
  100. return (EINVAL);
  101. }
  102. ((QUEUE*)dbp->q_internal)->page_ext = extentsize;
  103. return (0);
  104. }
  105. /*
  106.  * __db_prqueue --
  107.  * Print out a queue
  108.  *
  109.  * PUBLIC: int __db_prqueue __P((DB *, FILE *, u_int32_t));
  110.  */
  111. int
  112. __db_prqueue(dbp, fp, flags)
  113. DB *dbp;
  114. FILE *fp;
  115. u_int32_t flags;
  116. {
  117. DB_MPOOLFILE *mpf;
  118. PAGE *h;
  119. QMETA *meta;
  120. db_pgno_t first, i, last, pg_ext, stop;
  121. int ret, t_ret;
  122. mpf = dbp->mpf;
  123. /* Find out the page number of the last page in the database. */
  124. i = PGNO_BASE_MD;
  125. if ((ret = mpf->get(mpf, &i, 0, &meta)) != 0)
  126. return (ret);
  127. first = QAM_RECNO_PAGE(dbp, meta->first_recno);
  128. last = QAM_RECNO_PAGE(dbp, meta->cur_recno);
  129. ret = __db_prpage(dbp, (PAGE *)meta, fp, flags);
  130. if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
  131. ret = t_ret;
  132. if (ret != 0)
  133. return (ret);
  134. i = first;
  135. if (first > last)
  136. stop = QAM_RECNO_PAGE(dbp, UINT32_T_MAX);
  137. else
  138. stop = last;
  139. /* Dump each page. */
  140. begin:
  141. for (; i <= stop; ++i) {
  142. if ((ret = __qam_fget(dbp, &i, 0, &h)) != 0) {
  143. pg_ext = ((QUEUE *)dbp->q_internal)->page_ext;
  144. if (pg_ext == 0) {
  145. if (ret == DB_PAGE_NOTFOUND && first == last)
  146. return (0);
  147. return (ret);
  148. }
  149. if (ret == ENOENT || ret == DB_PAGE_NOTFOUND) {
  150. i += pg_ext - ((i - 1) % pg_ext) - 1;
  151. continue;
  152. }
  153. return (ret);
  154. }
  155. (void)__db_prpage(dbp, h, fp, flags);
  156. if ((ret = __qam_fput(dbp, i, h, 0)) != 0)
  157. return (ret);
  158. }
  159. if (first > last) {
  160. i = 1;
  161. stop = last;
  162. first = last;
  163. goto begin;
  164. }
  165. return (0);
  166. }
  167. /*
  168.  * __qam_remove
  169.  * Remove method for a Queue.
  170.  *
  171.  * PUBLIC: int __qam_remove __P((DB *,
  172.  * PUBLIC:     DB_TXN *, const char *, const char *, DB_LSN *));
  173.  */
  174. int
  175. __qam_remove(dbp, txn, name, subdb, lsnp)
  176. DB *dbp;
  177. DB_TXN *txn;
  178. const char *name, *subdb;
  179. DB_LSN *lsnp;
  180. {
  181. DB_ENV *dbenv;
  182. DB *tmpdbp;
  183. MPFARRAY *ap;
  184. QUEUE *qp;
  185. QUEUE_FILELIST *filelist, *fp;
  186. int ret, needclose, t_ret;
  187. char buf[MAXPATHLEN];
  188. u_int8_t fid[DB_FILE_ID_LEN];
  189. COMPQUIET(lsnp, NULL);
  190. dbenv = dbp->dbenv;
  191. ret = 0;
  192. filelist = NULL;
  193. needclose = 0;
  194. PANIC_CHECK(dbenv);
  195. /*
  196.  * Subdatabases.
  197.  */
  198. if (subdb != NULL) {
  199. __db_err(dbenv,
  200.     "Queue does not support multiple databases per file");
  201. ret = EINVAL;
  202. goto err;
  203. }
  204. /*
  205.  * Since regular remove no longer opens the database, we may have
  206.  * to do it here.
  207.  */
  208. if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
  209. tmpdbp = dbp;
  210. else {
  211. if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
  212. return (ret);
  213. /*
  214.  * We need to make sure we don't self-deadlock, so give
  215.  * this dbp the same locker as the incoming one.
  216.  */
  217. tmpdbp->lid = dbp->lid;
  218. /*
  219.  * If this is a transactional dbp and the open fails, then
  220.  * the transactional abort will close the dbp.  If it's not
  221.  * a transactional open, then we always have to close it
  222.  * even if the open fails.  Once the open has succeeded,
  223.  * then we will always want to close it.
  224.  */
  225. if (txn == NULL)
  226. needclose = 1;
  227. if ((ret = tmpdbp->open(tmpdbp,
  228.     txn, name, NULL, DB_QUEUE, 0, 0)) != 0)
  229. goto err;
  230. needclose = 1;
  231. }
  232. qp = (QUEUE *)tmpdbp->q_internal;
  233. if (qp->page_ext != 0 &&
  234.     (ret = __qam_gen_filelist(tmpdbp, &filelist)) != 0)
  235. goto err;
  236. if (filelist == NULL)
  237. goto err;
  238. for (fp = filelist; fp->mpf != NULL; fp++) {
  239. snprintf(buf, sizeof(buf),
  240.     QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, fp->id);
  241. if ((ret = fp->mpf->close(fp->mpf, DB_MPOOL_DISCARD)) != 0)
  242. goto err;
  243. if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
  244. ap = &qp->array1;
  245. else
  246. ap = &qp->array2;
  247. ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
  248. /* Take care of object reclamation. */
  249. __qam_exid(tmpdbp, fid, fp->id);
  250. if ((ret = __fop_remove(dbenv,
  251.     txn, fid, buf, DB_APP_DATA)) != 0)
  252. goto err;
  253. }
  254. err: if (filelist != NULL)
  255. __os_free(dbenv, filelist);
  256. if (needclose) {
  257. /*
  258.  * Since we copied the lid from the dbp, we'd better not
  259.  * free it here.
  260.  */
  261. tmpdbp->lid = DB_LOCK_INVALIDID;
  262. /* We need to remove the lockevent we associated with this. */
  263. if (txn != NULL)
  264. __txn_remlock(dbenv,
  265.     txn, &tmpdbp->handle_lock, DB_LOCK_INVALIDID);
  266. if ((t_ret =
  267.     __db_close_i(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
  268. ret = t_ret;
  269. }
  270. return (ret);
  271. }
  272. /*
  273.  * __qam_rename
  274.  * Rename method for Queue.
  275.  *
  276.  * PUBLIC: int __qam_rename __P((DB *, DB_TXN *,
  277.  * PUBLIC:     const char *, const char *, const char *));
  278.  */
  279. int
  280. __qam_rename(dbp, txn, filename, subdb, newname)
  281. DB *dbp;
  282. DB_TXN *txn;
  283. const char *filename, *subdb, *newname;
  284. {
  285. DB_ENV *dbenv;
  286. DB *tmpdbp;
  287. MPFARRAY *ap;
  288. QUEUE *qp;
  289. QUEUE_FILELIST *fp, *filelist;
  290. char buf[MAXPATHLEN], nbuf[MAXPATHLEN];
  291. char *namep;
  292. int ret, needclose, t_ret;
  293. u_int8_t fid[DB_FILE_ID_LEN], *fidp;
  294. dbenv = dbp->dbenv;
  295. ret = 0;
  296. filelist = NULL;
  297. needclose = 0;
  298. if (subdb != NULL) {
  299. __db_err(dbenv,
  300.     "Queue does not support multiple databases per file");
  301. ret = EINVAL;
  302. goto err;
  303. }
  304. /*
  305.  * Since regular rename no longer opens the database, we may have
  306.  * to do it here.
  307.  */
  308. if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
  309. tmpdbp = dbp;
  310. else {
  311. if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
  312. return (ret);
  313. /* Copy the incoming locker so we don't self-deadlock. */
  314. tmpdbp->lid = dbp->lid;
  315. needclose = 1;
  316. if ((ret = tmpdbp->open(tmpdbp, txn, filename, NULL,
  317.     DB_QUEUE, 0, 0)) != 0)
  318. goto err;
  319. }
  320. qp = (QUEUE *)tmpdbp->q_internal;
  321. if (qp->page_ext != 0 &&
  322.     (ret = __qam_gen_filelist(tmpdbp, &filelist)) != 0)
  323. goto err;
  324. if ((namep = __db_rpath(newname)) != NULL)
  325. newname = namep + 1;
  326. fidp = fid;
  327. for (fp = filelist; fp != NULL && fp->mpf != NULL; fp++) {
  328. fp->mpf->get_fileid(fp->mpf, fidp);
  329. if ((ret = fp->mpf->close(fp->mpf, DB_MPOOL_DISCARD)) != 0)
  330. goto err;
  331. if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
  332. ap = &qp->array1;
  333. else
  334. ap = &qp->array2;
  335. ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
  336. snprintf(buf, sizeof(buf),
  337.     QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, fp->id);
  338. snprintf(nbuf, sizeof(nbuf),
  339.     QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], newname, fp->id);
  340. if ((ret = __fop_rename(dbenv,
  341.     txn, buf, nbuf, fidp, DB_APP_DATA)) != 0)
  342. goto err;
  343. }
  344. err: if (filelist != NULL)
  345. __os_free(dbenv, filelist);
  346. if (needclose) {
  347. /* We copied this, so we mustn't free it. */
  348. tmpdbp->lid = DB_LOCK_INVALIDID;
  349. /* We need to remove the lockevent we associated with this. */
  350. if (txn != NULL)
  351.     __txn_remlock(dbenv,
  352. txn, &tmpdbp->handle_lock, DB_LOCK_INVALIDID);
  353. if ((t_ret =
  354.     __db_close_i(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
  355. ret = t_ret;
  356. }
  357. return (ret);
  358. }