6811333 Remove prom_printf() message in emlxs driver
[opensolaris.git] / usr / src / lib / libnisdb / db_index_entry.cc
blob213358c65b26c61fdbef6bbe49876b609ac4c58b
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * db_index_entry.cc
25 * Copyright (c) 1988-2000 by Sun Microsystems, Inc.
26 * All Rights Reserved.
29 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <stdio.h>
33 #include "db_headers.h"
34 #include "db_index_entry.h"
35 #include "nisdb_mt.h"
37 /* Constructor: create an entry using given string and location info. */
38 db_index_entry::db_index_entry(char* name, int nlen, entryp ep)
40 if ((key = new item(name, nlen)) == NULL)
41 FATAL("db_index_entry::db_index_entry: cannot allocate space",
42 DB_MEMORY_LIMIT);
43 location = ep;
44 next_result = next = NULL;
45 /* what about hashval ? */
49 * Constructor: create an entry using the given info.
50 * A copy of the item is made. New entry is added to head of list of 'n'.
52 db_index_entry::db_index_entry(unsigned long hval, item* k,
53 entryp ep, db_index_entry_p rest)
55 if ((key = new item(k)) == NULL)
56 FATAL(
57 "db_index_entry::db_index_entry: cannot allocate space (2)",
58 DB_MEMORY_LIMIT);
59 location = ep;
60 next = rest;
61 next_result = NULL;
62 hashval = hval;
66 * Join two lists (entry as identified by its 'location' occurs on both list,
67 * then it is included in the list returned).
68 * Returns pointer to resulting list; size of list
69 * returned in 'newsize'. List is chained using the 'nextresult' pointer.
71 db_index_entry_p
72 db_index_entry::join(long /* size1 */, long /* size2 */,
73 db_index_entry_p list2, long * newsize)
75 db_index_entry_p mergedlist = NULL, // records that occur on both lists
76 mergedtail = NULL, // tail pointer of mergedlist
77 current, // current pointer of this list
78 other, // current pointer of updated list2
79 otherprev, // previous pointer of updated list2
80 otherstart = list2; // head of updated list2
81 int count = 0;
84 * algorithm is straightforward:
85 * traverse this list,
86 * for each item, traverse list2,
87 * if item on list1 matches item on list2,
88 * add to merged list and delete it from list2.
91 for (current = this; (current != NULL) && (otherstart != NULL);
92 current = current->next_result) {
93 /* find 'current' in 'other' list */
94 otherprev = NULL;
95 for (other = otherstart;
96 other != NULL;
97 other = other->next_result) {
98 if (current->location == other->location)
99 break;
100 else
101 otherprev = other;
103 if (other != NULL) { /* found */
104 /* delete 'other' from future consideration */
105 if (otherprev == NULL) {
106 /* new head */
107 otherstart = otherstart->next_result;
108 } else {
109 /* bypass 'other' */
110 otherprev->next_result = other->next_result;
112 /* add 'current' to list of items found so far */
113 if (mergedlist == NULL)
114 mergedlist = current; /* first one found */
115 else
116 mergedtail->next_result = current; /* append */
117 mergedtail = current; /* point to last entry found */
118 ++count;
121 if (mergedtail) mergedtail->next_result = NULL; /* set end to null */
122 *newsize = count;
123 return (mergedlist);
126 /* Relocate bucket starting with this entry to new hashtable 'new_tab'. */
127 void
128 db_index_entry::relocate(db_index_entry_p *new_tab, unsigned long hashsize)
130 db_index_entry_p np, next_np, *hp;
132 for (np = this; np != NULL; np = next_np) {
133 next_np = np->next;
134 hp = &new_tab[np->hashval % hashsize];
135 np->next = *hp;
136 *hp = np;
140 /* Return the next entry in the bucket starting with this entry
141 with the same hashvalue, key and location as this entry. */
142 db_index_entry_p
143 db_index_entry::getnext(bool_t casein, unsigned long hval, item *i, entryp l)
145 db_index_entry_p np;
147 for (np = this; np != NULL; np = np->next) {
148 if ((np->hashval == hval) &&
149 (np->key->equal(i, casein)) && l == location) {
150 break;
154 if (np != NULL)
155 return (np->next);
156 else
157 return (NULL);
161 * Return pointer to index entry with same hash value, same key,
162 * and same record number as those supplied. Returns NULL if not found.
164 db_index_entry_p
165 db_index_entry::lookup(bool_t casein, unsigned long hval,
166 item *i, entryp recnum)
168 db_index_entry_p np;
170 for (np = this; np != NULL; np = np->next) {
171 if (np->hashval == hval && np->key->equal(i, casein) &&
172 np->location == recnum) {
173 break;
176 if (np) np->next_result = NULL; /* should only be 1 */
177 return (np);
181 * Returns pointer to a list of index entries with the same hash value and
182 * key as those given. Returns in 'how_many' the number of entries in the
183 * list returned. The list is linked by the 'next_result' field of the
184 * index entries. These may be changed after the next call to 'lookup'
185 * or 'join'.
187 db_index_entry_p
188 db_index_entry::lookup(bool_t casein, unsigned long hval,
189 item *i, long * how_many)
191 db_index_entry_p fst, prev, curr;
192 long count = 0;
194 for (fst = this; fst != NULL; fst = fst->next) {
195 if ((fst->hashval == hval) && (fst->key->equal(i, casein))) {
196 ++count;
197 break;
201 * gather all the ones with the same key; assume that all entries
202 * with same key are located contiguously.
204 if (fst != NULL) {
205 prev = fst;
206 for (curr = fst->next; curr != NULL; curr = curr->next) {
207 if ((curr->hashval == hval) &&
208 (curr->key->equal(i, casein))) {
209 prev->addresult(curr);
210 prev = curr;
211 ++count;
213 else
214 break;
216 prev->addresult(NULL); /* terminate the list -CM */
218 *how_many = count;
219 return (fst);
223 * Remove entry with the specified hashvalue, key, and record number.
224 * Returns 'TRUE' if successful, FALSE otherwise.
225 * If the entry being removed is at the head of the list, then
226 * the head is updated to reflect the removal. The storage for the index
227 * entry is freed. The record pointed to by 'recnum' must be removed
228 * through another means. All that is updated in this operation is the
229 * index.
231 bool_t
232 db_index_entry::remove(db_index_entry_p *head, bool_t casein,
233 unsigned long hval, item *i, entryp recnum)
235 db_index_entry_p np, dp;
237 /* Search for it in the bucket */
238 for (dp = np = this; np != NULL; np = np->next) {
239 if (np->hashval == hval && np->key->equal(i, casein) &&
240 np->location == recnum) {
241 break;
242 } else {
243 dp = np;
247 if (np == NULL) return FALSE; // cannot delete if it is not there
249 if (dp == np) {
250 *head = np->next; // deleting head of bucket
251 } else {
252 dp->next = np->next; // deleting interior link
254 delete np;
256 return (TRUE);
259 /* Replace the 'location' field of the index entry with the given one. */
261 void
262 db_index_entry::replace(entryp ep)
264 location = ep;
269 * Create and add an entry with the given hashvalue, key value, and record
270 * location, to the bucket pointed to by 'hashvalue'.
271 * If an entry with the same hashvalue and key value is found,
272 * the entry is added after the first entry with this property. Otherwise,
273 * the entry is added to the head of the bucket. This way, entries
274 * with the same hashvalue and key are not scattered throughout the bucket
275 * but they occur together. Copy is made of given key.
277 bool_t
278 db_index_entry::add(db_index_entry **head, bool_t casein,
279 unsigned long hval, item *i, entryp recnum)
282 db_index_entry_p curr, prev, rp, save;
284 /* Search for it in the bucket */
285 for (prev = curr = this; curr != NULL; curr = curr->next) {
286 if (curr->hashval == hval && curr->key->equal(i, casein)) {
287 break;
288 } else {
289 prev = curr;
295 if (curr == NULL) {
296 /* none with same hashvalue/key found. Add to head of list. */
297 save = *head;
298 *head = new db_index_entry(hval, i, recnum, * head);
299 if (*head == NULL) {
300 *head = save; // restore previous state
301 FATAL3(
302 "db_index_entry::add: cannot allocate space for head",
303 DB_MEMORY_LIMIT, FALSE);
305 } else {
306 /* Found same hashvalue/key. Add entry after that one. */
307 save = prev->next;
308 prev->next = new db_index_entry(hval, i, recnum, prev->next);
309 if (prev->next == NULL) {
310 prev->next = save; // restore previous state
311 FATAL3(
312 "db_index_entry::add: cannot allocate space for entry",
313 DB_MEMORY_LIMIT, FALSE);
317 return (TRUE);
320 /* Print this entry to stdout. */
321 void
322 db_index_entry::print()
324 if (key != NULL) {
325 key->print();
326 printf("\t");
328 printf(": %d\n", location);
331 /* Print bucket starting with this entry. */
332 void
333 db_index_entry::print_all()
335 db_index_entry *np;
336 for (np = this; np != NULL; np = np->next) {
337 np->print();
341 /* Print result list starting with this entry. */
342 void
343 db_index_entry::print_results()
345 db_index_entry *np;
346 for (np = this; np != NULL; np = np->next_result) {
347 np->print();