int Dbc::pget(Dbt* key, Dbt *pkey, Dbt *data, u_int32_t _flags) { int ret; DBC *dbc = this; ret = dbc->c_pget(dbc, key, pkey, data, _flags); /* Logic is the same as for Dbc::get - reusing macro. */ if (!DB_RETOK_DBCGET(ret)) { if (ret == ENOMEM && DB_OVERFLOWED_DBT(key)) DB_ERROR_DBT("Dbc::pget", key, ON_ERROR_UNKNOWN); else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data)) DB_ERROR_DBT("Dbc::pget", data, ON_ERROR_UNKNOWN); else DB_ERROR("Dbc::pget", ret, ON_ERROR_UNKNOWN); } return (ret); }
/* * DbRecord_search_field -- * Search, looking for a record by field. */ static int DbRecord_search_field(DbField *f, char *value, OPERATOR op) { #ifdef HAVE_WILDCARD_SUPPORT regex_t preq; #endif DBC *dbc; DbRecord record; DBT key, data, pkey; double value_double; u_long value_ulong; u_int32_t cursor_flags; int ret, t_ret; int (*cmp)(void *, void *, OPERATOR); void *faddr, *valuep; dbc = NULL; memset(&key, 0, sizeof(key)); memset(&pkey, 0, sizeof(pkey)); memset(&data, 0, sizeof(data)); /* * Initialize the comparison function, crack the value. Wild cards * are always strings, otherwise we follow the field type. */ if (op == WC || op == NWC) { #ifdef HAVE_WILDCARD_SUPPORT if (f->type != STRING) { dbenv->errx(dbenv, "wildcard operator only supported for string fields"); return (1); } if (regcomp(&preq, value, 0) != 0) { dbenv->errx(dbenv, "regcomp of pattern failed"); return (1); } valuep = &preq; cmp = field_cmp_re; #else dbenv->errx(dbenv, "wildcard operators not supported in this build"); return (1); #endif } else switch (f->type) { case DOUBLE: if (strtod_err(value, &value_double) != 0) return (1); cmp = field_cmp_double; valuep = &value_double; key.size = sizeof(double); break; case STRING: valuep = value; cmp = field_cmp_string; key.size = (u_int32_t)strlen(value); break; case UNSIGNED_LONG: if (strtoul_err(value, &value_ulong) != 0) return (1); cmp = field_cmp_ulong; valuep = &value_ulong; key.size = sizeof(u_long); break; default: case NOTSET: abort(); /* NOTREACHED */ } /* * Retrieve the first record that interests us. The range depends on * the operator: * * ~ beginning to end * != beginning to end * < beginning to first match * <= beginning to last match * = first match to last match * > record after last match to end * >= first match to end * * If we have a secondary, set a cursor in the secondary, else set the * cursor to the beginning of the primary. * * XXX * If the wildcard string has a leading non-magic character we should * be able to do a range search instead of a full-database search. * * Step through records to the first non-match or to the end of the * database, depending on the operation. If the comparison function * returns success for a key/data pair, print the pair. */ if (f->secondary == NULL || op == NEQ || op == WC || op == NWC) { if ((ret = db->cursor(db, NULL, &dbc, 0)) != 0) goto err; while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) { if ((ret = DbRecord_init(&key, &data, &record)) != 0) break; faddr = (u_int8_t *)&record + f->offset; if (cmp(faddr, valuep, op)) DbRecord_print(&record, NULL); else if (op == EQ || op == LT || op == LTEQ) break; } } else { if ((ret = f->secondary->cursor(f->secondary, NULL, &dbc, 0)) != 0) goto err; key.data = valuep; cursor_flags = op == LT || op == LTEQ ? DB_FIRST : DB_SET_RANGE; if ((ret = dbc->c_pget(dbc, &key, &pkey, &data, cursor_flags)) != 0) goto done; if (op == GT) { while ((ret = dbc->c_pget( dbc, &key, &pkey, &data, DB_NEXT)) == 0) { if ((ret = DbRecord_init(&pkey, &data, &record)) != 0) break; faddr = (u_int8_t *)&record + f->offset; if (cmp(faddr, valuep, op) != 0) break; } if (ret != 0) goto done; } do { if ((ret = DbRecord_init(&pkey, &data, &record)) != 0) break; faddr = (u_int8_t *)&record + f->offset; if (cmp(faddr, valuep, op)) DbRecord_print(&record, NULL); else if (op == EQ || op == LT || op == LTEQ) break; } while ((ret = dbc->c_pget(dbc, &key, &pkey, &data, DB_NEXT)) == 0); } done: if (ret == DB_NOTFOUND) ret = 0; err: if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0) ret = t_ret; #ifdef HAVE_WILDCARD_SUPPORT if (op == WC || op == NWC) regfree(&preq); #endif return (ret); }
enum jaldb_status jaldb_iterate_by_timestamp(jaldb_context *ctx, enum jaldb_rec_type type, const char *timestamp, jaldb_iter_cb cb, void *up) { enum jaldb_status ret = JALDB_E_INVAL; struct tm target_time, record_time; memset(&target_time, 0, sizeof(target_time)); memset(&record_time, 0, sizeof(record_time)); int target_ms = 0; int record_ms = 0; char *tmp_time = NULL; struct jaldb_record *rec = NULL; int byte_swap = 0; struct jaldb_record_dbs *rdbs = NULL; int db_ret = 0; DBT key; DBT pkey; DBT val; DBC *cursor = NULL; memset(&key, 0, sizeof(key)); memset(&pkey, 0, sizeof(pkey)); memset(&val, 0, sizeof(val)); key.flags = DB_DBT_REALLOC; val.flags = DB_DBT_REALLOC; time_t target_secs = 0; tmp_time = strptime(timestamp, "%Y-%m-%dT%H:%M:%S", &target_time); if (!tmp_time) { fprintf(stderr, "ERROR: Invalid time format specified.\n"); ret = JALDB_E_INVAL_TIMESTAMP; goto out; } if (!sscanf(tmp_time,".%d-%*d:%*d", &target_ms)) { fprintf(stderr, "ERROR: Invalid time format specified.\n"); ret = JALDB_E_INVAL_TIMESTAMP; goto out; } // Calculate the target time in secs once before we start looping target_secs = mktime(&target_time); if (!ctx || !cb) { ret = JALDB_E_UNINITIALIZED; goto out; } switch(type) { case JALDB_RTYPE_JOURNAL: rdbs = ctx->journal_dbs; break; case JALDB_RTYPE_AUDIT: rdbs = ctx->audit_dbs; break; case JALDB_RTYPE_LOG: rdbs = ctx->log_dbs; break; default: ret = JALDB_E_INVAL_RECORD_TYPE; goto out; } if (!rdbs) { ret = JALDB_E_UNINITIALIZED; goto out; } // Use the record creation time database db_ret = rdbs->timestamp_idx_db->get_byteswapped(rdbs->timestamp_idx_db, &byte_swap); if (0 != db_ret) { ret = JALDB_E_INVAL; goto out; } db_ret = rdbs->timestamp_idx_db->cursor(rdbs->timestamp_idx_db, NULL, &cursor, DB_DEGREE_2); if (0 != db_ret) { JALDB_DB_ERR(rdbs->timestamp_idx_db, db_ret); ret = JALDB_E_INVAL; goto out; } while(0 == db_ret) { db_ret = cursor->c_pget(cursor, &key, &pkey, &val, DB_NEXT); if (0 != db_ret) { if (DB_NOTFOUND == db_ret) { ret = JALDB_OK; } else { JALDB_DB_ERR(rdbs->timestamp_idx_db, db_ret); ret = JALDB_E_INVAL; } goto out; } // mktime() like to set things like timezone to system timezone - need to clean out the tm struct before each call memset(&record_time, 0, sizeof(record_time)); tmp_time = strptime((char*) key.data, "%Y-%m-%dT%H:%M:%S", &record_time); if (!tmp_time) { fprintf(stderr, "ERROR: Cannot get strptime from record\n"); ret = JALDB_E_INVAL_TIMESTAMP; goto out; } if (!sscanf(tmp_time,".%d-%*d:%*d", &record_ms)) { ret = JALDB_E_INVAL_TIMESTAMP; goto out; } double delta = difftime(target_secs,mktime(&record_time)); if (delta < 0) { // record_time is > target_time, so break out goto out; } if (delta == 0) { if (record_ms > target_ms) { goto out; } } ret = jaldb_deserialize_record(byte_swap, (uint8_t*) val.data, val.size, &rec); if (ret != JALDB_OK) { goto out; } switch (cb((char*) pkey.data, rec, up)) { case JALDB_ITER_CONT: break; case JALDB_ITER_REM: // Need to close cursor before removing record cursor->c_close(cursor); cursor = NULL; ret = jaldb_remove_record(ctx, type, (char*) pkey.data); if (JALDB_OK == ret) { ret = jaldb_remove_segments_from_disk(ctx, rec); } if (ret != JALDB_OK) { // something went wrong... goto out; } db_ret = rdbs->timestamp_idx_db->cursor(rdbs->timestamp_idx_db, NULL, &cursor, DB_DEGREE_2); if (0 != db_ret) { JALDB_DB_ERR(rdbs->timestamp_idx_db, db_ret); ret = JALDB_E_INVAL; goto out; } break; default: goto out; } jaldb_destroy_record(&rec); } out: if (cursor) { cursor->c_close(cursor); } jaldb_destroy_record(&rec); free(key.data); free(val.data); return ret; }
// }}} // {{{ dumpall: Dump all db key metadata static int dumpall (bool bytime) { adb_master_metadata_t mmd; bzero (&mmd, sizeof (mmd)); DBT begin_time, key, data; u_int64_t totalsz = 0; unsigned keys = 0; int r = 0; DBC *cursor; if (bytime) r = byexpiredb->cursor (byexpiredb, NULL, &cursor, 0); else r = metadatadb->cursor (metadatadb, NULL, &cursor, 0); if (r) { warn << "cursor error: " << r << " " << db_strerror (r) << "\n"; return r; } for (int i = 0; ; i++) { bzero (&begin_time, sizeof (begin_time)); bzero (&key, sizeof (key)); bzero (&data, sizeof (data)); if (bytime) r = cursor->c_pget (cursor, &begin_time, &key, &data, DB_NEXT); else r = cursor->c_get (cursor, &key, &data, DB_NEXT); if (r == DB_NOTFOUND) { aout << "EOF.\n"; r = 0; break; } else if (r) { warn << "error: " << r << " " << db_strerror (r) << "\n"; break; } if (key.size != sha1::hashsize) { buf2xdr (mmd, data.data, data.size); continue; } chordID k; mpz_set_rawmag_be (&k, static_cast<char *> (key.data), key.size); adb_metadata_t md; buf2xdr (md, data.data, data.size); aout << "key[" << i << "] " << k << " " << md.size << " " << md.expiration << "\n"; keys++; totalsz += md.size; aout->flush (); } cursor->c_close (cursor); aout << "total keys: " << keys << "\n"; aout << "total bytes: " << totalsz << "\n"; if (totalsz != mmd.size) warn << "Master metadata total bytes error: " << mmd.size << "\n"; return r; }