00001
00002
00003
00004
00005
00006
00007 #include "config.h"
00008
00009 #ifndef lint
00010 static const char revid[] = "$Id: log__register_8c-source.html,v 1.1 2008/06/08 10:20:30 sebdiaz Exp $";
00011 #endif
00012
00013 #ifndef NO_SYSTEM_INCLUDES
00014 #include <sys/types.h>
00015
00016 #include <errno.h>
00017 #include <string.h>
00018 #endif
00019
00020 #ifdef HAVE_RPC
00021 #include "db_server.h"
00022 #endif
00023
00024 #include "db_int.h"
00025 #include "log.h"
00026
00027 #ifdef HAVE_RPC
00028 #include "gen_client_ext.h"
00029 #include "rpc_client_ext.h"
00030 #endif
00031
00032
00033
00034
00035
00036 int
00037 CDB_log_register(dbenv, dbp, name)
00038 DB_ENV *dbenv;
00039 DB *dbp;
00040 const char *name;
00041 {
00042 DBT fid_dbt, r_name;
00043 DB_LOG *dblp;
00044 DB_LSN r_unused;
00045 FNAME *found, *fnp, *recover_fnp, *reuse_fnp;
00046 LOG *lp;
00047 size_t len;
00048 int32_t maxid;
00049 int inserted, ok, ret;
00050 void *namep;
00051
00052 #ifdef HAVE_RPC
00053 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00054 return (__dbcl_log_register(dbenv, dbp, name));
00055 #endif
00056
00057 PANIC_CHECK(dbenv);
00058 ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
00059
00060 dblp = dbenv->lg_handle;
00061 lp = dblp->reginfo.primary;
00062 fnp = reuse_fnp = NULL;
00063 inserted = ret = 0;
00064 namep = NULL;
00065
00066
00067 if (dbp->type != DB_BTREE && dbp->type != DB_QUEUE &&
00068 dbp->type != DB_HASH && dbp->type != DB_RECNO) {
00069 CDB___db_err(dbenv, "CDB_log_register: unknown DB file type");
00070 return (EINVAL);
00071 }
00072
00073 R_LOCK(dbenv, &dblp->reginfo);
00074
00075
00076
00077
00078
00079
00080
00081 ok = 0;
00082 found = NULL;
00083 recover_fnp = NULL;
00084 for (maxid = 0, fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
00085 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
00086 if (F_ISSET(dblp, DBLOG_RECOVER) && fnp->id == dbp->log_fileid)
00087 recover_fnp = fnp;
00088 if (fnp->ref == 0) {
00089 if (reuse_fnp == NULL)
00090 reuse_fnp = fnp;
00091 continue;
00092 }
00093 if (memcmp(dbp->fileid, fnp->ufid, DB_FILE_ID_LEN) == 0) {
00094 if (fnp->meta_pgno == 0) {
00095 if (fnp->locked == 1) {
00096 CDB___db_err(dbenv, "File is locked");
00097 return (EINVAL);
00098 }
00099 if (found != NULL)
00100 goto found;
00101 ok = 1;
00102 }
00103 if (dbp->meta_pgno == fnp->meta_pgno) {
00104 if (F_ISSET(dblp, DBLOG_RECOVER)) {
00105 if (fnp->id != dbp->log_fileid) {
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 CDB___log_rem_logid(dblp,
00117 NULL, fnp->id);
00118 if (recover_fnp != NULL)
00119 break;
00120 continue;
00121 }
00122 fnp->ref = 1;
00123 goto found;
00124 }
00125 ++fnp->ref;
00126 if (ok)
00127 goto found;
00128 found = fnp;
00129 }
00130 }
00131 if (maxid <= fnp->id)
00132 maxid = fnp->id + 1;
00133 }
00134 if ((fnp = found) != NULL)
00135 goto found;
00136
00137
00138 if (recover_fnp != NULL)
00139 fnp = recover_fnp;
00140 else if (reuse_fnp != NULL)
00141 fnp = reuse_fnp;
00142 else {
00143 if ((ret = CDB___db_shalloc(dblp->reginfo.addr,
00144 sizeof(FNAME), 0, &fnp)) != 0)
00145 goto mem_err;
00146 fnp->id = maxid;
00147 }
00148
00149 if (F_ISSET(dblp, DBLOG_RECOVER))
00150 fnp->id = dbp->log_fileid;
00151
00152 fnp->ref = 1;
00153 fnp->locked = 0;
00154 fnp->s_type = dbp->type;
00155 memcpy(fnp->ufid, dbp->fileid, DB_FILE_ID_LEN);
00156 fnp->meta_pgno = dbp->meta_pgno;
00157
00158 if (name != NULL) {
00159 len = strlen(name) + 1;
00160 if ((ret =
00161 CDB___db_shalloc(dblp->reginfo.addr, len, 0, &namep)) != 0) {
00162 mem_err: CDB___db_err(dbenv,
00163 "Unable to allocate memory to register %s", namep);
00164 goto err;
00165 }
00166 fnp->name_off = R_OFFSET(&dblp->reginfo, namep);
00167 memcpy(namep, name, len);
00168 } else
00169 fnp->name_off = INVALID_ROFF;
00170
00171
00172 if (reuse_fnp == NULL && recover_fnp == NULL)
00173 SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
00174 inserted = 1;
00175
00176
00177 if (!F_ISSET(dblp, DBLOG_RECOVER)) {
00178
00179
00180
00181
00182 if (name != NULL) {
00183 r_name.data = (void *)name;
00184 r_name.size = strlen(name) + 1;
00185 }
00186 memset(&fid_dbt, 0, sizeof(fid_dbt));
00187 fid_dbt.data = dbp->fileid;
00188 fid_dbt.size = DB_FILE_ID_LEN;
00189 if ((ret = CDB___log_register_log(dbenv, NULL, &r_unused,
00190 0, LOG_OPEN, name == NULL ? NULL : &r_name,
00191 &fid_dbt, fnp->id, dbp->type, dbp->meta_pgno)) != 0)
00192 goto err;
00193 }
00194
00195 found:
00196
00197
00198
00199
00200 if (!F_ISSET(dblp, DBLOG_RECOVER) &&
00201 (ret = CDB___log_add_logid(dbenv, dblp, dbp, fnp->id)) != 0)
00202 goto err;
00203
00204 if (!F_ISSET(dblp, DBLOG_RECOVER))
00205 dbp->log_fileid = fnp->id;
00206
00207 if (0) {
00208 err: if (inserted)
00209 SH_TAILQ_REMOVE(&lp->fq, fnp, q, __fname);
00210 if (namep != NULL)
00211 CDB___db_shalloc_free(dblp->reginfo.addr, namep);
00212 if (fnp != NULL)
00213 CDB___db_shalloc_free(dblp->reginfo.addr, fnp);
00214 }
00215
00216 R_UNLOCK(dbenv, &dblp->reginfo);
00217
00218 return (ret);
00219 }
00220
00221
00222
00223
00224
00225 int
00226 CDB_log_unregister(dbenv, dbp)
00227 DB_ENV *dbenv;
00228 DB *dbp;
00229 {
00230 int ret;
00231
00232 #ifdef HAVE_RPC
00233 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00234 return (__dbcl_log_unregister(dbenv, dbp));
00235 #endif
00236
00237 PANIC_CHECK(dbenv);
00238 ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
00239
00240 ret = CDB___log_filelist_update(dbenv, dbp, dbp->log_fileid, NULL, NULL);
00241 dbp->log_fileid = DB_LOGFILEID_INVALID;
00242 return (ret);
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 int CDB___log_filelist_update(dbenv, dbp, fid, newname, set)
00257 DB_ENV *dbenv;
00258 DB *dbp;
00259 int32_t fid;
00260 const char *newname;
00261 int *set;
00262 {
00263 DBT fid_dbt, r_name;
00264 DB_LOG *dblp;
00265 DB_LSN r_unused;
00266 FNAME *fnp;
00267 LOG *lp;
00268 u_int32_t len, newlen;
00269 int ret;
00270 void *namep;
00271
00272 ret = 0;
00273 dblp = dbenv->lg_handle;
00274 lp = dblp->reginfo.primary;
00275
00276 R_LOCK(dbenv, &dblp->reginfo);
00277
00278
00279 for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
00280 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname))
00281 if (fid == fnp->id)
00282 break;
00283 if (fnp == NULL) {
00284 CDB___db_err(dbenv, "CDB_log_unregister: non-existent file id");
00285 ret = EINVAL;
00286 goto ret1;
00287 }
00288
00289
00290
00291
00292
00293
00294
00295 namep = NULL;
00296 len = 0;
00297 if (fnp->name_off != INVALID_ROFF) {
00298 namep = R_ADDR(&dblp->reginfo, fnp->name_off);
00299 len = strlen(namep) + 1;
00300 }
00301 if (!F_ISSET(dblp, DBLOG_RECOVER) && fnp->ref == 1) {
00302 if (namep != NULL) {
00303 memset(&r_name, 0, sizeof(r_name));
00304 r_name.data = namep;
00305 r_name.size = len;
00306 }
00307 memset(&fid_dbt, 0, sizeof(fid_dbt));
00308 fid_dbt.data = fnp->ufid;
00309 fid_dbt.size = DB_FILE_ID_LEN;
00310 if ((ret = CDB___log_register_log(dbenv, NULL, &r_unused,
00311 0, LOG_CLOSE,
00312 fnp->name_off == INVALID_ROFF ? NULL : &r_name,
00313 &fid_dbt, fid, fnp->s_type, fnp->meta_pgno))
00314 != 0)
00315 goto ret1;
00316 }
00317
00318
00319
00320
00321 if (newname != NULL) {
00322 DB_ASSERT(fnp->ref == 1);
00323 newlen = strlen(newname) + 1;
00324 if (!F_ISSET(dblp, DBLOG_RECOVER)) {
00325 r_name.data = (void *) newname;
00326 r_name.size = newlen;
00327 if ((ret = CDB___log_register_log(dbenv,
00328 NULL, &r_unused, 0, LOG_OPEN, &r_name, &fid_dbt,
00329 fnp->id, fnp->s_type, fnp->meta_pgno)) != 0)
00330 goto ret1;
00331 }
00332
00333
00334
00335
00336 if (set != NULL) {
00337 if (len != newlen || memcmp(namep, newname, len) != 0)
00338 *set = 1;
00339 else {
00340 *set = 0;
00341 goto ret1;
00342 }
00343 }
00344
00345
00346
00347
00348 if (len < newlen) {
00349 CDB___db_shalloc_free(dblp->reginfo.addr,
00350 R_ADDR(&dblp->reginfo, fnp->name_off));
00351 if ((ret = CDB___db_shalloc(
00352 dblp->reginfo.addr, newlen, 0, &namep)) != 0) {
00353 CDB___db_err(dbenv,
00354 "Unable to allocate memory to register %s",
00355 namep);
00356 goto ret1;
00357 }
00358 fnp->name_off = R_OFFSET(&dblp->reginfo, namep);
00359 } else
00360 namep = R_ADDR(&dblp->reginfo, fnp->name_off);
00361 memcpy(namep, newname, newlen);
00362 } else {
00363
00364
00365
00366
00367
00368 DB_ASSERT(fnp->ref >= 1);
00369 --fnp->ref;
00370 if (fnp->ref == 0) {
00371 if (fnp->name_off != INVALID_ROFF)
00372 CDB___db_shalloc_free(dblp->reginfo.addr,
00373 R_ADDR(&dblp->reginfo, fnp->name_off));
00374 fnp->name_off = INVALID_ROFF;
00375 }
00376
00377
00378
00379
00380
00381
00382 if (!F_ISSET(dblp, DBLOG_RECOVER))
00383 CDB___log_rem_logid(dblp, dbp, fid);
00384 }
00385
00386 ret1: R_UNLOCK(dbenv, &dblp->reginfo);
00387 return (ret);
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 int
00397 CDB___log_file_lock(dbp)
00398 DB *dbp;
00399 {
00400 DB_ENV *dbenv;
00401 DB_LOG *dblp;
00402 FNAME *found, *fnp;
00403 LOG *lp;
00404 int ret;
00405
00406 dbenv = dbp->dbenv;
00407 dblp = dbenv->lg_handle;
00408 lp = dblp->reginfo.primary;
00409
00410 found = NULL;
00411 ret = 0;
00412 R_LOCK(dbenv, &dblp->reginfo);
00413
00414 for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
00415 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
00416 if (fnp->ref == 0)
00417 continue;
00418
00419 if (!memcmp(dbp->fileid, fnp->ufid, DB_FILE_ID_LEN)) {
00420 if (fnp->meta_pgno == 0) {
00421 if (fnp->ref != 1)
00422 goto err;
00423
00424 fnp->locked = 1;
00425 found = fnp;
00426 } else {
00427 err: CDB___db_err(dbp->dbenv, "File is open");
00428 ret = EINVAL;
00429 goto done;
00430 }
00431
00432 }
00433 }
00434 done: R_UNLOCK(dbenv, &dblp->reginfo);
00435 return (ret);
00436 }