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
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/crypto.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/db_shash.h"
00022 #include "dbinc/db_swap.h"
00023 #include "dbinc/db_am.h"
00024 #include "dbinc/lock.h"
00025 #include "dbinc/mp.h"
00026 #include "dbinc/qam.h"
00027 #include "dbinc/fop.h"
00028
00029 static int __qam_init_meta __P((DB *, QMETA *));
00030
00031
00032
00033
00034
00035
00036
00037 int
00038 __qam_open(dbp, txn, name, base_pgno, mode, flags)
00039 DB *dbp;
00040 DB_TXN *txn;
00041 const char *name;
00042 db_pgno_t base_pgno;
00043 int mode;
00044 u_int32_t flags;
00045 {
00046 DBC *dbc;
00047 DB_ENV *dbenv;
00048 DB_LOCK metalock;
00049 DB_MPOOLFILE *mpf;
00050 QMETA *qmeta;
00051 QUEUE *t;
00052 int ret, t_ret;
00053
00054 dbenv = dbp->dbenv;
00055 mpf = dbp->mpf;
00056 t = dbp->q_internal;
00057 ret = 0;
00058 qmeta = NULL;
00059
00060 if (name == NULL && t->page_ext != 0) {
00061 __db_err(dbenv,
00062 "Extent size may not be specified for in-memory queue database");
00063 return (EINVAL);
00064 }
00065
00066
00067 dbp->db_am_remove = __qam_remove;
00068 dbp->db_am_rename = __qam_rename;
00069
00070
00071
00072
00073
00074
00075
00076 if ((ret = __db_cursor(dbp, txn, &dbc,
00077 LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ?
00078 DB_WRITECURSOR : 0)) != 0)
00079 return (ret);
00080
00081
00082
00083
00084
00085
00086 if ((ret =
00087 __db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0)
00088 goto err;
00089 if ((ret = __memp_fget(mpf, &base_pgno, 0, &qmeta)) != 0)
00090 goto err;
00091
00092
00093 if (qmeta->dbmeta.magic != DB_QAMMAGIC) {
00094 __db_err(dbenv, "%s: unexpected file type or format", name);
00095 ret = EINVAL;
00096 goto err;
00097 }
00098
00099
00100 t->page_ext = qmeta->page_ext;
00101
00102 if (t->page_ext != 0 && (ret = __qam_set_ext_data(dbp, name)) != 0)
00103 goto err;
00104
00105 if (mode == 0)
00106 mode = __db_omode("rw-rw----");
00107 t->mode = mode;
00108 t->re_pad = qmeta->re_pad;
00109 t->re_len = qmeta->re_len;
00110 t->rec_page = qmeta->rec_page;
00111
00112 t->q_meta = base_pgno;
00113 t->q_root = base_pgno + 1;
00114
00115 err: if (qmeta != NULL &&
00116 (t_ret = __memp_fput(mpf, qmeta, 0)) != 0 && ret == 0)
00117 ret = t_ret;
00118
00119
00120 if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
00121 ret = t_ret;
00122
00123 if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
00124 ret = t_ret;
00125
00126 return (ret);
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 int
00136 __qam_set_ext_data(dbp, name)
00137 DB *dbp;
00138 const char *name;
00139 {
00140 QUEUE *t;
00141 int ret;
00142
00143 t = dbp->q_internal;
00144 t->pginfo.db_pagesize = dbp->pgsize;
00145 t->pginfo.flags =
00146 F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
00147 t->pginfo.type = dbp->type;
00148 t->pgcookie.data = &t->pginfo;
00149 t->pgcookie.size = sizeof(DB_PGINFO);
00150
00151 if ((ret = __os_strdup(dbp->dbenv, name, &t->path)) != 0)
00152 return (ret);
00153 t->dir = t->path;
00154 if ((t->name = __db_rpath(t->path)) == NULL) {
00155 t->name = t->path;
00156 t->dir = PATH_DOT;
00157 } else
00158 *t->name++ = '\0';
00159
00160 return (0);
00161 }
00162
00163
00164
00165
00166
00167
00168 int
00169 __qam_metachk(dbp, name, qmeta)
00170 DB *dbp;
00171 const char *name;
00172 QMETA *qmeta;
00173 {
00174 DB_ENV *dbenv;
00175 u_int32_t vers;
00176 int ret;
00177
00178 dbenv = dbp->dbenv;
00179 ret = 0;
00180
00181
00182
00183
00184
00185 vers = qmeta->dbmeta.version;
00186 if (F_ISSET(dbp, DB_AM_SWAP))
00187 M_32_SWAP(vers);
00188 switch (vers) {
00189 case 1:
00190 case 2:
00191 __db_err(dbenv,
00192 "%s: queue version %lu requires a version upgrade",
00193 name, (u_long)vers);
00194 return (DB_OLD_VERSION);
00195 case 3:
00196 case 4:
00197 break;
00198 default:
00199 __db_err(dbenv,
00200 "%s: unsupported qam version: %lu", name, (u_long)vers);
00201 return (EINVAL);
00202 }
00203
00204
00205 if (F_ISSET(dbp, DB_AM_SWAP) && (ret = __qam_mswap((PAGE *)qmeta)) != 0)
00206 return (ret);
00207
00208
00209 if (dbp->type != DB_QUEUE && dbp->type != DB_UNKNOWN)
00210 return (EINVAL);
00211 dbp->type = DB_QUEUE;
00212 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE);
00213
00214
00215 dbp->pgsize = qmeta->dbmeta.pagesize;
00216
00217
00218 memcpy(dbp->fileid, qmeta->dbmeta.uid, DB_FILE_ID_LEN);
00219
00220
00221 dbp->db_am_rename = __qam_rename;
00222 dbp->db_am_remove = __qam_remove;
00223
00224 return (ret);
00225 }
00226
00227
00228
00229
00230
00231 static int
00232 __qam_init_meta(dbp, meta)
00233 DB *dbp;
00234 QMETA *meta;
00235 {
00236 QUEUE *t;
00237
00238 t = dbp->q_internal;
00239
00240 memset(meta, 0, sizeof(QMETA));
00241 LSN_NOT_LOGGED(meta->dbmeta.lsn);
00242 meta->dbmeta.pgno = PGNO_BASE_MD;
00243 meta->dbmeta.last_pgno = 0;
00244 meta->dbmeta.magic = DB_QAMMAGIC;
00245 meta->dbmeta.version = DB_QAMVERSION;
00246 meta->dbmeta.pagesize = dbp->pgsize;
00247 if (F_ISSET(dbp, DB_AM_CHKSUM))
00248 FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM);
00249 if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
00250 meta->dbmeta.encrypt_alg =
00251 ((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg;
00252 DB_ASSERT(meta->dbmeta.encrypt_alg != 0);
00253 meta->crypto_magic = meta->dbmeta.magic;
00254 }
00255 meta->dbmeta.type = P_QAMMETA;
00256 meta->re_pad = t->re_pad;
00257 meta->re_len = t->re_len;
00258 meta->rec_page = CALC_QAM_RECNO_PER_PAGE(dbp);
00259 meta->cur_recno = 1;
00260 meta->first_recno = 1;
00261 meta->page_ext = t->page_ext;
00262 t->rec_page = meta->rec_page;
00263 memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
00264
00265
00266 if (QAM_RECNO_PER_PAGE(dbp) < 1) {
00267 __db_err(dbp->dbenv,
00268 "Record size of %lu too large for page size of %lu",
00269 (u_long)t->re_len, (u_long)dbp->pgsize);
00270 return (EINVAL);
00271 }
00272
00273 return (0);
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 int
00289 __qam_new_file(dbp, txn, fhp, name)
00290 DB *dbp;
00291 DB_TXN *txn;
00292 DB_FH *fhp;
00293 const char *name;
00294 {
00295 QMETA *meta;
00296 DB_ENV *dbenv;
00297 DB_MPOOLFILE *mpf;
00298 DB_PGINFO pginfo;
00299 DBT pdbt;
00300 db_pgno_t pgno;
00301 int ret;
00302 void *buf;
00303
00304 dbenv = dbp->dbenv;
00305 mpf = dbp->mpf;
00306 buf = NULL;
00307 meta = NULL;
00308
00309
00310
00311 if (F_ISSET(dbp, DB_AM_INMEM)) {
00312 pgno = PGNO_BASE_MD;
00313 ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &meta);
00314 } else {
00315 ret = __os_calloc(dbenv, 1, dbp->pgsize, &buf);
00316 meta = (QMETA *)buf;
00317 }
00318 if (ret != 0)
00319 return (ret);
00320
00321 if ((ret = __qam_init_meta(dbp, meta)) != 0)
00322 goto err;
00323
00324 if (F_ISSET(dbp, DB_AM_INMEM)) {
00325 if ((ret = __db_log_page(dbp,
00326 txn, &meta->dbmeta.lsn, pgno, (PAGE *)meta)) != 0)
00327 goto err;
00328 ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
00329 } else {
00330 pginfo.db_pagesize = dbp->pgsize;
00331 pginfo.flags =
00332 F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
00333 pginfo.type = DB_QUEUE;
00334 pdbt.data = &pginfo;
00335 pdbt.size = sizeof(pginfo);
00336 if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
00337 goto err;
00338 ret = __fop_write(dbenv, txn, name,
00339 DB_APP_DATA, fhp, dbp->pgsize, 0, 0, buf, dbp->pgsize, 1,
00340 F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
00341 }
00342 if (ret != 0)
00343 goto err;
00344 meta = NULL;
00345
00346 err: if (name != NULL)
00347 __os_free(dbenv, buf);
00348 else if (meta != NULL)
00349 (void)__memp_fput(mpf, meta, 0);
00350 return (ret);
00351 }