Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

qam_method.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1999-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: qam_method.c,v 12.2 2005/09/28 17:45:01 margo Exp $
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  * __qam_db_create --
00031  *      Queue specific initialization of the DB structure.
00032  *
00033  * PUBLIC: int __qam_db_create __P((DB *));
00034  */
00035 int
00036 __qam_db_create(dbp)
00037         DB *dbp;
00038 {
00039         QUEUE *t;
00040         int ret;
00041 
00042         /* Allocate and initialize the private queue structure. */
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  * __qam_db_close --
00056  *      Queue specific discard of the DB structure.
00057  *
00058  * PUBLIC: int __qam_db_close __P((DB *, u_int32_t));
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  * __qam_get_extentsize --
00112  *      The DB->q_get_extentsize method.
00113  *
00114  * PUBLIC: int __qam_get_extentsize __P((DB *, u_int32_t *));
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  * __queue_pageinfo -
00144  *      Given a dbp, get first/last page information about a queue.
00145  *
00146  * PUBLIC: int __queue_pageinfo __P((DB *, db_pgno_t *, db_pgno_t *,
00147  * PUBLIC:       int *, int, u_int32_t));
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         /* Find out the page number of the last page in the database. */
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  * __db_prqueue --
00197  *      Print out a queue
00198  *
00199  * PUBLIC: int __db_prqueue __P((DB *, u_int32_t));
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         /* Dump each page. */
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  * __qam_remove --
00255  *      Remove method for a Queue.
00256  *
00257  * PUBLIC: int __qam_remove __P((DB *, DB_TXN *, const char *, const char *));
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  * __qam_rename --
00270  *      Rename method for a Queue.
00271  *
00272  * PUBLIC: int __qam_rename __P((DB *,
00273  * PUBLIC:         DB_TXN *, const char *, const char *, const char *));
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  * __qam_rr --
00286  *      Remove/Rename method for a Queue.
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          * Since regular rename no longer opens the database, we may have
00313          * to do it here.
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                  * We need to make sure we don't self-deadlock, so give
00323                  * this dbp the same locker as the incoming one.
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                  * Since we copied the locker ID from the dbp, we'd better not
00338                  * free it here.
00339                  */
00340                 tmpdbp->lid = DB_LOCK_INVALIDID;
00341 
00342                 /* We need to remove the lock event we associated with this. */
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  * __qam_map_flags --
00356  *      Map queue-specific flags from public to the internal values.
00357  *
00358  * PUBLIC: void __qam_map_flags __P((DB *, u_int32_t *, u_int32_t *));
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  * __qam_set_flags --
00375  *      Set queue-specific flags.
00376  *
00377  * PUBLIC: int __qam_set_flags __P((DB *, u_int32_t *flagsp));
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 }

Generated on Sun Dec 25 12:14:44 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2