#include <stdio.h>
#include <malloc.h>
#include <strings.h>
#include <string.h>
#include <sys/param.h>
#include "db_headers.h"
#include "db.h"
#include "db_mindex.h"
#include "db_pickle.h"
#include "nisdb_mt.h"
#include "nisdb_ldap.h"
#include "ldap_nisdbquery.h"
#include "ldap_map.h"
#include "ldap_ruleval.h"
#include "ldap_scheme.h"
#include "ldap_parse.h"
#include "nis_hashitem.h"
db_mindex::db_mindex(db_scheme *how, char *tablePath) : rversion()
{
noWriteThrough.flag = 0;
noLDAPquery.flag = 0;
initialLoad.flag = 0;
objPath.ptr = NULL;
init(how);
if (tablePath != NULL)
configure(tablePath);
}
db_mindex::db_mindex() : rversion()
{
scheme = NULL;
table = NULL;
indices.indices_len = 0;
indices.indices_val = NULL;
noWriteThrough.flag = 0;
noLDAPquery.flag = 0;
initialLoad.flag = 0;
objPath.ptr = NULL;
INITRW(mindex);
}
db_mindex::~db_mindex()
{
reset();
DESTROYRW(mindex);
}
void
db_mindex::init(db_scheme * how)
{
scheme = new db_scheme(how);
if (scheme == NULL)
FATAL("db_mindex::init: could not allocate space for scheme",
DB_MEMORY_LIMIT);
if (scheme->numkeys() == 0) {
WARNING("db_mindex::init: empty scheme encountered");
}
indices.indices_len = how->numkeys();
db_key_desc * keys = how->keyloc();
int i;
indices.indices_val = new db_index[indices.indices_len];
if (indices.indices_val == NULL) {
delete scheme;
indices.indices_len = 0;
scheme = NULL;
FATAL("db_mindex::init: could not allocate space for indices",
DB_MEMORY_LIMIT);
}
for (i = 0; i < indices.indices_len; i++) {
indices.indices_val[i].init(&(keys[i]));
}
table = new db_table();
if (table == NULL) {
delete scheme;
scheme = NULL;
delete indices.indices_val;
indices.indices_val = NULL;
indices.indices_len = 0;
FATAL("db_mindex::init: could not allocate space for table",
DB_MEMORY_LIMIT);
}
rversion.zero();
INITRW(mindex);
objPath.ptr = NULL;
}
void
db_mindex::reset_tables()
{
int i;
WRITELOCKV(this, "w db_mindex::reset_tables");
if (indices.indices_val != NULL) {
for (i = 0; i < indices.indices_len; i++) {
indices.indices_val[i].reset();
}
}
if (table) table->reset();
WRITEUNLOCKV(this, "wu db_mindex::reset_tables");
}
db_index_entry_p
db_mindex::satisfy_query(db_query *q, long *count, bool_t *valid) {
return (satisfy_query(q, count, valid, FALSE));
}
db_index_entry_p
db_mindex::satisfy_query(db_query *q, long *count, bool_t *valid,
bool_t fromLDAP) {
db_index_entry_p ret;
bool_t validRequest;
int queryRes;
if (valid == NULL)
valid = &validRequest;
*count = 0;
*valid = FALSE;
READLOCK(this, NULL, "r db_mindex::satisfy_query");
fromLDAP = (fromLDAP && !noLDAPquery.flag &&
(table->mapping.fromLDAP ||
table->mapping.objType != NIS_TABLE_OBJ));
if (fromLDAP && table->mapping.matchFetch == mat_always) {
int lockcode = 0;
READLOCKNR(table, lockcode,
"r db_mindex::satisfy_query table");
if (lockcode != 0) {
READUNLOCK(this, NULL, "ru db_mindex::satisfy_query");
return (NULL);
}
queryRes = queryLDAP(q, 0, 1);
READUNLOCKNR(table, lockcode,
"ru db_mindex::satisfy_query table");
if (lockcode != 0) {
READUNLOCK(this, NULL, "ru db_mindex::satisfy_query");
return (NULL);
}
if (queryRes != LDAP_SUCCESS) {
READUNLOCK(this, NULL, "ru db_mindex::satisfy_query");
return (NULL);
}
}
ret = satisfy_query_dbonly(q, count, fromLDAP ? TRUE : FALSE, valid);
if (ret != NULL || !fromLDAP) {
READUNLOCK(this, NULL, "ru db_mindex::satisfy_query");
return (ret);
} else if (ret == NULL && !(*valid)) {
READUNLOCK(this, NULL, "ru db_mindex::satisfy_query");
return (NULL);
}
if (table->mapping.matchFetch != mat_never) {
queryRes = queryLDAP(q, 0, 1);
} else {
queryRes = LDAP_SUCCESS;
}
if (queryRes == LDAP_SUCCESS) {
ret = satisfy_query_dbonly(q, count, TRUE, valid);
if (ret == NULL) {
ret = satisfy_query_dbonly(q, count, FALSE, valid);
}
} else {
ret = satisfy_query_dbonly(q, count, FALSE, valid);
}
READUNLOCK(this, NULL, "ru db_mindex::satisfy_query");
return (ret);
}
db_index_entry_p
db_mindex::satisfy_query_dbonly(db_query *q, long *count,
bool_t checkExpire, bool_t *valid)
{
db_index_entry_p oldres = NULL, newres;
int i, curr_ind;
long num_new, num_old = 0;
int limit = q->size();
db_qcomp * comps = q->queryloc();
if (valid) *valid = TRUE;
if (indices.indices_len != 0 && indices.indices_val == NULL) {
WARNING("db_mindex::satisfy_query: table has no indices");
if (valid) *valid = FALSE;
*count = 0;
return (NULL);
}
for (i = 0; i < limit; i++) {
if ((curr_ind = comps[i].which_index) < indices.indices_len) {
newres = indices.indices_val[curr_ind].lookup(
comps[i].index_value, &num_new,
table, checkExpire);
if (newres == NULL) {
*count = 0;
return (NULL);
}
if (oldres == NULL) {
oldres = newres;
num_old = num_new;
} else {
oldres = newres->join(num_new, num_old,
oldres, &num_old);
if (oldres == NULL) {
*count = 0;
return (NULL);
}
}
} else {
WARNING("db_mindex::satisfy_query: index out of range");
if (valid) *valid = FALSE;
*count = 0;
return (NULL);
}
}
*count = num_old;
return (oldres);
}
entry_object_p *
db_mindex::prepare_results(int count, db_index_entry_p res, db_status *statp)
{
READLOCK(this, NULL, "r db_mindex::prepare_results");
READLOCK2(table, NULL, "r table db_mindex::prepare_results", this);
entry_object_p * entries = new entry_object_p[count];
int i;
if (entries == NULL) {
READUNLOCK2(this, table, NULL, NULL,
"ru db_mindex::prepare_results: could not allocate space",
"ru table db_mindex::prepare_results: could not allocate space");
FATAL3("db_mindex::prepare_results: could not allocate space",
DB_MEMORY_LIMIT, NULL);
}
for (i = 0; i < count; i++) {
if (res == NULL) {
int j;
for (j = 0; j < i; j++)
free_entry(entries[j]);
syslog(LOG_ERR,
"db_mindex::prepare_results: incorrect count");
*statp = DB_INTERNAL_ERROR;
} else {
entries[i] =
new_entry(table->get_entry(res->getlocation()));
res = res->getnextresult();
}
}
READUNLOCK2(this, table, entries, entries,
"ru db_mindex::prepare_results",
"ru db_mindex::prepare_results");
return (entries);
}
db_query *
db_mindex::extract_index_values_from_record(entryp recnum)
{
db_query *ret;
ret = extract_index_values_from_object(table->get_entry(recnum));
return (ret);
}
db_query *
db_mindex::extract_index_values_from_object(entry_object_p obj)
{
READLOCK(this, NULL, "r db_mindex::extract_index_values_from_object");
if (scheme->numkeys() != indices.indices_len) {
syslog(LOG_ERR,
"number of keys (%d) does not equal number of indices (%d)",
scheme->numkeys(), indices.indices_len);
READUNLOCK(this, NULL,
"ru db_mindex::extract_index_values_from_object");
return (new db_query());
} else if (obj == NULL) {
READUNLOCK(this, NULL,
"ru db_mindex::extract_index_values_from_object");
return (NULL);
} else {
db_query* answer = new db_query(scheme, obj);
if (answer) {
READUNLOCK(this, NULL,
"ru db_mindex::extract_index_values_from_object");
return (answer);
} else {
FATAL3("db_mindex::extract: could not allocate space",
DB_MEMORY_LIMIT, NULL);
}
}
READUNLOCK(this, NULL,
"ru db_mindex::extract_index_values_from_object");
return (NULL);
}
db_status
db_mindex::first(entryp *where, entry_object ** answer)
{
db_status ret = DB_SUCCESS;
READLOCK(this, DB_LOCK_ERROR, "r db_mindex::first");
READLOCK2(table, DB_LOCK_ERROR, "r table db_mindex::first", this);
if (table->mapping.fromLDAP) {
struct timeval now;
(void) gettimeofday(&now, NULL);
if (now.tv_sec >= table->mapping.enumExpire) {
int queryRes = queryLDAP(0, 0, 1);
if (queryRes == LDAP_SUCCESS)
table->mapping.enumExpire = now.tv_sec +
table->mapping.ttl;
else {
READUNLOCK2(this, table,
DB_LOCK_ERROR, DB_LOCK_ERROR,
"ru db_mindex::first LDAP",
"ru table db_mindex::first LDAP");
return (DB_INTERNAL_ERROR);
}
}
}
entry_object_p ptr = table->first_entry(where);
if (ptr == NULL)
ret = DB_NOTFOUND;
else
*answer = new_entry(ptr);
READUNLOCK2(this, table, ret, ret,
"ru db_mindex::first", "ru table db_mindex::first");
return (ret);
}
db_status
db_mindex::next(entryp previous, entryp *where, entry_object **answer)
{
db_status ret = DB_SUCCESS;
READLOCK(this, DB_LOCK_ERROR, "r db_mindex::next");
READLOCK2(table, DB_LOCK_ERROR, "r db_mindex::next", this);
if (!(table->entry_exists_p(previous)))
ret = DB_NOTFOUND;
else {
entry_object * ptr = table->next_entry(previous, where);
if (ptr == NULL)
ret = DB_NOTFOUND;
else
*answer = new_entry(ptr);
}
READUNLOCK2(this, table, ret, ret,
"ru db_mindex::next", "ru table db_mindex::next");
return (ret);
}
static void
delete_result_list(db_next_index_desc* orig)
{
db_next_index_desc* curr, *save_next;
for (curr = orig; curr != NULL; 0) {
save_next = curr->next;
delete curr;
curr = save_next;
}
}
static db_next_index_desc *
copy_result_list(db_index_entry* orig)
{
db_next_index_desc *head = NULL, *curr;
db_index_entry *current;
for (current = orig; current != NULL;
current = current->getnextresult()) {
curr = new db_next_index_desc(current->getlocation(), head);
if (curr == NULL) {
FATAL3(
"db_mindex::copy_result_list: could not allocate space",
DB_MEMORY_LIMIT, NULL);
}
head = curr;
}
return (head);
}
db_status
db_mindex::reset_next(db_next_index_desc *orig)
{
if (orig == NULL)
return (DB_NOTFOUND);
delete_result_list(orig);
return (DB_SUCCESS);
}
db_status
db_mindex::first(db_query *q,
db_next_index_desc **where, entry_object ** answer)
{
READLOCK(this, DB_LOCK_ERROR, "r db_mindex::first");
READLOCK2(table, DB_LOCK_ERROR, "r table db_mindex::first", this);
long count;
bool_t valid_query;
db_status ret = DB_SUCCESS;
db_index_entry * rp = satisfy_query(q, &count, &valid_query, TRUE);
if (valid_query != TRUE)
ret = DB_BADQUERY;
else if (rp == NULL) {
*answer = NULL;
ret = DB_NOTFOUND;
} else {
*where = copy_result_list(rp);
entry_object_p ptr = table->get_entry((*where)->location);
if (ptr == NULL)
ret = DB_NOTFOUND;
else
*answer = new_entry(ptr);
}
READUNLOCK2(this, table, ret, ret,
"ru db_mindex::first", "ru table db_mindex::first");
return (ret);
}
db_status
db_mindex::next(db_next_index_desc *previous, db_next_index_desc **where,
entry_object **answer)
{
READLOCK(this, DB_LOCK_ERROR, "r db_mindex::next");
READLOCK2(table, DB_LOCK_ERROR, "r table db_mindex::next", this);
db_status ret = DB_SUCCESS;
if (previous == NULL)
ret = DB_NOTFOUND;
else {
*where = previous->next;
delete previous;
if (*where == NULL)
ret = DB_NOTFOUND;
else {
entry_object * ptr =
table->get_entry((*where)->location);
if (ptr == NULL)
ret = DB_NOTFOUND;
else {
*answer = new_entry(ptr);
ret = DB_SUCCESS;
}
}
}
READUNLOCK2(this, table, ret, ret,
"ru db_mindex::next", "ru table db_mindex::next");
return (ret);
}
db_status
db_mindex::lookup(db_query *q, long *count, entry_object_p **result)
{
bool_t valid_query;
db_index_entry * rp = satisfy_query(q, count, &valid_query, TRUE);
db_status stat = DB_SUCCESS;
if (valid_query != TRUE)
return (DB_BADQUERY);
if (rp == NULL) {
*result = NULL;
return (DB_NOTFOUND);
}
*result = prepare_results((int)*count, rp, &stat);
return (stat);
}
db_status
db_mindex::all(long *count, entry_object_p **result)
{
entry_object *ptr;
entryp where;
long how_many, i;
int lret = 0;
if (table == NULL) {
*result = NULL;
return (DB_NOTFOUND);
}
READLOCK(this, DB_LOCK_ERROR, "r db_mindex::all");
READLOCKNR(table, lret, "r table db_mindex::all");
if (lret != 0) {
READUNLOCK(this, DB_LOCK_ERROR, "ru db_mindex::all");
return (DB_LOCK_ERROR);
}
if (table->mapping.fromLDAP) {
struct timeval now;
(void) gettimeofday(&now, NULL);
if (now.tv_sec >= table->mapping.enumExpire) {
int queryRes = queryLDAP(0, 0, 1);
if (queryRes != LDAP_SUCCESS) {
READUNLOCKNR(table, lret,
"ru table db_mindex::all LDAP");
READUNLOCK(this, DB_LOCK_ERROR,
"ru db_mindex::all LDAP");
return (DB_INTERNAL_ERROR);
}
}
}
if ((how_many = table->fullness()) <= 0) {
*count = 0;
*result = NULL;
READUNLOCKNR(table, lret, "ru table db_mindex::all");
READUNLOCK(this, DB_NOTFOUND, "ru db_mindex::all");
return (DB_NOTFOUND);
}
entry_object_p * answer = new entry_object_p[how_many];
if (answer == NULL) {
READUNLOCKNR(table, lret, "ru table db_mindex::all");
READUNLOCK(this, DB_MEMORY_LIMIT, "ru db_mindex::all");
FATAL3("db_mindex::all: could not allocate space",
DB_MEMORY_LIMIT, DB_MEMORY_LIMIT);
}
*count = how_many;
ptr = table->first_entry(&where);
if (ptr != NULL)
answer[0] = new_entry(ptr);
else {
WARNING("db_mindex::all: null first entry found in all");
answer[0] = NULL;
}
for (i = 1; i < how_many; i++) {
ptr = table->next_entry(where, &where);
if (ptr != NULL)
answer[i] = new_entry(ptr);
else {
WARNING(
"db_mindex::all: null internal entry found in all");
answer[i] = NULL;
}
}
READUNLOCKNR(table, lret, "ru table db_mindex::all");
*result = answer;
READUNLOCK(this, DB_SUCCESS, "ru db_mindex::all");
return (DB_SUCCESS);
}
db_status
db_mindex::remove_aux(entryp recloc)
{
int i, curr_ind;
db_status res = DB_SUCCESS;
WRITELOCK(this, DB_LOCK_ERROR, "w db_mindex::remove_aux");
db_query * cq = extract_index_values_from_record(recloc);
if (cq == NULL) {
WRITEUNLOCK(this, DB_MEMORY_LIMIT, "wu db_mindex::remove_aux");
FATAL3("db_mindex::remove_aux: could not allocate space",
DB_MEMORY_LIMIT, DB_MEMORY_LIMIT);
}
if (cq->size() != indices.indices_len) {
delete cq;
syslog(LOG_ERR,
"db_mindex::remove_aux: record contains wrong number of indices");
WRITEUNLOCK(this, DB_INTERNAL_ERROR,
"wu db_mindex::remove_aux");
return (DB_INTERNAL_ERROR);
}
if (!noWriteThrough.flag) {
nis_object *o = 0;
entry_object *e = table->get_entry(recloc);
int queryRes, doingModify;
if (saveOldObjForModify((entry_obj *)e, &doingModify) == 0)
res = DB_INTERNAL_ERROR;
if (res == DB_SUCCESS && !doingModify) {
if (e != 0 && e->en_type != 0 &&
strcmp(e->en_type, "IN_DIRECTORY") == 0)
o = unmakePseudoEntryObj(e, 0);
queryRes = removeLDAP(cq, o);
if (queryRes != LDAP_SUCCESS) {
if (table->mapping.storeErrorDisp == abandon)
res = DB_INTERNAL_ERROR;
}
if (o != 0)
nis_destroy_object(o);
}
}
if (res == DB_SUCCESS) {
db_qcomp * comps = cq->queryloc();
if (indices.indices_val != NULL) {
for (i = 0; i < indices.indices_len; i++) {
curr_ind = comps[i].which_index;
indices.indices_val[curr_ind].remove(
comps[i].index_value, recloc);
}
}
table->delete_entry(recloc);
}
delete cq;
WRITEUNLOCK(this, DB_SUCCESS, "wu db_mindex::remove_aux");
return (res);
}
db_status
db_mindex::remove(db_query *q)
{
long count = 0;
db_index_entry *rp;
db_status rstat;
bool_t valid_query;
WRITELOCK(this, DB_LOCK_ERROR, "w db_mindex::remove");
WRITELOCK2(table, DB_LOCK_ERROR, "w table db_mindex::remove", this);
if (q == NULL) {
if (table->mapping.toLDAP && !noWriteThrough.flag) {
int queryRes = removeLDAP(q, 0);
#ifdef NISDB_LDAP_DEBUG
if (queryRes != LDAP_SUCCESS)
abort();
#endif
}
if (table != NULL && table->getsize() > 0) {
reset_tables();
WRITEUNLOCK2(table, this, DB_SUCCESS, DB_SUCCESS,
"wu table db_mindex::remove",
"wu db_mindex::remove");
return (DB_SUCCESS);
} else {
WRITEUNLOCK2(table, this, DB_NOTFOUND, DB_NOTFOUND,
"wu table db_mindex::remove",
"wu db_mindex::remove");
return (DB_NOTFOUND);
}
}
rp = satisfy_query(q, &count, &valid_query, FALSE);
if (valid_query != TRUE) {
WRITEUNLOCK2(table, this, DB_BADQUERY, DB_BADQUERY,
"wu table db_mindex::remove", "wu db_mindex::remove");
return (DB_BADQUERY);
}
if (count == 0) {
WRITEUNLOCK2(table, this, DB_NOTFOUND, DB_NOTFOUND,
"wu table db_mindex::remove", "wu db_mindex::remove");
return (DB_NOTFOUND);
} else if (count == 1) {
db_status s;
s = remove_aux(rp->getlocation());
WRITEUNLOCK2(table, this, s, s,
"wu table db_mindex::remove", "wu db_mindex::remove");
return (s);
} else {
int i;
db_index_entry *next_entry;
for (i = 0; i < count; i++) {
if (rp == NULL) {
syslog(LOG_ERR,
"db_mindex::remove: incorrect number of indices");
WRITEUNLOCK2(table, this, DB_INTERNAL_ERROR,
DB_INTERNAL_ERROR,
"wu table db_mindex::remove",
"wu db_mindex::remove");
return (DB_INTERNAL_ERROR);
}
next_entry = rp->getnextresult();
rstat = remove_aux(rp->getlocation());
if (rstat != DB_SUCCESS) {
WRITEUNLOCK2(table, this, rstat, rstat,
"wu table db_mindex::remove",
"wu db_mindex::remove");
return (rstat);
}
rp = next_entry;
}
WRITEUNLOCK2(table, this, DB_SUCCESS, DB_SUCCESS,
"wu table db_mindex::remove", "wu db_mindex::remove");
return (DB_SUCCESS);
}
}
db_status
db_mindex::add(db_query *q, entry_object * obj)
{
long count = 0;
int i, curr_ind;
bool_t valid;
db_index_entry *rp = NULL;
db_status rstat;
const char *myself = "db_mindex::add";
WRITELOCK(this, DB_LOCK_ERROR, "w db_mindex::add");
WRITELOCK2(table, DB_LOCK_ERROR, "w table db_mindex::add", this);
if (q) {
rp = satisfy_query(q, &count, &valid, FALSE);
if (!valid) {
WRITEUNLOCK2(this, table, DB_LOCK_ERROR, DB_LOCK_ERROR,
"wu db_mindex::add",
"wu table db_mindex::add");
return (DB_BADQUERY);
}
}
if (count == 1) {
rstat = remove_aux(rp->getlocation());
if (rstat != DB_SUCCESS) {
WRITEUNLOCK2(this, table, rstat, rstat,
"wu db_mindex::add",
"wu table db_mindex::add");
return (rstat);
}
count = 0;
}
if (count == 0) {
entryp recloc = table->add_entry(obj, initialLoad.flag);
db_query *cq = extract_index_values_from_object(obj);
if (cq == NULL) {
table->delete_entry(recloc);
WRITEUNLOCK2(this, table,
DB_MEMORY_LIMIT, DB_MEMORY_LIMIT,
"wu db_mindex::add DB_MEMORY_LIMIT",
"wu table db_mindex::add DB_MEMORY_LIMIT");
FATAL3("db_mindex::add: could not allocate space for",
DB_MEMORY_LIMIT, DB_MEMORY_LIMIT);
}
if (cq ->size() != indices.indices_len) {
table->delete_entry(recloc);
delete cq;
syslog(LOG_ERR,
"db_mindex::add: record contains wrong number of indices");
WRITEUNLOCK2(this, table,
DB_INTERNAL_ERROR, DB_INTERNAL_ERROR,
"wu db_mindex::add DB_INTERNAL_ERROR",
"wu table db_mindex::add DB_INTERNAL_ERROR");
return (DB_INTERNAL_ERROR);
}
db_qcomp * comps = cq->queryloc();
if (indices.indices_val != NULL) {
for (i = 0; i < indices.indices_len; i++) {
curr_ind = comps[i].which_index;
indices.indices_val[curr_ind].add(
comps[i].index_value, recloc);
}
}
delete cq;
if (!noWriteThrough.flag) {
int queryRes;
entry_object *e = 0;
if (retrieveOldObjForModify((entry_obj **)&e) == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error retrieving old object for LDAP update",
myself);
return (DB_INTERNAL_ERROR);
}
queryRes = storeLDAP(q, obj, 0, e, 0);
if (queryRes != LDAP_SUCCESS) {
if (table->mapping.storeErrorDisp == abandon) {
WRITEUNLOCK2(this, table,
DB_INTERNAL_ERROR,
DB_INTERNAL_ERROR,
"wu db_mindex::add LDAP",
"wu table db_mindex::add LDAP");
return (DB_INTERNAL_ERROR);
} else {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: LDAP store failed: %s",
myself,
ldap_err2string(queryRes));
}
}
}
rstat = DB_SUCCESS;
} else
rstat = DB_NOTUNIQUE;
WRITEUNLOCK2(this, table, rstat, rstat,
"wu db_mindex::add",
"wu table db_mindex::add");
return (rstat);
}
static bool_t
transfer_aux(XDR* x, pptr rp)
{
return (xdr_db_mindex(x, (db_mindex*) rp));
}
class pickle_mindex: public pickle_file {
public:
pickle_mindex(char *f, pickle_mode m) : pickle_file(f, m) {}
int transfer(db_mindex* dp)
{
int ret;
WRITELOCK(dp, -1, "w pickle_mindex::transfer");
ret = pickle_file::transfer((pptr) dp, &transfer_aux);
WRITEUNLOCK(dp, ret, "wu pickle_mindex::transfer");
return (ret);
}
};
int
db_mindex::dump(char *file)
{
pickle_mindex f(file, PICKLE_WRITE);
int status = f.transfer(this);
if (status == 1)
return (-1);
else
return (status);
}
void
db_mindex::reset()
{
WRITELOCKV(this, "w db_mindex::reset");
reset_tables();
if (indices.indices_val) {
delete [] indices.indices_val;
indices.indices_val = NULL;
}
if (table) { delete table; table = NULL; }
if (scheme) { delete scheme; scheme = NULL; }
indices.indices_len = 0;
rversion.zero();
if (objPath.ptr != 0) {
free(objPath.ptr);
objPath.ptr = 0;
}
WRITEUNLOCKV(this, "wu db_mindex::reset");
}
int
db_mindex::load(char *file)
{
pickle_mindex f(file, PICKLE_READ);
int status;
int init_table = (this->table == NULL);
int init_scheme = (this->scheme == NULL);
WRITELOCK(this, -1, "w db_mindex::load");
reset();
if ((status = f.transfer(this)) != 0) {
reset();
}
if (status == 0 && this->scheme != 0 && init_scheme) {
db_scheme *tmpscheme = new db_scheme();
if (tmpscheme != 0) {
(void) memcpy(tmpscheme, this->scheme,
this->scheme->oldstructsize());
free(this->scheme);
this->scheme = tmpscheme;
} else {
status = -1;
}
}
if (status == 0 && this->table != 0 && init_table) {
db_table *tmptable = new db_table();
if (tmptable != 0) {
(void) memcpy(tmptable, this->table,
this->table->oldstructsize());
free(this->table);
this->table = tmptable;
(void) this->configure(file);
} else {
status = -1;
}
}
if (status == 0 && this->indices.indices_val != NULL) {
db_index *tmp_indices;
int n_index = this->indices.indices_len;
tmp_indices = new db_index[n_index];
if (tmp_indices != NULL) {
for (int i = 0; i < n_index; i++) {
if (tmp_indices[i].move_xdr_db_index
(&this->indices.indices_val[i]) != DB_SUCCESS) {
status = -1;
break;
}
}
free(this->indices.indices_val);
this->indices.indices_val = tmp_indices;
this->indices.indices_len = n_index;
} else {
status = -1;
}
}
WRITEUNLOCK(this, status, "wu db_mindex::load");
return (status);
}
void
db_mindex::print_stats()
{
long size, count, i;
long *stats = table->stats(TRUE);
printf("table_size = %d\n", stats[0]);
printf("last_used = %d\n", stats[1]);
printf("count = %d\n", stats[2]);
printf("free list size = %d\n", stats[3]);
printf("free list count = %d\n", stats[4]);
for (i = 5; i < 5+stats[4]; i++) {
printf("%d, ", stats[i]);
}
printf("\n");
free((char *)stats);
if (indices.indices_val == NULL) {
printf("No indices to print\n");
return;
}
for (i = 0; i < indices.indices_len; i++) {
printf("***** INDEX %d ******\n", i);
indices.indices_val[i].stats(&size, &count);
printf("index table size = %d\ncount = %d\n", size, count);
}
}
void
db_mindex::print_all_indices()
{
int i;
READLOCKV(this, "r db_mindex::print_all_indices");
if (indices.indices_val == NULL) {
printf("No indices to print\n");
READUNLOCKV(this, "ru db_mindex::print_all_indices");
return;
}
for (i = 0; i < indices.indices_len; i++) {
printf("***** INDEX %d ******\n", i);
indices.indices_val[i].print();
}
READUNLOCKV(this, "ru db_mindex::print_all_indices");
}
void
db_mindex::print_index(int n)
{
READLOCKV(this, "r db_mindex::print_index");
if (n >= 0 && n < indices.indices_len)
indices.indices_val[n].print();
READUNLOCKV(this, "ru db_mindex::print_index");
}