1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * db_index.cc 24*7c478bd9Sstevel@tonic-gate * 25*7c478bd9Sstevel@tonic-gate * Copyright 1988-2002 Sun Microsystems, Inc. All rights reserved. 26*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 27*7c478bd9Sstevel@tonic-gate */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include <stdio.h> 32*7c478bd9Sstevel@tonic-gate #include <malloc.h> 33*7c478bd9Sstevel@tonic-gate #include "db_headers.h" 34*7c478bd9Sstevel@tonic-gate #include "db_index.h" 35*7c478bd9Sstevel@tonic-gate #include "db_pickle.h" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include "nisdb_mt.h" 38*7c478bd9Sstevel@tonic-gate #include "nisdb_rw.h" 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate static int hashsizes[] = { /* hashtable sizes */ 41*7c478bd9Sstevel@tonic-gate 11, 42*7c478bd9Sstevel@tonic-gate 113, 43*7c478bd9Sstevel@tonic-gate 337, 44*7c478bd9Sstevel@tonic-gate 977, 45*7c478bd9Sstevel@tonic-gate 2053, 46*7c478bd9Sstevel@tonic-gate 4073, 47*7c478bd9Sstevel@tonic-gate 8011, 48*7c478bd9Sstevel@tonic-gate 16001, 49*7c478bd9Sstevel@tonic-gate 0 50*7c478bd9Sstevel@tonic-gate }; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate // prevents wrap around numbers from being passed 53*7c478bd9Sstevel@tonic-gate #define CALLOC_LIMIT 536870911 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* Constructor: creates empty index. */ 56*7c478bd9Sstevel@tonic-gate db_index::db_index() 57*7c478bd9Sstevel@tonic-gate { 58*7c478bd9Sstevel@tonic-gate tab = NULL; 59*7c478bd9Sstevel@tonic-gate table_size = 0; 60*7c478bd9Sstevel@tonic-gate count = 0; 61*7c478bd9Sstevel@tonic-gate case_insens = FALSE; 62*7c478bd9Sstevel@tonic-gate INITRW(index); 63*7c478bd9Sstevel@tonic-gate /* grow(); */ 64*7c478bd9Sstevel@tonic-gate } 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate /* Destructor: deletes index, including all associated db_index_entry. */ 68*7c478bd9Sstevel@tonic-gate db_index::~db_index() 69*7c478bd9Sstevel@tonic-gate { 70*7c478bd9Sstevel@tonic-gate WRITELOCKV(this, "w db_index::~db_index"); 71*7c478bd9Sstevel@tonic-gate reset(); 72*7c478bd9Sstevel@tonic-gate DESTROYRW(index); 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate /* Get rid of table and all associated entries, and reset counters */ 76*7c478bd9Sstevel@tonic-gate void 77*7c478bd9Sstevel@tonic-gate db_index::reset() 78*7c478bd9Sstevel@tonic-gate { 79*7c478bd9Sstevel@tonic-gate db_index_entry * curr, *n; 80*7c478bd9Sstevel@tonic-gate int i; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate WRITELOCKV(this, "w db_index::reset"); 83*7c478bd9Sstevel@tonic-gate /* Add sanity test in case table was corrupted */ 84*7c478bd9Sstevel@tonic-gate if (tab != NULL) { 85*7c478bd9Sstevel@tonic-gate for (i = 0; i < table_size; i++) { // go through table 86*7c478bd9Sstevel@tonic-gate curr = tab[i]; 87*7c478bd9Sstevel@tonic-gate while (curr != NULL) { // go through bucket 88*7c478bd9Sstevel@tonic-gate n = curr->getnextentry(); 89*7c478bd9Sstevel@tonic-gate delete curr; 90*7c478bd9Sstevel@tonic-gate curr = n; 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate delete tab; // get rid of table itself 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate tab = NULL; 98*7c478bd9Sstevel@tonic-gate table_size = count = 0; 99*7c478bd9Sstevel@tonic-gate WRITEUNLOCKV(this, "wu db_index::reset"); 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * Initialize index according to the specification of the key descriptor 105*7c478bd9Sstevel@tonic-gate * Currently, only affects case_insens flag of index. 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate void 108*7c478bd9Sstevel@tonic-gate db_index::init(db_key_desc * k) 109*7c478bd9Sstevel@tonic-gate { 110*7c478bd9Sstevel@tonic-gate WRITELOCKV(this, "w db_index::init"); 111*7c478bd9Sstevel@tonic-gate if ((k->key_flags)&DB_KEY_CASE) 112*7c478bd9Sstevel@tonic-gate case_insens = TRUE; 113*7c478bd9Sstevel@tonic-gate WRITEUNLOCKV(this, "wu db_index::init"); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* Returns the next size to use for the hash table */ 117*7c478bd9Sstevel@tonic-gate static long unsigned 118*7c478bd9Sstevel@tonic-gate get_next_hashsize(long unsigned oldsize) 119*7c478bd9Sstevel@tonic-gate { 120*7c478bd9Sstevel@tonic-gate long unsigned newsize = 0, n; 121*7c478bd9Sstevel@tonic-gate if (oldsize == 0) 122*7c478bd9Sstevel@tonic-gate newsize = hashsizes[0]; 123*7c478bd9Sstevel@tonic-gate else { 124*7c478bd9Sstevel@tonic-gate for (n = 0; newsize = hashsizes[n++]; ) 125*7c478bd9Sstevel@tonic-gate if (oldsize == newsize) { 126*7c478bd9Sstevel@tonic-gate newsize = hashsizes[n]; /* get next size */ 127*7c478bd9Sstevel@tonic-gate break; 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate if (newsize == 0) 130*7c478bd9Sstevel@tonic-gate newsize = oldsize * 2 + 1; /* just double */ 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate return (newsize); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* 136*7c478bd9Sstevel@tonic-gate * Grow the current hashtable upto the next size. 137*7c478bd9Sstevel@tonic-gate * The contents of the existing hashtable is copied to the new one and 138*7c478bd9Sstevel@tonic-gate * relocated according to its hashvalue relative to the new size. 139*7c478bd9Sstevel@tonic-gate * Old table is deleted after the relocation. 140*7c478bd9Sstevel@tonic-gate */ 141*7c478bd9Sstevel@tonic-gate void 142*7c478bd9Sstevel@tonic-gate db_index::grow() 143*7c478bd9Sstevel@tonic-gate { 144*7c478bd9Sstevel@tonic-gate long unsigned oldsize = table_size, i; 145*7c478bd9Sstevel@tonic-gate db_index_entry_p * oldtab = tab; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate WRITELOCKV(this, "w db_index::grow"); 148*7c478bd9Sstevel@tonic-gate table_size = get_next_hashsize(table_size); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 151*7c478bd9Sstevel@tonic-gate if (debug > 3) 152*7c478bd9Sstevel@tonic-gate fprintf(ddt, "savehash GROWING to %d\n", table_size); 153*7c478bd9Sstevel@tonic-gate #endif 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate if (table_size > CALLOC_LIMIT) { 156*7c478bd9Sstevel@tonic-gate table_size = oldsize; 157*7c478bd9Sstevel@tonic-gate WRITEUNLOCKV(this, 158*7c478bd9Sstevel@tonic-gate "wu db_index::grow: table size exceeds calloc limit"); 159*7c478bd9Sstevel@tonic-gate FATAL("db_index::grow: table size exceeds calloc limit", 160*7c478bd9Sstevel@tonic-gate DB_MEMORY_LIMIT); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate if ((tab = (db_index_entry_p*) 164*7c478bd9Sstevel@tonic-gate calloc((unsigned int) table_size, 165*7c478bd9Sstevel@tonic-gate sizeof (db_index_entry_p))) == NULL) { 166*7c478bd9Sstevel@tonic-gate tab = oldtab; // restore previous table info 167*7c478bd9Sstevel@tonic-gate table_size = oldsize; 168*7c478bd9Sstevel@tonic-gate WRITEUNLOCKV(this, 169*7c478bd9Sstevel@tonic-gate "wu db_index::grow: cannot allocate space"); 170*7c478bd9Sstevel@tonic-gate FATAL("db_index::grow: cannot allocate space", DB_MEMORY_LIMIT); 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate if (oldtab != NULL) { // must transfer contents of old to new 174*7c478bd9Sstevel@tonic-gate for (i = 0; i < oldsize; i++) { 175*7c478bd9Sstevel@tonic-gate oldtab[i]->relocate(tab, table_size); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate delete oldtab; // delete old hashtable 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate WRITEUNLOCKV(this, "wu db_index::grow"); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* 183*7c478bd9Sstevel@tonic-gate * Look up given index value in hashtable. 184*7c478bd9Sstevel@tonic-gate * Return pointer to db_index_entries that match the given value, linked 185*7c478bd9Sstevel@tonic-gate * via the 'next_result' pointer. Return in 'how_many_found' the size 186*7c478bd9Sstevel@tonic-gate * of this list. Return NULL if not found. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate db_index_entry * 189*7c478bd9Sstevel@tonic-gate db_index::lookup(item *index_value, long *how_many_found, 190*7c478bd9Sstevel@tonic-gate db_table *table, bool_t checkTTL) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate register unsigned long hval; 193*7c478bd9Sstevel@tonic-gate unsigned long bucket; 194*7c478bd9Sstevel@tonic-gate db_index_entry *ret; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate READLOCK(this, NULL, "r db_index::lookup"); 197*7c478bd9Sstevel@tonic-gate if (index_value == NULL || table_size == 0 || tab == NULL) { 198*7c478bd9Sstevel@tonic-gate READUNLOCK(this, NULL, "ru db_index::lookup"); 199*7c478bd9Sstevel@tonic-gate return (NULL); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate hval = index_value->get_hashval(case_insens); 202*7c478bd9Sstevel@tonic-gate bucket = hval % table_size; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate db_index_entry_p fst = tab[bucket ]; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (fst != NULL) 207*7c478bd9Sstevel@tonic-gate ret = fst->lookup(case_insens, hval, 208*7c478bd9Sstevel@tonic-gate index_value, how_many_found); 209*7c478bd9Sstevel@tonic-gate else 210*7c478bd9Sstevel@tonic-gate ret = NULL; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate if (ret != NULL && checkTTL && table != NULL) { 213*7c478bd9Sstevel@tonic-gate if (!table->cacheValid(ret->getlocation())) 214*7c478bd9Sstevel@tonic-gate ret = NULL; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate READUNLOCK(this, ret, "ru db_index::lookup"); 218*7c478bd9Sstevel@tonic-gate return (ret); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * Remove the entry with the given index value and location 'recnum'. 223*7c478bd9Sstevel@tonic-gate * If successful, return DB_SUCCESS; otherwise DB_NOTUNIQUE if index_value 224*7c478bd9Sstevel@tonic-gate * is null; DB_NOTFOUND if entry is not found. 225*7c478bd9Sstevel@tonic-gate * If successful, decrement count of number of entries in hash table. 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate db_status 228*7c478bd9Sstevel@tonic-gate db_index::remove(item* index_value, entryp recnum) 229*7c478bd9Sstevel@tonic-gate { 230*7c478bd9Sstevel@tonic-gate register unsigned long hval; 231*7c478bd9Sstevel@tonic-gate unsigned long bucket; 232*7c478bd9Sstevel@tonic-gate register db_index_entry *fst; 233*7c478bd9Sstevel@tonic-gate db_status ret; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (index_value == NULL) 236*7c478bd9Sstevel@tonic-gate return (DB_NOTUNIQUE); 237*7c478bd9Sstevel@tonic-gate WRITELOCK(this, DB_LOCK_ERROR, "w db_index::remove"); 238*7c478bd9Sstevel@tonic-gate if (table_size == 0 || tab == NULL) { 239*7c478bd9Sstevel@tonic-gate WRITEUNLOCK(this, DB_NOTFOUND, "wu db_index::remove"); 240*7c478bd9Sstevel@tonic-gate return (DB_NOTFOUND); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate hval = index_value->get_hashval(case_insens); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate bucket = hval % table_size; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate fst = tab[bucket]; 247*7c478bd9Sstevel@tonic-gate if (fst == NULL) 248*7c478bd9Sstevel@tonic-gate ret = DB_NOTFOUND; 249*7c478bd9Sstevel@tonic-gate else if (fst->remove(&tab[bucket], case_insens, hval, index_value, 250*7c478bd9Sstevel@tonic-gate recnum)) { 251*7c478bd9Sstevel@tonic-gate --count; 252*7c478bd9Sstevel@tonic-gate ret = DB_SUCCESS; 253*7c478bd9Sstevel@tonic-gate } else 254*7c478bd9Sstevel@tonic-gate ret = DB_NOTFOUND; 255*7c478bd9Sstevel@tonic-gate WRITEUNLOCK(this, ret, "wu db_index::remove"); 256*7c478bd9Sstevel@tonic-gate return (ret); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * Add a new index entry with the given index value and location 'recnum'. 261*7c478bd9Sstevel@tonic-gate * Return DB_NOTUNIQUE, if entry with identical index_value and recnum 262*7c478bd9Sstevel@tonic-gate * already exists. If entry is added, return DB_SUCCESS. 263*7c478bd9Sstevel@tonic-gate * Increment count of number of entries in index table and grow table 264*7c478bd9Sstevel@tonic-gate * if number of entries equals size of table. 265*7c478bd9Sstevel@tonic-gate * Note that a copy of index_value is made for new entry. 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate db_status 268*7c478bd9Sstevel@tonic-gate db_index::add(item* index_value, entryp recnum) 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate register unsigned long hval; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate if (index_value == NULL) 273*7c478bd9Sstevel@tonic-gate return (DB_NOTUNIQUE); 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate hval = index_value->get_hashval(case_insens); 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate WRITELOCK(this, DB_LOCK_ERROR, "w db_index::add"); 278*7c478bd9Sstevel@tonic-gate if (tab == NULL) grow(); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate db_index_entry_p fst, newbucket; 281*7c478bd9Sstevel@tonic-gate unsigned long bucket; 282*7c478bd9Sstevel@tonic-gate bucket = hval %table_size; 283*7c478bd9Sstevel@tonic-gate fst = tab[bucket]; 284*7c478bd9Sstevel@tonic-gate if (fst == NULL) { /* Empty bucket */ 285*7c478bd9Sstevel@tonic-gate if ((newbucket = new db_index_entry(hval, index_value, 286*7c478bd9Sstevel@tonic-gate recnum, tab[bucket])) == NULL) { 287*7c478bd9Sstevel@tonic-gate WRITEUNLOCK(this, DB_MEMORY_LIMIT, 288*7c478bd9Sstevel@tonic-gate "wu db_index::add"); 289*7c478bd9Sstevel@tonic-gate FATAL3("db_index::add: cannot allocate space", 290*7c478bd9Sstevel@tonic-gate DB_MEMORY_LIMIT, DB_MEMORY_LIMIT); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate tab[bucket] = newbucket; 293*7c478bd9Sstevel@tonic-gate } else if (fst->add(&tab[bucket], case_insens, 294*7c478bd9Sstevel@tonic-gate hval, index_value, recnum)) { 295*7c478bd9Sstevel@tonic-gate /* do nothing */ 296*7c478bd9Sstevel@tonic-gate } else { 297*7c478bd9Sstevel@tonic-gate WRITEUNLOCK(this, DB_NOTUNIQUE, "wu db_index::add"); 298*7c478bd9Sstevel@tonic-gate return (DB_NOTUNIQUE); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate /* increase hash table size if number of entries equals table size */ 302*7c478bd9Sstevel@tonic-gate if (++count > table_size) 303*7c478bd9Sstevel@tonic-gate grow(); 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate WRITEUNLOCK(this, DB_SUCCESS, "wu db_index::add"); 306*7c478bd9Sstevel@tonic-gate return (DB_SUCCESS); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* ************************* pickle_index ********************* */ 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate /* Does the actual writing to/from file specific for db_index structure. */ 312*7c478bd9Sstevel@tonic-gate static bool_t 313*7c478bd9Sstevel@tonic-gate transfer_aux(XDR* x, pptr ip) 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate return (xdr_db_index(x, (db_index*) ip)); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate class pickle_index: public pickle_file { 319*7c478bd9Sstevel@tonic-gate public: 320*7c478bd9Sstevel@tonic-gate pickle_index(char *f, pickle_mode m) : pickle_file(f, m) {} 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* Transfers db_index structure pointed to by dp to/from file. */ 323*7c478bd9Sstevel@tonic-gate int transfer(db_index* dp) 324*7c478bd9Sstevel@tonic-gate { return (pickle_file::transfer((pptr) dp, &transfer_aux)); } 325*7c478bd9Sstevel@tonic-gate }; 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* Dumps this index to named file. */ 328*7c478bd9Sstevel@tonic-gate int 329*7c478bd9Sstevel@tonic-gate db_index::dump(char *file) 330*7c478bd9Sstevel@tonic-gate { 331*7c478bd9Sstevel@tonic-gate int ret; 332*7c478bd9Sstevel@tonic-gate pickle_index f(file, PICKLE_WRITE); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate WRITELOCK(this, -1, "w db_index::dump"); 335*7c478bd9Sstevel@tonic-gate int status = f.transfer(this); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate if (status == 1) 338*7c478bd9Sstevel@tonic-gate ret = -1; /* cannot open for write */ 339*7c478bd9Sstevel@tonic-gate else 340*7c478bd9Sstevel@tonic-gate ret = status; 341*7c478bd9Sstevel@tonic-gate WRITEUNLOCK(this, ret, "wu db_index::dump"); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Constructor: creates index by loading it from the specified file. 346*7c478bd9Sstevel@tonic-gate * If loading fails, creates empty index. 347*7c478bd9Sstevel@tonic-gate */ 348*7c478bd9Sstevel@tonic-gate db_index::db_index(char *file) 349*7c478bd9Sstevel@tonic-gate { 350*7c478bd9Sstevel@tonic-gate pickle_index f(file, PICKLE_READ); 351*7c478bd9Sstevel@tonic-gate tab = NULL; 352*7c478bd9Sstevel@tonic-gate table_size = count = 0; 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* load new hashbuf */ 355*7c478bd9Sstevel@tonic-gate if (f.transfer(this) < 0) { 356*7c478bd9Sstevel@tonic-gate /* Load failed; reset. */ 357*7c478bd9Sstevel@tonic-gate tab = NULL; 358*7c478bd9Sstevel@tonic-gate table_size = count = 0; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate INITRW(index); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Return in 'tsize' the table_size, and 'tcount' the number of entries 367*7c478bd9Sstevel@tonic-gate * in the table. 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate void 370*7c478bd9Sstevel@tonic-gate db_index::stats(long *tsize, long *tcount) 371*7c478bd9Sstevel@tonic-gate { 372*7c478bd9Sstevel@tonic-gate READLOCKV(this, "r db_index::stats"); 373*7c478bd9Sstevel@tonic-gate *tsize = table_size; 374*7c478bd9Sstevel@tonic-gate *tcount = count; 375*7c478bd9Sstevel@tonic-gate READUNLOCKV(this, "ru db_index::stats"); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate /* Print all entries in the table. */ 379*7c478bd9Sstevel@tonic-gate void 380*7c478bd9Sstevel@tonic-gate db_index::print() 381*7c478bd9Sstevel@tonic-gate { 382*7c478bd9Sstevel@tonic-gate long i; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate READLOCKV(this, "r db_index::print"); 385*7c478bd9Sstevel@tonic-gate /* Add sanity check in case table corrupted */ 386*7c478bd9Sstevel@tonic-gate if (tab != NULL) { 387*7c478bd9Sstevel@tonic-gate for (i = 0; i < table_size; i++) { 388*7c478bd9Sstevel@tonic-gate if (tab[i] != NULL) 389*7c478bd9Sstevel@tonic-gate tab[i]->print_all(); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate READUNLOCKV(this, "ru db_index::print"); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate /* 396*7c478bd9Sstevel@tonic-gate * Moves an index from an xdr index. Upon completion, original index's tab 397*7c478bd9Sstevel@tonic-gate * will be NULL. 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate db_status 401*7c478bd9Sstevel@tonic-gate db_index::move_xdr_db_index(db_index *orig) 402*7c478bd9Sstevel@tonic-gate { 403*7c478bd9Sstevel@tonic-gate table_size = orig->table_size; 404*7c478bd9Sstevel@tonic-gate orig->table_size = 0; 405*7c478bd9Sstevel@tonic-gate count = orig->count; 406*7c478bd9Sstevel@tonic-gate orig->count = 0; 407*7c478bd9Sstevel@tonic-gate case_insens = orig->case_insens; 408*7c478bd9Sstevel@tonic-gate tab = orig->tab; 409*7c478bd9Sstevel@tonic-gate orig->tab = NULL; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate return (DB_SUCCESS); 412*7c478bd9Sstevel@tonic-gate } 413