qam_method.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:10k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999, 2000
  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.17 2001/01/10 04:50:54 ubell 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 "db_page.h"
  17. #include "db_int.h"
  18. #include "db_shash.h"
  19. #include "db_am.h"
  20. #include "qam.h"
  21. #include "db.h"
  22. #include "mp.h"
  23. #include "lock.h"
  24. #include "log.h"
  25. static int __qam_set_extentsize __P((DB *, u_int32_t));
  26. static int __qam_remove_callback __P((DB *, void *));
  27. struct __qam_cookie {
  28. DB_LSN lsn;
  29. QUEUE_FILELIST *filelist;
  30. };
  31. /*
  32.  * __qam_db_create --
  33.  * Queue specific initialization of the DB structure.
  34.  *
  35.  * PUBLIC: int __qam_db_create __P((DB *));
  36.  */
  37. int
  38. __qam_db_create(dbp)
  39. DB *dbp;
  40. {
  41. QUEUE *t;
  42. int ret;
  43. /* Allocate and initialize the private queue structure. */
  44. if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(QUEUE), &t)) != 0)
  45. return (ret);
  46. dbp->q_internal = t;
  47. dbp->set_q_extentsize = __qam_set_extentsize;
  48. t->re_pad = ' ';
  49. return (0);
  50. }
  51. /*
  52.  * __qam_db_close --
  53.  * Queue specific discard of the DB structure.
  54.  *
  55.  * PUBLIC: int __qam_db_close __P((DB *));
  56.  */
  57. int
  58. __qam_db_close(dbp)
  59. DB *dbp;
  60. {
  61. DB_MPOOLFILE *mpf;
  62. MPFARRAY *array;
  63. QUEUE *t;
  64. struct __qmpf *mpfp;
  65. u_int32_t i;
  66. int ret, t_ret;
  67. ret = 0;
  68. t = dbp->q_internal;
  69. array = &t->array1;
  70. again:
  71. mpfp = array->mpfarray;
  72. if (mpfp != NULL) {
  73. for (i = array->low_extent;
  74.     i <= array->hi_extent; i++, mpfp++) {
  75. mpf = mpfp->mpf;
  76. mpfp->mpf = NULL;
  77. if (mpf != NULL &&
  78.     (t_ret = memp_fclose(mpf)) != 0 && ret == 0)
  79. ret = t_ret;
  80. }
  81. __os_free(array->mpfarray, 0);
  82. }
  83. if (t->array2.n_extent != 0) {
  84. array = &t->array2;
  85. array->n_extent = 0;
  86. goto again;
  87. }
  88. if (t->path != NULL)
  89. __os_free(t->path, 0);
  90. __os_free(t, sizeof(QUEUE));
  91. dbp->q_internal = NULL;
  92. return (ret);
  93. }
  94. static int
  95. __qam_set_extentsize(dbp, extentsize)
  96. DB *dbp;
  97. u_int32_t extentsize;
  98. {
  99. DB_ILLEGAL_AFTER_OPEN(dbp, "set_extentsize");
  100. if (extentsize < 1) {
  101. __db_err(dbp->dbenv, "Extent size must be at least 1.");
  102. return (EINVAL);
  103. }
  104. ((QUEUE*)dbp->q_internal)->page_ext = extentsize;
  105. return (0);
  106. }
  107. /*
  108.  * __db_prqueue --
  109.  * Print out a queue
  110.  *
  111.  * PUBLIC: int __db_prqueue __P((DB *, u_int32_t));
  112.  */
  113. int
  114. __db_prqueue(dbp, flags)
  115. DB *dbp;
  116. u_int32_t flags;
  117. {
  118. PAGE *h;
  119. QMETA *meta;
  120. db_pgno_t first, i, last, pg_ext, stop;
  121. int ret;
  122. /* Find out the page number of the last page in the database. */
  123. i = PGNO_BASE_MD;
  124. if ((ret = memp_fget(dbp->mpf, &i, 0, &meta)) != 0)
  125. return (ret);
  126. first = QAM_RECNO_PAGE(dbp, meta->first_recno);
  127. last = QAM_RECNO_PAGE(dbp, meta->cur_recno);
  128. if ((ret = __db_prpage(dbp, (PAGE *)meta, flags)) != 0)
  129. return (ret);
  130. if ((ret = memp_fput(dbp->mpf, meta, 0)) != 0)
  131. return (ret);
  132. i = first;
  133. if (first > last)
  134. stop = QAM_RECNO_PAGE(dbp, UINT32_T_MAX);
  135. else
  136. stop = last;
  137. /* Dump each page. */
  138. begin:
  139. for (; i <= stop; ++i) {
  140. if ((ret = __qam_fget(dbp, &i, DB_MPOOL_EXTENT, &h)) != 0) {
  141. pg_ext = ((QUEUE *)dbp->q_internal)->page_ext;
  142. if (pg_ext == 0) {
  143. if (ret == EINVAL && first == last)
  144. return (0);
  145. return (ret);
  146. }
  147. if (ret == ENOENT || ret == EINVAL) {
  148. i += pg_ext - ((i - 1) % pg_ext) - 1;
  149. continue;
  150. }
  151. return (ret);
  152. }
  153. (void)__db_prpage(dbp, h, flags);
  154. if ((ret = __qam_fput(dbp, i, h, 0)) != 0)
  155. return (ret);
  156. }
  157. if (first > last) {
  158. i = 1;
  159. stop = last;
  160. first = last;
  161. goto begin;
  162. }
  163. return (0);
  164. }
  165. /*
  166.  * __qam_remove
  167.  * Remove method for a Queue.
  168.  *
  169.  * PUBLIC: int __qam_remove __P((DB *, const char *,
  170.  * PUBLIC:      const char *, DB_LSN *, int (**)(DB *, void*), void **));
  171.  */
  172. int
  173. __qam_remove(dbp, name, subdb, lsnp, callbackp, cookiep)
  174. DB *dbp;
  175. const char *name, *subdb;
  176. DB_LSN *lsnp;
  177. int (**callbackp) __P((DB *, void *));
  178. void **cookiep;
  179. {
  180. DBT namedbt;
  181. DB_ENV *dbenv;
  182. DB_LSN lsn;
  183. MPFARRAY *ap;
  184. QUEUE *qp;
  185. int ret;
  186. char *backup, buf[256], *real_back, *real_name;
  187. QUEUE_FILELIST *filelist, *fp;
  188. struct __qam_cookie *qam_cookie;
  189. dbenv = dbp->dbenv;
  190. ret = 0;
  191. backup = real_back = real_name = NULL;
  192. filelist = NULL;
  193. PANIC_CHECK(dbenv);
  194. /*
  195.  * Subdatabases.
  196.  */
  197. if (subdb != NULL) {
  198. __db_err(dbenv,
  199.     "Queue does not support multiple databases per file.");
  200. ret = EINVAL;
  201. goto done;
  202. }
  203. qp = (QUEUE *)dbp->q_internal;
  204. if (qp->page_ext != 0 &&
  205.     (ret = __qam_gen_filelist(dbp, &filelist)) != 0)
  206. goto done;
  207. if (filelist == NULL)
  208. goto done;
  209. for (fp = filelist; fp->mpf != NULL; fp++) {
  210. snprintf(buf,
  211.     sizeof(buf), QUEUE_EXTENT, qp->dir, qp->name, fp->id);
  212. if ((ret = __db_appname(dbenv,
  213.     DB_APP_DATA, NULL, buf, 0, NULL, &real_name)) != 0)
  214. goto done;
  215. if (LOGGING_ON(dbenv)) {
  216. memset(&namedbt, 0, sizeof(namedbt));
  217. namedbt.data = (char *)buf;
  218. namedbt.size = strlen(buf) + 1;
  219. if ((ret =
  220.     __qam_delete_log(dbenv, dbp->open_txn,
  221.     &lsn, DB_FLUSH, &namedbt, lsnp)) != 0) {
  222. __db_err(dbenv,
  223.     "%s: %s", name, db_strerror(ret));
  224. goto done;
  225. }
  226. }
  227. (void)__memp_fremove(fp->mpf);
  228. if ((ret = memp_fclose(fp->mpf)) != 0)
  229. goto done;
  230. if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
  231. ap = &qp->array1;
  232. else
  233. ap = &qp->array2;
  234. ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
  235. /* Create name for backup file. */
  236. if (TXN_ON(dbenv)) {
  237. if ((ret = __db_backup_name(dbenv,
  238.     buf, &backup, lsnp)) != 0)
  239. goto done;
  240. if ((ret = __db_appname(dbenv, DB_APP_DATA,
  241.      NULL, backup, 0, NULL, &real_back)) != 0)
  242. goto done;
  243. if ((ret = __os_rename(dbenv,
  244.      real_name, real_back)) != 0)
  245. goto done;
  246. __os_freestr(real_back);
  247. real_back = NULL;
  248. }
  249. else
  250. if ((ret = __os_unlink(dbenv, real_name)) != 0)
  251. goto done;
  252. __os_freestr(real_name);
  253. real_name = NULL;
  254. }
  255. if ((ret= __os_malloc(dbenv,
  256.     sizeof(struct __qam_cookie), NULL, &qam_cookie)) != 0)
  257. goto done;
  258. qam_cookie->lsn = *lsnp;
  259. qam_cookie->filelist = filelist;
  260. *cookiep = qam_cookie;
  261. *callbackp = __qam_remove_callback;
  262. done:
  263. if (ret != 0 && filelist != NULL)
  264. __os_free(filelist, 0);
  265. if (real_back != NULL)
  266. __os_freestr(real_back);
  267. if (real_name != NULL)
  268. __os_freestr(real_name);
  269. if (backup != NULL)
  270. __os_freestr(backup);
  271. return (ret);
  272. }
  273. static int
  274. __qam_remove_callback(dbp, cookie)
  275. DB *dbp;
  276. void *cookie;
  277. {
  278. DB_ENV *dbenv;
  279. DB_LSN *lsnp;
  280. QUEUE *qp;
  281. QUEUE_FILELIST *filelist, *fp;
  282. char *backup, buf[256], *real_back;
  283. int ret;
  284. qp = (QUEUE *)dbp->q_internal;
  285. if (qp->page_ext == 0)
  286. return (__os_unlink(dbp->dbenv, cookie));
  287. dbenv = dbp->dbenv;
  288. lsnp = &((struct __qam_cookie *)cookie)->lsn;
  289. filelist = fp = ((struct __qam_cookie *)cookie)->filelist;
  290. real_back = backup = NULL;
  291. if ((ret =
  292.     __db_backup_name(dbenv, qp->name, &backup, lsnp)) != 0)
  293. goto err;
  294. if ((ret = __db_appname(dbenv,
  295.     DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
  296. goto err;
  297. if ((ret = __os_unlink(dbp->dbenv, real_back)) != 0)
  298. goto err;
  299. __os_freestr(backup);
  300. __os_freestr(real_back);
  301. if (fp == NULL)
  302. return (0);
  303. for (; fp->mpf != NULL; fp++) {
  304. snprintf(buf,
  305.     sizeof(buf), QUEUE_EXTENT, qp->dir, qp->name, fp->id);
  306. real_back = backup = NULL;
  307. if ((ret = __db_backup_name(dbenv, buf, &backup, lsnp)) != 0)
  308. goto err;
  309. if ((ret = __db_appname(dbenv,
  310.     DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
  311. goto err;
  312. ret = __os_unlink(dbenv, real_back);
  313. __os_freestr(real_back);
  314. __os_freestr(backup);
  315. }
  316. __os_free(filelist, 0);
  317. __os_free(cookie, sizeof (struct __qam_cookie));
  318. return (0);
  319. err:
  320. if (backup != NULL)
  321. __os_freestr(backup);
  322. if (real_back != NULL)
  323. __os_freestr(real_back);
  324. return (ret);
  325. }
  326. /*
  327.  * __qam_rename
  328.  * Rename method for Queue.
  329.  *
  330.  * PUBLIC: int __qam_rename __P((DB *,
  331.  * PUBLIC:     const char *, const char *, const char *));
  332.  */
  333. int
  334. __qam_rename(dbp, filename, subdb, newname)
  335. DB *dbp;
  336. const char *filename, *subdb, *newname;
  337. {
  338. DBT namedbt, newnamedbt;
  339. DB_ENV *dbenv;
  340. DB_LSN newlsn;
  341. MPFARRAY *ap;
  342. QUEUE *qp;
  343. QUEUE_FILELIST *fp, *filelist;
  344. char buf[256], nbuf[256], *namep, *real_name, *real_newname;
  345. int ret;
  346. dbenv = dbp->dbenv;
  347. ret = 0;
  348. real_name = real_newname = NULL;
  349. filelist = NULL;
  350. qp = (QUEUE *)dbp->q_internal;
  351. if (subdb != NULL) {
  352. __db_err(dbenv,
  353.     "Queue does not support multiple databases per file.");
  354. ret = EINVAL;
  355. goto err;
  356. }
  357. if (qp->page_ext != 0 &&
  358.     (ret = __qam_gen_filelist(dbp, &filelist)) != 0)
  359. goto err;
  360. if ((namep = __db_rpath(newname)) != NULL)
  361. newname = namep + 1;
  362. for (fp = filelist; fp != NULL && fp->mpf != NULL; fp++) {
  363. if ((ret = __memp_fremove(fp->mpf)) != 0)
  364. goto err;
  365. if ((ret = memp_fclose(fp->mpf)) != 0)
  366. goto err;
  367. if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
  368. ap = &qp->array1;
  369. else
  370. ap = &qp->array2;
  371. ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
  372. snprintf(buf,
  373.     sizeof(buf), QUEUE_EXTENT, qp->dir, qp->name, fp->id);
  374. if ((ret = __db_appname(dbenv,
  375.     DB_APP_DATA, NULL, buf, 0, NULL, &real_name)) != 0)
  376. goto err;
  377. snprintf(nbuf,
  378.      sizeof(nbuf), QUEUE_EXTENT, qp->dir, newname, fp->id);
  379. if ((ret = __db_appname(dbenv,
  380.     DB_APP_DATA, NULL, nbuf, 0, NULL, &real_newname)) != 0)
  381. goto err;
  382. if (LOGGING_ON(dbenv)) {
  383. memset(&namedbt, 0, sizeof(namedbt));
  384. namedbt.data = (char *)buf;
  385. namedbt.size = strlen(buf) + 1;
  386. memset(&newnamedbt, 0, sizeof(namedbt));
  387. newnamedbt.data = (char *)nbuf;
  388. newnamedbt.size = strlen(nbuf) + 1;
  389. if ((ret =
  390.     __qam_rename_log(dbenv,
  391.     dbp->open_txn, &newlsn, 0,
  392.     &namedbt, &newnamedbt)) != 0) {
  393. __db_err(dbenv, "%s: %s", filename, db_strerror(ret));
  394. goto err;
  395. }
  396. if ((ret = __log_filelist_update(dbenv, dbp,
  397.     dbp->log_fileid, newname, NULL)) != 0)
  398. goto err;
  399. }
  400. if ((ret = __os_rename(dbenv, real_name, real_newname)) != 0)
  401. goto err;
  402. __os_freestr(real_name);
  403. __os_freestr(real_newname);
  404. real_name = real_newname = NULL;
  405. }
  406. err:
  407. if (real_name != NULL)
  408. __os_freestr(real_name);
  409. if (real_newname != NULL)
  410. __os_freestr(real_newname);
  411. if (filelist != NULL)
  412. __os_free(filelist, 0);
  413. return (ret);
  414. }