00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 #endif
00015
00016 #include "db_int.h"
00017 #include "dbinc/db_page.h"
00018 #include "dbinc/db_shash.h"
00019 #include "dbinc/db_am.h"
00020 #include "dbinc/lock.h"
00021 #include "dbinc/mp.h"
00022 #include "dbinc/qam.h"
00023 #include "dbinc/txn.h"
00024
00025 static int __qam_rr __P((DB *, DB_TXN *,
00026 const char *, const char *, const char *, qam_name_op));
00027 static int __qam_set_extentsize __P((DB *, u_int32_t));
00028
00029
00030
00031
00032
00033
00034
00035 int
00036 __qam_db_create(dbp)
00037 DB *dbp;
00038 {
00039 QUEUE *t;
00040 int ret;
00041
00042
00043 if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(QUEUE), &t)) != 0)
00044 return (ret);
00045 dbp->q_internal = t;
00046 dbp->get_q_extentsize = __qam_get_extentsize;
00047 dbp->set_q_extentsize = __qam_set_extentsize;
00048
00049 t->re_pad = ' ';
00050
00051 return (0);
00052 }
00053
00054
00055
00056
00057
00058
00059
00060 int
00061 __qam_db_close(dbp, flags)
00062 DB *dbp;
00063 u_int32_t flags;
00064 {
00065 DB_MPOOLFILE *mpf;
00066 MPFARRAY *array;
00067 QUEUE *t;
00068 struct __qmpf *mpfp;
00069 u_int32_t i;
00070 int ret, t_ret;
00071
00072 ret = 0;
00073 if ((t = dbp->q_internal) == NULL)
00074 return (0);
00075
00076 array = &t->array1;
00077 again:
00078 mpfp = array->mpfarray;
00079 if (mpfp != NULL) {
00080 for (i = array->low_extent;
00081 i <= array->hi_extent; i++, mpfp++) {
00082 mpf = mpfp->mpf;
00083 mpfp->mpf = NULL;
00084 if (mpf != NULL && (t_ret = __memp_fclose(mpf,
00085 LF_ISSET(DB_AM_DISCARD) ? DB_MPOOL_DISCARD : 0))
00086 != 0 && ret == 0)
00087 ret = t_ret;
00088 }
00089 __os_free(dbp->dbenv, array->mpfarray);
00090 }
00091 if (t->array2.n_extent != 0) {
00092 array = &t->array2;
00093 array->n_extent = 0;
00094 goto again;
00095 }
00096
00097 if (LF_ISSET(DB_AM_DISCARD) &&
00098 (t_ret = __qam_nameop(dbp, NULL,
00099 NULL, QAM_NAME_DISCARD)) != 0 && ret == 0)
00100 ret = t_ret;
00101
00102 if (t->path != NULL)
00103 __os_free(dbp->dbenv, t->path);
00104 __os_free(dbp->dbenv, t);
00105 dbp->q_internal = NULL;
00106
00107 return (ret);
00108 }
00109
00110
00111
00112
00113
00114
00115
00116 int
00117 __qam_get_extentsize(dbp, q_extentsizep)
00118 DB *dbp;
00119 u_int32_t *q_extentsizep;
00120 {
00121 *q_extentsizep = ((QUEUE*)dbp->q_internal)->page_ext;
00122 return (0);
00123 }
00124
00125 static int
00126 __qam_set_extentsize(dbp, extentsize)
00127 DB *dbp;
00128 u_int32_t extentsize;
00129 {
00130 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_extentsize");
00131
00132 if (extentsize < 1) {
00133 __db_err(dbp->dbenv, "Extent size must be at least 1");
00134 return (EINVAL);
00135 }
00136
00137 ((QUEUE*)dbp->q_internal)->page_ext = extentsize;
00138
00139 return (0);
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149 int
00150 __queue_pageinfo(dbp, firstp, lastp, emptyp, prpage, flags)
00151 DB *dbp;
00152 db_pgno_t *firstp, *lastp;
00153 int *emptyp;
00154 int prpage;
00155 u_int32_t flags;
00156 {
00157 DB_MPOOLFILE *mpf;
00158 QMETA *meta;
00159 db_pgno_t first, i, last;
00160 int empty, ret, t_ret;
00161
00162 mpf = dbp->mpf;
00163
00164
00165 i = PGNO_BASE_MD;
00166 if ((ret = __memp_fget(mpf, &i, 0, &meta)) != 0)
00167 return (ret);
00168
00169 first = QAM_RECNO_PAGE(dbp, meta->first_recno);
00170 last = QAM_RECNO_PAGE(
00171 dbp, meta->cur_recno == 1 ? 1 : meta->cur_recno - 1);
00172
00173 empty = meta->cur_recno == meta->first_recno;
00174 if (firstp != NULL)
00175 *firstp = first;
00176 if (lastp != NULL)
00177 *lastp = last;
00178 if (emptyp != NULL)
00179 *emptyp = empty;
00180 #ifdef HAVE_STATISTICS
00181 if (prpage)
00182 ret = __db_prpage(dbp, (PAGE *)meta, flags);
00183 #else
00184 COMPQUIET(prpage, 0);
00185 COMPQUIET(flags, 0);
00186 #endif
00187
00188 if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
00189 ret = t_ret;
00190
00191 return (ret);
00192 }
00193
00194 #ifdef HAVE_STATISTICS
00195
00196
00197
00198
00199
00200
00201 int
00202 __db_prqueue(dbp, flags)
00203 DB *dbp;
00204 u_int32_t flags;
00205 {
00206 PAGE *h;
00207 db_pgno_t first, i, last, pg_ext, stop;
00208 int empty, ret;
00209
00210 if ((ret = __queue_pageinfo(dbp, &first, &last, &empty, 1, flags)) != 0)
00211 return (ret);
00212
00213 if (empty || ret != 0)
00214 return (ret);
00215
00216 i = first;
00217 if (first > last)
00218 stop = QAM_RECNO_PAGE(dbp, UINT32_MAX);
00219 else
00220 stop = last;
00221
00222
00223 begin:
00224 for (; i <= stop; ++i) {
00225 if ((ret = __qam_fget(dbp, &i, 0, &h)) != 0) {
00226 pg_ext = ((QUEUE *)dbp->q_internal)->page_ext;
00227 if (pg_ext == 0) {
00228 if (ret == DB_PAGE_NOTFOUND && first == last)
00229 return (0);
00230 return (ret);
00231 }
00232 if (ret == ENOENT || ret == DB_PAGE_NOTFOUND) {
00233 i += (pg_ext - ((i - 1) % pg_ext)) - 1;
00234 continue;
00235 }
00236 return (ret);
00237 }
00238 (void)__db_prpage(dbp, h, flags);
00239 if ((ret = __qam_fput(dbp, i, h, 0)) != 0)
00240 return (ret);
00241 }
00242
00243 if (first > last) {
00244 i = 1;
00245 stop = last;
00246 first = last;
00247 goto begin;
00248 }
00249 return (0);
00250 }
00251 #endif
00252
00253
00254
00255
00256
00257
00258
00259 int
00260 __qam_remove(dbp, txn, name, subdb)
00261 DB *dbp;
00262 DB_TXN *txn;
00263 const char *name, *subdb;
00264 {
00265 return (__qam_rr(dbp, txn, name, subdb, NULL, QAM_NAME_REMOVE));
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275 int
00276 __qam_rename(dbp, txn, name, subdb, newname)
00277 DB *dbp;
00278 DB_TXN *txn;
00279 const char *name, *subdb, *newname;
00280 {
00281 return (__qam_rr(dbp, txn, name, subdb, newname, QAM_NAME_RENAME));
00282 }
00283
00284
00285
00286
00287
00288 static int
00289 __qam_rr(dbp, txn, name, subdb, newname, op)
00290 DB *dbp;
00291 DB_TXN *txn;
00292 const char *name, *subdb, *newname;
00293 qam_name_op op;
00294 {
00295 DB_ENV *dbenv;
00296 DB *tmpdbp;
00297 QUEUE *qp;
00298 int ret, t_ret;
00299
00300 dbenv = dbp->dbenv;
00301 ret = 0;
00302
00303 PANIC_CHECK(dbenv);
00304
00305 if (subdb != NULL && name != NULL) {
00306 __db_err(dbenv,
00307 "Queue does not support multiple databases per file");
00308 return (EINVAL);
00309 }
00310
00311
00312
00313
00314
00315 if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
00316 tmpdbp = dbp;
00317 else {
00318 if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
00319 return (ret);
00320
00321
00322
00323
00324
00325 tmpdbp->lid = dbp->lid;
00326 if ((ret = __db_open(tmpdbp, txn,
00327 name, NULL, DB_QUEUE, DB_RDONLY, 0, PGNO_BASE_MD)) != 0)
00328 goto err;
00329 }
00330
00331 qp = (QUEUE *)tmpdbp->q_internal;
00332 if (qp->page_ext != 0)
00333 ret = __qam_nameop(tmpdbp, txn, newname, op);
00334
00335 if (!F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
00336 err:
00337
00338
00339
00340 tmpdbp->lid = DB_LOCK_INVALIDID;
00341
00342
00343 if (txn != NULL)
00344 __txn_remlock(dbenv,
00345 txn, &tmpdbp->handle_lock, DB_LOCK_INVALIDID);
00346
00347 if ((t_ret =
00348 __db_close(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
00349 ret = t_ret;
00350 }
00351 return (ret);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360 void
00361 __qam_map_flags(dbp, inflagsp, outflagsp)
00362 DB *dbp;
00363 u_int32_t *inflagsp, *outflagsp;
00364 {
00365 COMPQUIET(dbp, NULL);
00366
00367 if (FLD_ISSET(*inflagsp, DB_INORDER)) {
00368 FLD_SET(*outflagsp, DB_AM_INORDER);
00369 FLD_CLR(*inflagsp, DB_INORDER);
00370 }
00371 }
00372
00373
00374
00375
00376
00377
00378
00379 int
00380 __qam_set_flags(dbp, flagsp)
00381 DB *dbp;
00382 u_int32_t *flagsp;
00383 {
00384
00385 __qam_map_flags(dbp, flagsp, &dbp->flags);
00386 return (0);
00387 }