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 <stdlib.h>
00016 #include <string.h>
00017 #endif
00018
00019 #include "db_int.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/log.h"
00022 #include "dbinc/qam.h"
00023 #include "dbinc/txn.h"
00024
00025 static int __absname __P((DB_ENV *, char *, char *, char **));
00026 static int __build_data __P((DB_ENV *, char *, char ***));
00027 static int __cmpfunc __P((const void *, const void *));
00028 static int __log_archive __P((DB_ENV *, char **[], u_int32_t));
00029 static int __usermem __P((DB_ENV *, char ***));
00030
00031
00032
00033
00034
00035
00036
00037 int
00038 __log_archive_pp(dbenv, listp, flags)
00039 DB_ENV *dbenv;
00040 char ***listp;
00041 u_int32_t flags;
00042 {
00043 DB_THREAD_INFO *ip;
00044 int ret;
00045
00046 PANIC_CHECK(dbenv);
00047 ENV_REQUIRES_CONFIG(dbenv,
00048 dbenv->lg_handle, "DB_ENV->log_archive", DB_INIT_LOG);
00049
00050 #define OKFLAGS (DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG | DB_ARCH_REMOVE)
00051 if (flags != 0) {
00052 if ((ret = __db_fchk(
00053 dbenv, "DB_ENV->log_archive", flags, OKFLAGS)) != 0)
00054 return (ret);
00055 if ((ret = __db_fcchk(dbenv, "DB_ENV->log_archive",
00056 flags, DB_ARCH_DATA, DB_ARCH_LOG)) != 0)
00057 return (ret);
00058 if ((ret = __db_fcchk(dbenv, "DB_ENV->log_archive",
00059 flags, DB_ARCH_REMOVE,
00060 DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG)) != 0)
00061 return (ret);
00062 }
00063
00064 ENV_ENTER(dbenv, ip);
00065 REPLICATION_WRAP(dbenv, (__log_archive(dbenv, listp, flags)), ret);
00066 ENV_LEAVE(dbenv, ip);
00067 return (ret);
00068 }
00069
00070
00071
00072
00073
00074 static int
00075 __log_archive(dbenv, listp, flags)
00076 DB_ENV *dbenv;
00077 char ***listp;
00078 u_int32_t flags;
00079 {
00080 DBT rec;
00081 DB_LOG *dblp;
00082 LOG *lp;
00083 DB_LOGC *logc;
00084 DB_LSN stable_lsn;
00085 u_int array_size, n;
00086 u_int32_t fnum;
00087 int ret, t_ret;
00088 char **array, **arrayp, *name, *p, *pref;
00089
00090 dblp = dbenv->lg_handle;
00091 lp = (LOG *)dblp->reginfo.primary;
00092 array = NULL;
00093 name = NULL;
00094 ret = 0;
00095 COMPQUIET(fnum, 0);
00096
00097 if (flags != DB_ARCH_REMOVE)
00098 *listp = NULL;
00099
00100
00101 if (lp->db_log_inmemory) {
00102 LF_CLR(~DB_ARCH_DATA);
00103 if (flags == 0)
00104 return (0);
00105 }
00106
00107
00108
00109
00110
00111 if (!LF_ISSET(DB_ARCH_DATA) &&
00112 !LF_ISSET(DB_ARCH_LOG) && __rep_noarchive(dbenv))
00113 return (0);
00114
00115
00116
00117
00118
00119 pref = LF_ISSET(DB_ARCH_ABS) ? dbenv->db_abshome : NULL;
00120
00121 LF_CLR(DB_ARCH_ABS);
00122 switch (flags) {
00123 case DB_ARCH_DATA:
00124 ret = __build_data(dbenv, pref, listp);
00125 goto err;
00126 case DB_ARCH_LOG:
00127 memset(&rec, 0, sizeof(rec));
00128 if ((ret = __log_cursor(dbenv, &logc)) != 0)
00129 goto err;
00130 #ifdef UMRW
00131 ZERO_LSN(stable_lsn);
00132 #endif
00133 ret = __log_c_get(logc, &stable_lsn, &rec, DB_LAST);
00134 if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
00135 ret = t_ret;
00136 if (ret != 0)
00137 goto err;
00138 fnum = stable_lsn.file;
00139 break;
00140 case DB_ARCH_REMOVE:
00141 __log_autoremove(dbenv);
00142 goto err;
00143 case 0:
00144
00145 ret = __log_get_stable_lsn(dbenv, &stable_lsn);
00146
00147
00148
00149
00150
00151 if (ret != 0) {
00152 if (ret == DB_NOTFOUND)
00153 ret = 0;
00154 goto err;
00155 }
00156
00157 fnum = stable_lsn.file - 1;
00158 break;
00159 default:
00160 DB_ASSERT(0);
00161 ret = EINVAL;
00162 goto err;
00163 }
00164
00165 #define LIST_INCREMENT 64
00166
00167 array_size = 64;
00168 if ((ret = __os_malloc(dbenv,
00169 sizeof(char *) * array_size, &array)) != 0)
00170 goto err;
00171 array[0] = NULL;
00172
00173
00174 for (n = 0; fnum > 0; --fnum) {
00175 if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0)
00176 goto err;
00177 if (__os_exists(name, NULL) != 0) {
00178 if (LF_ISSET(DB_ARCH_LOG) && fnum == stable_lsn.file)
00179 continue;
00180 __os_free(dbenv, name);
00181 name = NULL;
00182 break;
00183 }
00184
00185 if (n >= array_size - 2) {
00186 array_size += LIST_INCREMENT;
00187 if ((ret = __os_realloc(dbenv,
00188 sizeof(char *) * array_size, &array)) != 0)
00189 goto err;
00190 }
00191
00192 if (pref != NULL) {
00193 if ((ret =
00194 __absname(dbenv, pref, name, &array[n])) != 0)
00195 goto err;
00196 __os_free(dbenv, name);
00197 } else if ((p = __db_rpath(name)) != NULL) {
00198 if ((ret = __os_strdup(dbenv, p + 1, &array[n])) != 0)
00199 goto err;
00200 __os_free(dbenv, name);
00201 } else
00202 array[n] = name;
00203
00204 name = NULL;
00205 array[++n] = NULL;
00206 }
00207
00208
00209 if (n == 0)
00210 goto err;
00211
00212
00213 qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
00214
00215
00216 if ((ret = __usermem(dbenv, &array)) != 0)
00217 goto err;
00218
00219 if (listp != NULL)
00220 *listp = array;
00221
00222 if (0) {
00223 err: if (array != NULL) {
00224 for (arrayp = array; *arrayp != NULL; ++arrayp)
00225 __os_free(dbenv, *arrayp);
00226 __os_free(dbenv, array);
00227 }
00228 if (name != NULL)
00229 __os_free(dbenv, name);
00230 }
00231
00232 return (ret);
00233 }
00234
00235
00236
00237
00238
00239
00240
00241 int
00242 __log_get_stable_lsn(dbenv, stable_lsn)
00243 DB_ENV *dbenv;
00244 DB_LSN *stable_lsn;
00245 {
00246 DB_LOGC *logc;
00247 DBT rec;
00248 __txn_ckp_args *ckp_args;
00249 int ret, t_ret;
00250
00251 ret = 0;
00252 memset(&rec, 0, sizeof(rec));
00253 if (!TXN_ON(dbenv)) {
00254 if ((ret = __log_get_cached_ckp_lsn(dbenv, stable_lsn)) != 0)
00255 goto err;
00256
00257
00258
00259
00260
00261
00262 if (IS_ZERO_LSN(*stable_lsn) && (ret =
00263 __txn_findlastckp(dbenv, stable_lsn, NULL)) != 0)
00264 goto err;
00265
00266
00267
00268
00269 if (IS_ZERO_LSN(*stable_lsn)) {
00270 ret = DB_NOTFOUND;
00271 goto err;
00272 }
00273 } else if ((ret = __txn_getckp(dbenv, stable_lsn)) != 0)
00274 goto err;
00275 if ((ret = __log_cursor(dbenv, &logc)) != 0)
00276 goto err;
00277
00278
00279
00280
00281 if ((ret = __log_c_get(logc, stable_lsn, &rec, DB_SET)) == 0 &&
00282 (ret = __txn_ckp_read(dbenv, rec.data, &ckp_args)) == 0) {
00283 *stable_lsn = ckp_args->ckp_lsn;
00284 __os_free(dbenv, ckp_args);
00285 }
00286 if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
00287 ret = t_ret;
00288 err:
00289 return (ret);
00290 }
00291
00292
00293
00294
00295
00296
00297
00298 void
00299 __log_autoremove(dbenv)
00300 DB_ENV *dbenv;
00301 {
00302 int ret;
00303 char **begin, **list;
00304
00305
00306
00307
00308
00309
00310
00311 if ((ret = __log_archive(dbenv, &list, DB_ARCH_ABS)) != 0) {
00312 if (ret != DB_NOTFOUND)
00313 __db_err(dbenv,
00314 "log file auto-remove: %s", db_strerror(ret));
00315 return;
00316 }
00317
00318
00319
00320
00321
00322 if (list != NULL) {
00323 for (begin = list; *list != NULL; ++list)
00324 (void)__os_unlink(dbenv, *list);
00325 __os_ufree(dbenv, begin);
00326 }
00327 }
00328
00329
00330
00331
00332
00333 static int
00334 __build_data(dbenv, pref, listp)
00335 DB_ENV *dbenv;
00336 char *pref, ***listp;
00337 {
00338 DBT rec;
00339 DB_LOGC *logc;
00340 DB_LSN lsn;
00341 __dbreg_register_args *argp;
00342 u_int array_size, last, n, nxt;
00343 u_int32_t rectype;
00344 int ret, t_ret;
00345 char **array, **arrayp, **list, **lp, *p, *real_name;
00346
00347
00348 array_size = 64;
00349 if ((ret = __os_malloc(dbenv,
00350 sizeof(char *) * array_size, &array)) != 0)
00351 return (ret);
00352 array[0] = NULL;
00353
00354 memset(&rec, 0, sizeof(rec));
00355 if ((ret = __log_cursor(dbenv, &logc)) != 0)
00356 return (ret);
00357 for (n = 0; (ret = __log_c_get(logc, &lsn, &rec, DB_PREV)) == 0;) {
00358 if (rec.size < sizeof(rectype)) {
00359 ret = EINVAL;
00360 __db_err(dbenv, "DB_ENV->log_archive: bad log record");
00361 break;
00362 }
00363
00364 memcpy(&rectype, rec.data, sizeof(rectype));
00365 if (rectype != DB___dbreg_register)
00366 continue;
00367 if ((ret =
00368 __dbreg_register_read(dbenv, rec.data, &argp)) != 0) {
00369 ret = EINVAL;
00370 __db_err(dbenv,
00371 "DB_ENV->log_archive: unable to read log record");
00372 break;
00373 }
00374
00375 if (n >= array_size - 2) {
00376 array_size += LIST_INCREMENT;
00377 if ((ret = __os_realloc(dbenv,
00378 sizeof(char *) * array_size, &array)) != 0)
00379 goto free_continue;
00380 }
00381
00382 if ((ret = __os_strdup(dbenv,
00383 argp->name.data, &array[n++])) != 0)
00384 goto free_continue;
00385 array[n] = NULL;
00386
00387 if (argp->ftype == DB_QUEUE) {
00388 if ((ret = __qam_extent_names(dbenv,
00389 argp->name.data, &list)) != 0)
00390 goto q_err;
00391 for (lp = list;
00392 lp != NULL && *lp != NULL; lp++) {
00393 if (n >= array_size - 2) {
00394 array_size += LIST_INCREMENT;
00395 if ((ret = __os_realloc(dbenv,
00396 sizeof(char *) *
00397 array_size, &array)) != 0)
00398 goto q_err;
00399 }
00400 if ((ret =
00401 __os_strdup(dbenv, *lp, &array[n++])) != 0)
00402 goto q_err;
00403 array[n] = NULL;
00404 }
00405 q_err: if (list != NULL)
00406 __os_free(dbenv, list);
00407 }
00408 free_continue: __os_free(dbenv, argp);
00409 if (ret != 0)
00410 break;
00411 }
00412 if (ret == DB_NOTFOUND)
00413 ret = 0;
00414 if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
00415 ret = t_ret;
00416 if (ret != 0)
00417 goto err1;
00418
00419
00420 if (n == 0) {
00421 ret = 0;
00422 *listp = NULL;
00423 goto err1;
00424 }
00425
00426
00427 qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
00428
00429
00430
00431
00432
00433 for (last = nxt = 0; nxt < n;) {
00434
00435
00436
00437
00438
00439 if (last != nxt) {
00440 array[last] = array[nxt];
00441 array[nxt] = NULL;
00442 }
00443 for (++nxt; nxt < n &&
00444 strcmp(array[last], array[nxt]) == 0; ++nxt) {
00445 __os_free(dbenv, array[nxt]);
00446 array[nxt] = NULL;
00447 }
00448
00449
00450 if ((ret = __db_appname(dbenv,
00451 DB_APP_DATA, array[last], 0, NULL, &real_name)) != 0)
00452 goto err2;
00453
00454
00455 if (__os_exists(real_name, NULL) != 0) {
00456 __os_free(dbenv, real_name);
00457 __os_free(dbenv, array[last]);
00458 array[last] = NULL;
00459 continue;
00460 }
00461
00462
00463 __os_free(dbenv, array[last]);
00464 array[last] = NULL;
00465 if (pref != NULL) {
00466 ret = __absname(dbenv, pref, real_name, &array[last]);
00467 __os_free(dbenv, real_name);
00468 if (ret != 0)
00469 goto err2;
00470 } else if ((p = __db_rpath(real_name)) != NULL) {
00471 ret = __os_strdup(dbenv, p + 1, &array[last]);
00472 __os_free(dbenv, real_name);
00473 if (ret != 0)
00474 goto err2;
00475 } else
00476 array[last] = real_name;
00477 ++last;
00478 }
00479
00480
00481 array[last] = NULL;
00482
00483
00484 if ((ret = __usermem(dbenv, &array)) != 0)
00485 goto err1;
00486
00487 *listp = array;
00488 return (0);
00489
00490 err2:
00491
00492
00493
00494
00495 if (array != NULL)
00496 for (; nxt < n; ++nxt)
00497 __os_free(dbenv, array[nxt]);
00498
00499
00500 err1: if (array != NULL) {
00501 for (arrayp = array; *arrayp != NULL; ++arrayp)
00502 __os_free(dbenv, *arrayp);
00503 __os_free(dbenv, array);
00504 }
00505 return (ret);
00506 }
00507
00508
00509
00510
00511
00512 static int
00513 __absname(dbenv, pref, name, newnamep)
00514 DB_ENV *dbenv;
00515 char *pref, *name, **newnamep;
00516 {
00517 size_t l_pref, l_name;
00518 int isabspath, ret;
00519 char *newname;
00520
00521 l_name = strlen(name);
00522 isabspath = __os_abspath(name);
00523 l_pref = isabspath ? 0 : strlen(pref);
00524
00525
00526 if ((ret = __os_malloc(dbenv,
00527 l_pref + l_name + 2, &newname)) != 0)
00528 return (ret);
00529 *newnamep = newname;
00530
00531
00532 if (!isabspath) {
00533 memcpy(newname, pref, l_pref);
00534 if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL)
00535 newname[l_pref++] = PATH_SEPARATOR[0];
00536 }
00537 memcpy(newname + l_pref, name, l_name + 1);
00538
00539 return (0);
00540 }
00541
00542
00543
00544
00545
00546
00547 static int
00548 __usermem(dbenv, listp)
00549 DB_ENV *dbenv;
00550 char ***listp;
00551 {
00552 size_t len;
00553 int ret;
00554 char **array, **arrayp, **orig, *strp;
00555
00556
00557 for (len = 0, orig = *listp; *orig != NULL; ++orig)
00558 len += sizeof(char *) + strlen(*orig) + 1;
00559 len += sizeof(char *);
00560
00561
00562 if ((ret = __os_umalloc(dbenv, len, &array)) != 0)
00563 return (ret);
00564
00565 strp = (char *)(array + (orig - *listp) + 1);
00566
00567
00568 for (orig = *listp, arrayp = array; *orig != NULL; ++orig, ++arrayp) {
00569 len = strlen(*orig);
00570 memcpy(strp, *orig, len + 1);
00571 *arrayp = strp;
00572 strp += len + 1;
00573
00574 __os_free(dbenv, *orig);
00575 }
00576
00577
00578 *arrayp = NULL;
00579
00580 __os_free(dbenv, *listp);
00581 *listp = array;
00582
00583 return (0);
00584 }
00585
00586 static int
00587 __cmpfunc(p1, p2)
00588 const void *p1, *p2;
00589 {
00590 return (strcmp(*((char * const *)p1), *((char * const *)p2)));
00591 }