00001
00002
00003
00004
00005
00006
00007 #include "config.h"
00008
00009 #ifndef lint
00010 static const char revid[] = "$Id: log__get_8c-source.html,v 1.1 2008/06/08 10:20:23 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 #include <unistd.h>
00019 #endif
00020
00021 #ifdef HAVE_RPC
00022 #include "db_server.h"
00023 #endif
00024
00025 #include "db_int.h"
00026 #include "db_page.h"
00027 #include "log.h"
00028 #include "hash.h"
00029
00030 #ifdef HAVE_RPC
00031 #include "gen_client_ext.h"
00032 #include "rpc_client_ext.h"
00033 #endif
00034
00035
00036
00037
00038
00039 int
00040 CDB_log_get(dbenv, alsn, dbt, flags)
00041 DB_ENV *dbenv;
00042 DB_LSN *alsn;
00043 DBT *dbt;
00044 u_int32_t flags;
00045 {
00046 DB_LOG *dblp;
00047 DB_LSN saved_lsn;
00048 int ret;
00049
00050 #ifdef HAVE_RPC
00051 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00052 return (__dbcl_log_get(dbenv, alsn, dbt, flags));
00053 #endif
00054
00055 PANIC_CHECK(dbenv);
00056 ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
00057
00058
00059 if (flags != DB_CHECKPOINT && flags != DB_CURRENT &&
00060 flags != DB_FIRST && flags != DB_LAST &&
00061 flags != DB_NEXT && flags != DB_PREV && flags != DB_SET)
00062 return (CDB___db_ferr(dbenv, "CDB_log_get", 1));
00063
00064 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00065 if (flags == DB_NEXT || flags == DB_PREV || flags == DB_CURRENT)
00066 return (CDB___db_ferr(dbenv, "CDB_log_get", 1));
00067 if (!F_ISSET(dbt,
00068 DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM))
00069 return (CDB___db_ferr(dbenv, "threaded data", 1));
00070 }
00071
00072 dblp = dbenv->lg_handle;
00073 R_LOCK(dbenv, &dblp->reginfo);
00074
00075
00076
00077
00078
00079
00080 saved_lsn = *alsn;
00081 if ((ret = CDB___log_get(dblp,
00082 alsn, dbt, flags, 0)) == 0 && alsn->offset == 0) {
00083 switch (flags) {
00084 case DB_FIRST:
00085 flags = DB_NEXT;
00086 break;
00087 case DB_LAST:
00088 flags = DB_PREV;
00089 break;
00090 }
00091 if (F_ISSET(dbt, DB_DBT_MALLOC)) {
00092 CDB___os_free(dbt->data, dbt->size);
00093 dbt->data = NULL;
00094 }
00095 ret = CDB___log_get(dblp, alsn, dbt, flags, 0);
00096 }
00097 if (ret != 0)
00098 *alsn = saved_lsn;
00099
00100 R_UNLOCK(dbenv, &dblp->reginfo);
00101
00102 return (ret);
00103 }
00104
00105
00106
00107
00108
00109
00110
00111 int
00112 CDB___log_get(dblp, alsn, dbt, flags, silent)
00113 DB_LOG *dblp;
00114 DB_LSN *alsn;
00115 DBT *dbt;
00116 u_int32_t flags;
00117 int silent;
00118 {
00119 DB_ENV *dbenv;
00120 DB_LSN nlsn;
00121 HDR hdr;
00122 LOG *lp;
00123 size_t len;
00124 size_t nr;
00125 int cnt, ret;
00126 char *np, *tbuf;
00127 const char *fail;
00128 void *shortp, *readp;
00129 u_int32_t offset;
00130 u_int8_t *p;
00131
00132 lp = dblp->reginfo.primary;
00133 fail = np = tbuf = NULL;
00134 dbenv = dblp->dbenv;
00135
00136 nlsn = dblp->c_lsn;
00137 switch (flags) {
00138 case DB_CHECKPOINT:
00139 nlsn = lp->chkpt_lsn;
00140 if (IS_ZERO_LSN(nlsn)) {
00141
00142 ret = ENOENT;
00143 goto err2;
00144 }
00145 break;
00146 case DB_NEXT:
00147 if (!IS_ZERO_LSN(nlsn)) {
00148
00149 nlsn.offset += dblp->c_len;
00150 break;
00151 }
00152
00153 case DB_FIRST:
00154
00155 if ((ret = CDB___log_find(dblp, 1, &cnt)) != 0)
00156 goto err2;
00157
00158
00159
00160
00161
00162
00163 if (cnt == 0)
00164 cnt = 1;
00165
00166 nlsn.file = cnt;
00167 nlsn.offset = 0;
00168 break;
00169 case DB_CURRENT:
00170 break;
00171 case DB_PREV:
00172 if (!IS_ZERO_LSN(nlsn)) {
00173
00174 if (nlsn.offset == 0) {
00175 if (nlsn.file == 1 ||
00176 CDB___log_valid(dblp, nlsn.file - 1, 0) != 0)
00177 return (DB_NOTFOUND);
00178
00179 --nlsn.file;
00180 nlsn.offset = dblp->c_off;
00181 } else
00182 nlsn.offset = dblp->c_off;
00183 break;
00184 }
00185
00186 case DB_LAST:
00187 nlsn.file = lp->lsn.file;
00188 nlsn.offset = lp->lsn.offset - lp->len;
00189 break;
00190 case DB_SET:
00191 nlsn = *alsn;
00192 break;
00193 }
00194
00195 if (0) {
00196 next_file: ++nlsn.file;
00197 nlsn.offset = 0;
00198 }
00199
00200
00201 if (nlsn.file > lp->lsn.file ||
00202 (nlsn.file == lp->lsn.file && nlsn.offset >= lp->lsn.offset))
00203 return (DB_NOTFOUND);
00204
00205
00206 if (dblp->c_lsn.file != nlsn.file &&
00207 F_ISSET(&dblp->c_fh, DB_FH_VALID)) {
00208 (void)CDB___os_closehandle(&dblp->c_fh);
00209 }
00210
00211
00212 if (nlsn.file == lp->lsn.file && nlsn.offset >= lp->w_off) {
00213
00214 p = dblp->bufp + (nlsn.offset - lp->w_off);
00215 memcpy(&hdr, p, sizeof(HDR));
00216
00217
00218 len = hdr.len - sizeof(HDR);
00219 if ((ret = CDB___db_retcopy(NULL, dbt, p + sizeof(HDR),
00220 len, &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
00221 goto alloc_err;
00222 goto cksum;
00223 }
00224
00225 shortp = NULL;
00226
00227
00228 if (!F_ISSET(&dblp->c_fh, DB_FH_VALID)) {
00229 if ((ret = CDB___log_name(dblp, nlsn.file,
00230 &np, &dblp->c_fh, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
00231 fail = np;
00232 goto err1;
00233 }
00234 CDB___os_freestr(np);
00235 np = NULL;
00236 }
00237
00238
00239 if (nlsn.file == dblp->r_file && nlsn.offset > dblp->r_off
00240 && nlsn.offset + sizeof(HDR) < dblp->r_off + dblp->r_size)
00241 goto got_header;
00242
00243
00244
00245
00246
00247
00248
00249 readp = &hdr;
00250 offset = nlsn.offset;
00251 if (nlsn.file == lp->lsn.file && offset + sizeof(HDR) > lp->w_off)
00252 nr = lp->w_off - offset;
00253 else if (dblp->readbufp == NULL)
00254 nr = sizeof(HDR);
00255 else {
00256 nr = lp->buffer_size;
00257 readp = dblp->readbufp;
00258 dblp->r_file = nlsn.file;
00259
00260 if (flags == DB_PREV || flags == DB_LAST) {
00261 if (offset <= lp->buffer_size/2)
00262 offset = 0;
00263 else
00264 offset = offset - lp->buffer_size/2;
00265 }
00266 if (nlsn.file == lp->lsn.file && offset + nr > lp->lsn.offset)
00267 nr = lp->lsn.offset - offset;
00268 dblp->r_off = offset;
00269 }
00270
00271 if ((ret = CDB___os_seek(dblp->dbenv,
00272 &dblp->c_fh, 0, 0, offset, 0, DB_OS_SEEK_SET)) != 0) {
00273 fail = "seek";
00274 goto err1;
00275 }
00276 if ((ret = CDB___os_read(dblp->dbenv, &dblp->c_fh, readp, nr, &nr)) != 0) {
00277 fail = "read";
00278 goto err1;
00279 }
00280 if (nr < sizeof(HDR)) {
00281
00282 if (nr == 0) {
00283 if (flags != DB_NEXT || nlsn.file == lp->lsn.file)
00284 goto corrupt;
00285 goto next_file;
00286 }
00287
00288 if (dblp->readbufp != NULL)
00289 memcpy((u_int8_t *) &hdr, readp, nr);
00290
00291
00292
00293
00294
00295 if (lp->b_off < sizeof(HDR) - nr)
00296 goto corrupt;
00297
00298
00299 memcpy((u_int8_t *)&hdr + nr, dblp->bufp, sizeof(HDR) - nr);
00300
00301 if (hdr.len == 0)
00302 goto next_file;
00303
00304 shortp = dblp->bufp + (sizeof(HDR) - nr);
00305 }
00306
00307 else if (dblp->readbufp != NULL) {
00308 dblp->r_size = nr;
00309 got_header: memcpy((u_int8_t *)&hdr,
00310 dblp->readbufp + (nlsn.offset - dblp->r_off), sizeof(HDR));
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320 if (hdr.len == 0)
00321 goto next_file;
00322 if (hdr.len <= sizeof(HDR) || hdr.len > lp->persist.lg_max)
00323 goto corrupt;
00324 len = hdr.len - sizeof(HDR);
00325
00326
00327 if (shortp != NULL) {
00328 if (lp->b_off < ((u_int8_t *)shortp - dblp->bufp) + len)
00329 goto corrupt;
00330 if ((ret = CDB___db_retcopy(NULL, dbt, shortp, len,
00331 &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
00332 goto alloc_err;
00333 goto cksum;
00334 }
00335
00336 if (dblp->readbufp != NULL) {
00337 if (nlsn.offset + hdr.len < dblp->r_off + dblp->r_size) {
00338 if ((ret = CDB___db_retcopy(NULL, dbt, dblp->readbufp +
00339 (nlsn.offset - dblp->r_off) + sizeof(HDR),
00340 len, &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
00341 goto alloc_err;
00342 goto cksum;
00343 } else if ((ret = CDB___os_seek(dblp->dbenv, &dblp->c_fh, 0,
00344 0, nlsn.offset + sizeof(HDR), 0, DB_OS_SEEK_SET)) != 0) {
00345 fail = "seek";
00346 goto err1;
00347 }
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357 if ((ret = CDB___os_malloc(dbenv, len, NULL, &tbuf)) != 0)
00358 goto err1;
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 if (nlsn.file == lp->lsn.file &&
00371 nlsn.offset + sizeof(HDR) + len > lp->w_off)
00372 nr = lp->w_off - (nlsn.offset + sizeof(HDR));
00373 else
00374 nr = len;
00375 if ((ret = CDB___os_read(dblp->dbenv, &dblp->c_fh, tbuf, nr, &nr)) != 0) {
00376 fail = "read";
00377 goto err1;
00378 }
00379 if (len - nr > lp->buffer_size)
00380 goto corrupt;
00381 if (nr != len) {
00382 if (lp->b_off < len - nr)
00383 goto corrupt;
00384
00385
00386 memcpy((u_int8_t *)tbuf + nr, dblp->bufp, len - nr);
00387 }
00388
00389
00390 if ((ret = CDB___db_retcopy(NULL, dbt, tbuf, len,
00391 &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
00392 goto alloc_err;
00393 CDB___os_free(tbuf, 0);
00394 tbuf = NULL;
00395
00396 cksum: if (hdr.cksum != CDB___ham_func4(dbt->data, dbt->size)) {
00397 if (!silent)
00398 CDB___db_err(dbenv, "CDB_log_get: checksum mismatch");
00399 goto corrupt;
00400 }
00401
00402
00403 dblp->c_off = hdr.prev;
00404 dblp->c_len = hdr.len;
00405 dblp->c_lsn = *alsn = nlsn;
00406
00407 return (0);
00408
00409 corrupt:
00410
00411
00412
00413
00414 ret = EIO;
00415 fail = "read";
00416
00417 err1: if (!silent) {
00418 if (fail == NULL)
00419 CDB___db_err(dbenv, "CDB_log_get: %s", CDB_db_strerror(ret));
00420 else
00421 CDB___db_err(dbenv,
00422 "CDB_log_get: %s: %s", fail, CDB_db_strerror(ret));
00423 }
00424
00425 if (0) {
00426 alloc_err: if (!silent)
00427 CDB___db_err(dbenv,
00428 "Allocation failed: %lu", (u_long)len);
00429 }
00430
00431 err2: if (np != NULL)
00432 CDB___os_freestr(np);
00433 if (tbuf != NULL)
00434 CDB___os_free(tbuf, 0);
00435 return (ret);
00436 }