00001
00002
00003
00004
00005
00006
00007
00008 #include "config.h"
00009
00010 #ifndef lint
00011 static const char revid[] = "$Id: log__archive_8c-source.html,v 1.1 2008/06/08 10:20:14 sebdiaz Exp $";
00012 #endif
00013
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016
00017 #include <errno.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <unistd.h>
00021 #endif
00022
00023 #ifdef HAVE_RPC
00024 #include "db_server.h"
00025 #endif
00026
00027 #include "db_int.h"
00028 #include "db_dispatch.h"
00029 #include "log.h"
00030
00031 #ifdef HAVE_RPC
00032 #include "gen_client_ext.h"
00033 #include "rpc_client_ext.h"
00034 #endif
00035
00036 static int __absname __P((DB_ENV *, char *, char *, char **));
00037 static int __build_data __P((DB_ENV *, char *, char ***, void *(*)(size_t)));
00038 static int __cmpfunc __P((const void *, const void *));
00039 static int __usermem __P((DB_ENV *, char ***, void *(*)(size_t)));
00040
00041
00042
00043
00044
00045 int
00046 CDB_log_archive(dbenv, listp, flags, db_malloc)
00047 DB_ENV *dbenv;
00048 char ***listp;
00049 u_int32_t flags;
00050 void *(*db_malloc) __P((size_t));
00051 {
00052 DBT rec;
00053 DB_LOG *dblp;
00054 DB_LSN stable_lsn;
00055 u_int32_t fnum;
00056 int array_size, n, ret;
00057 char **array, **arrayp, *name, *p, *pref, buf[MAXPATHLEN];
00058
00059 #ifdef HAVE_RPC
00060 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00061 return (__dbcl_log_archive(dbenv, listp, flags, db_malloc));
00062 #endif
00063
00064 PANIC_CHECK(dbenv);
00065 ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
00066
00067 name = NULL;
00068 dblp = dbenv->lg_handle;
00069 COMPQUIET(fnum, 0);
00070
00071 #define OKFLAGS (DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG)
00072 if (flags != 0) {
00073 if ((ret =
00074 CDB___db_fchk(dbenv, "CDB_log_archive", flags, OKFLAGS)) != 0)
00075 return (ret);
00076 if ((ret =
00077 CDB___db_fcchk(dbenv,
00078 "CDB_log_archive", flags, DB_ARCH_DATA, DB_ARCH_LOG)) != 0)
00079 return (ret);
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 if (LF_ISSET(DB_ARCH_ABS)) {
00092 CDB___os_set_errno(0);
00093 if ((pref = getcwd(buf, sizeof(buf))) == NULL) {
00094 if (CDB___os_get_errno() == 0)
00095 CDB___os_set_errno(ENOMEM);
00096 return (CDB___os_get_errno());
00097 }
00098 } else
00099 pref = NULL;
00100
00101 switch (LF_ISSET(~DB_ARCH_ABS)) {
00102 case DB_ARCH_DATA:
00103 return (__build_data(dbenv, pref, listp, db_malloc));
00104 case DB_ARCH_LOG:
00105 memset(&rec, 0, sizeof(rec));
00106 if (F_ISSET(dbenv, DB_ENV_THREAD))
00107 F_SET(&rec, DB_DBT_MALLOC);
00108 if ((ret = CDB_log_get(dbenv, &stable_lsn, &rec, DB_LAST)) != 0)
00109 return (ret);
00110 if (F_ISSET(dbenv, DB_ENV_THREAD))
00111 CDB___os_free(rec.data, rec.size);
00112 fnum = stable_lsn.file;
00113 break;
00114 case 0:
00115 if ((ret = CDB___log_findckp(dbenv, &stable_lsn)) != 0) {
00116
00117
00118
00119
00120
00121 if (ret != DB_NOTFOUND)
00122 return (ret);
00123 *listp = NULL;
00124 return (0);
00125 }
00126
00127 fnum = stable_lsn.file - 1;
00128 break;
00129 }
00130
00131 #define LIST_INCREMENT 64
00132
00133 array_size = 10;
00134 if ((ret = CDB___os_malloc(dbenv,
00135 sizeof(char *) * array_size, NULL, &array)) != 0)
00136 return (ret);
00137 array[0] = NULL;
00138
00139
00140 for (n = 0; fnum > 0; --fnum) {
00141 if ((ret = CDB___log_name(dblp, fnum, &name, NULL, 0)) != 0)
00142 goto err;
00143 if (CDB___os_exists(name, NULL) != 0) {
00144 if (LF_ISSET(DB_ARCH_LOG) && fnum == stable_lsn.file)
00145 continue;
00146 CDB___os_freestr(name);
00147 name = NULL;
00148 break;
00149 }
00150
00151 if (n >= array_size - 1) {
00152 array_size += LIST_INCREMENT;
00153 if ((ret = CDB___os_realloc(dbenv,
00154 sizeof(char *) * array_size, NULL, &array)) != 0)
00155 goto err;
00156 }
00157
00158 if (LF_ISSET(DB_ARCH_ABS)) {
00159 if ((ret = __absname(dbenv,
00160 pref, name, &array[n])) != 0)
00161 goto err;
00162 CDB___os_freestr(name);
00163 } else if ((p = CDB___db_rpath(name)) != NULL) {
00164 if ((ret = CDB___os_strdup(dbenv, p + 1, &array[n])) != 0)
00165 goto err;
00166 CDB___os_freestr(name);
00167 } else
00168 array[n] = name;
00169
00170 name = NULL;
00171 array[++n] = NULL;
00172 }
00173
00174
00175 if (n == 0) {
00176 *listp = NULL;
00177 ret = 0;
00178 goto err;
00179 }
00180
00181
00182 qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
00183
00184
00185 if ((ret = __usermem(dbenv, &array, db_malloc)) != 0)
00186 goto err;
00187
00188 *listp = array;
00189 return (0);
00190
00191 err: if (array != NULL) {
00192 for (arrayp = array; *arrayp != NULL; ++arrayp)
00193 CDB___os_freestr(*arrayp);
00194 CDB___os_free(array, sizeof(char *) * array_size);
00195 }
00196 if (name != NULL)
00197 CDB___os_freestr(name);
00198 return (ret);
00199 }
00200
00201
00202
00203
00204
00205 static int
00206 __build_data(dbenv, pref, listp, db_malloc)
00207 DB_ENV *dbenv;
00208 char *pref, ***listp;
00209 void *(*db_malloc) __P((size_t));
00210 {
00211 DBT rec;
00212 DB_LSN lsn;
00213 __log_register_args *argp;
00214 u_int32_t rectype;
00215 int array_size, last, n, nxt, ret;
00216 char **array, **arrayp, *p, *real_name;
00217
00218
00219 array_size = 10;
00220 if ((ret = CDB___os_malloc(dbenv,
00221 sizeof(char *) * array_size, NULL, &array)) != 0)
00222 return (ret);
00223 array[0] = NULL;
00224
00225 memset(&rec, 0, sizeof(rec));
00226 if (F_ISSET(dbenv, DB_ENV_THREAD))
00227 F_SET(&rec, DB_DBT_MALLOC);
00228 for (n = 0, ret = CDB_log_get(dbenv, &lsn, &rec, DB_FIRST);
00229 ret == 0; ret = CDB_log_get(dbenv, &lsn, &rec, DB_NEXT)) {
00230 if (rec.size < sizeof(rectype)) {
00231 ret = EINVAL;
00232 CDB___db_err(dbenv, "CDB_log_archive: bad log record");
00233 goto lg_free;
00234 }
00235
00236 memcpy(&rectype, rec.data, sizeof(rectype));
00237 if (rectype != DB_log_register) {
00238 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00239 CDB___os_free(rec.data, rec.size);
00240 rec.data = NULL;
00241 }
00242 continue;
00243 }
00244 if ((ret = CDB___log_register_read(dbenv, rec.data, &argp)) != 0) {
00245 ret = EINVAL;
00246 CDB___db_err(dbenv,
00247 "CDB_log_archive: unable to read log record");
00248 goto lg_free;
00249 }
00250
00251 if (n >= array_size - 1) {
00252 array_size += LIST_INCREMENT;
00253 if ((ret = CDB___os_realloc(dbenv,
00254 sizeof(char *) * array_size, NULL, &array)) != 0)
00255 goto lg_free;
00256 }
00257
00258 if ((ret = CDB___os_strdup(dbenv,
00259 argp->name.data, &array[n])) != 0) {
00260 lg_free: if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
00261 CDB___os_free(rec.data, rec.size);
00262 goto err1;
00263 }
00264
00265 array[++n] = NULL;
00266 CDB___os_free(argp, 0);
00267
00268 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00269 CDB___os_free(rec.data, rec.size);
00270 rec.data = NULL;
00271 }
00272 }
00273
00274
00275 if (n == 0) {
00276 ret = 0;
00277 *listp = NULL;
00278 goto err1;
00279 }
00280
00281
00282 qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
00283
00284
00285
00286
00287
00288 for (last = nxt = 0; nxt < n;) {
00289
00290
00291
00292
00293
00294 if (last != nxt) {
00295 array[last] = array[nxt];
00296 array[nxt] = NULL;
00297 }
00298 for (++nxt; nxt < n &&
00299 strcmp(array[last], array[nxt]) == 0; ++nxt) {
00300 CDB___os_freestr(array[nxt]);
00301 array[nxt] = NULL;
00302 }
00303
00304
00305 if ((ret = CDB___db_appname(dbenv,
00306 DB_APP_DATA, NULL, array[last], 0, NULL, &real_name)) != 0)
00307 goto err2;
00308
00309
00310 if (CDB___os_exists(real_name, NULL) != 0) {
00311 CDB___os_freestr(real_name);
00312 CDB___os_freestr(array[last]);
00313 array[last] = NULL;
00314 continue;
00315 }
00316
00317
00318 CDB___os_freestr(array[last]);
00319 array[last] = NULL;
00320 if (pref != NULL) {
00321 ret = __absname(dbenv, pref, real_name, &array[last]);
00322 CDB___os_freestr(real_name);
00323 if (ret != 0)
00324 goto err2;
00325 } else if ((p = CDB___db_rpath(real_name)) != NULL) {
00326 ret = CDB___os_strdup(dbenv, p + 1, &array[last]);
00327 CDB___os_freestr(real_name);
00328 if (ret != 0)
00329 goto err2;
00330 } else
00331 array[last] = real_name;
00332 ++last;
00333 }
00334
00335
00336 array[last] = NULL;
00337
00338
00339 if ((ret = __usermem(dbenv, &array, db_malloc)) != 0)
00340 goto err1;
00341
00342 *listp = array;
00343 return (0);
00344
00345 err2:
00346
00347
00348
00349
00350 if (array != NULL)
00351 for (; nxt < n; ++nxt)
00352 CDB___os_freestr(array[nxt]);
00353
00354
00355 err1: if (array != NULL) {
00356 for (arrayp = array; *arrayp != NULL; ++arrayp)
00357 CDB___os_freestr(*arrayp);
00358 CDB___os_free(array, array_size * sizeof(char *));
00359 }
00360 return (ret);
00361 }
00362
00363
00364
00365
00366
00367 static int
00368 __absname(dbenv, pref, name, newnamep)
00369 DB_ENV *dbenv;
00370 char *pref, *name, **newnamep;
00371 {
00372 size_t l_pref, l_name;
00373 int isabspath, ret;
00374 char *newname;
00375
00376 l_name = strlen(name);
00377 isabspath = CDB___os_abspath(name);
00378 l_pref = isabspath ? 0 : strlen(pref);
00379
00380
00381 if ((ret = CDB___os_malloc(dbenv,
00382 l_pref + l_name + 2, NULL, &newname)) != 0)
00383 return (ret);
00384 *newnamep = newname;
00385
00386
00387 if (!isabspath) {
00388 memcpy(newname, pref, l_pref);
00389 if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL)
00390 newname[l_pref++] = PATH_SEPARATOR[0];
00391 }
00392 memcpy(newname + l_pref, name, l_name + 1);
00393
00394 return (0);
00395 }
00396
00397
00398
00399
00400
00401
00402 static int
00403 __usermem(dbenv, listp, db_malloc)
00404 DB_ENV *dbenv;
00405 char ***listp;
00406 void *(*db_malloc) __P((size_t));
00407 {
00408 size_t len;
00409 int ret;
00410 char **array, **arrayp, **orig, *strp;
00411
00412
00413 for (len = 0, orig = *listp; *orig != NULL; ++orig)
00414 len += sizeof(char *) + strlen(*orig) + 1;
00415 len += sizeof(char *);
00416
00417
00418 if ((ret = CDB___os_malloc(dbenv, len, db_malloc, &array)) != 0)
00419 return (ret);
00420
00421 strp = (char *)(array + (orig - *listp) + 1);
00422
00423
00424 for (orig = *listp, arrayp = array; *orig != NULL; ++orig, ++arrayp) {
00425 len = strlen(*orig);
00426 memcpy(strp, *orig, len + 1);
00427 *arrayp = strp;
00428 strp += len + 1;
00429
00430 CDB___os_freestr(*orig);
00431 }
00432
00433
00434 *arrayp = NULL;
00435
00436 CDB___os_free(*listp, 0);
00437 *listp = array;
00438
00439 return (0);
00440 }
00441
00442 static int
00443 __cmpfunc(p1, p2)
00444 const void *p1, *p2;
00445 {
00446 return (strcmp(*((char * const *)p1), *((char * const *)p2)));
00447 }