|
|
1.1 root 1: /* turbo_load.c - Quickly check for duplicate RDN's (from Tim Howes) */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/quipu/RCS/turbo_load.c,v 7.1 90/07/09 14:46:48 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/quipu/RCS/turbo_load.c,v 7.1 90/07/09 14:46:48 mrose Exp $
9: *
10: *
11: * $Log: turbo_load.c,v $
12: * Revision 7.1 90/07/09 14:46:48 mrose
13: * sync
14: *
15: * Revision 7.0 89/11/23 22:20:57 mrose
16: * Release 6.0
17: *
18: */
19:
20: /*
21: * NOTICE
22: *
23: * Acquisition, use, and distribution of this module and related
24: * materials are subject to the restrictions of a license agreement.
25: * Consult the Preface in the User's Manual for the full terms of
26: * this agreement.
27: *
28: */
29:
30: #include "quipu/config.h"
31: #include "quipu/util.h"
32: #include "quipu/entry.h"
33: #include "quipu/malloc.h"
34: #include <sys/stat.h>
35: #ifdef TURBO_DISK
36: #include "../../gdbm-1.3/gdbmdefs.h"
37: #endif
38:
39: extern LLog * log_dsap;
40:
41: extern int turbo_size;
42: extern int turbo_name_size;
43:
44: struct node {
45: char *name;
46: struct node *left;
47: struct node *right;
48: int bf;
49: };
50:
51: static struct node *node_heap;
52: static struct node *node_next;
53:
54: static char *name_heap;
55: static char *name_next;
56:
57: static struct node *root;
58: static long count;
59: static long comparisons;
60: static long entries;
61:
62: turbo_start(file)
63: #ifdef TURBO_DISK
64: gdbm_file_info *file;
65: #else
66: FILE *file;
67: #endif
68: {
69: struct stat buf;
70: int save_heap;
71:
72: #ifdef TURBO_DISK
73: if ( fstat(file->desc, &buf) != 0 ) {
74: #else
75: if ( fstat(fileno(file), &buf) != 0 ) {
76: #endif
77: LLOG (log_dsap, LLOG_EXCEPTIONS,("turbo: could not get filesize"));
78: return FALSE;
79: }
80:
81: /*
82: * This is a heuristic based on some edb file sizes at
83: * UM. If you find this isn't enough, try using
84: * a smaller turbo_size (in quiputailor). This should
85: * eventually be fixed to malloc more if the heuristic
86: * turns out not to be enough.
87: */
88: entries = (buf.st_size) / turbo_size;
89: if ( entries < 100 ) entries = 100;
90:
91: save_heap = mem_heap;
92: GENERAL_HEAP;
93: node_heap = (struct node *) calloc( (unsigned)entries, sizeof(struct node) );
94: node_next = node_heap;
95: name_heap = (char *) calloc( (unsigned)entries, (unsigned)turbo_name_size );
96: name_next = name_heap;
97: mem_heap = save_heap;
98: root = 0;
99: count = 0;
100: comparisons = 0;
101:
102: mem_heap = save_heap;
103: return TRUE;
104: }
105:
106: #define LH -1
107: #define EH 0
108: #define RH 1
109: #define ROTATERIGHT(x) { struct node *tmp;\
110: if ( *x == NULL || (*x)->left == NULL ) {\
111: (void) printf("RR error\n"); exit(1); \
112: }\
113: tmp = (*x)->left;\
114: (*x)->left = tmp->right;\
115: tmp->right = *x;\
116: *x = tmp;\
117: }
118: #define ROTATELEFT(x) { struct node *tmp;\
119: if ( *x == NULL || (*x)->right == NULL ) {\
120: (void) printf("RL error\n"); exit(1); \
121: }\
122: tmp = (*x)->right;\
123: (*x)->right = tmp->left;\
124: tmp->left = *x;\
125: *x = tmp;\
126: }
127:
128:
129: static avl_insert(iroot, name, taller)
130: struct node **iroot;
131: char *name;
132: int *taller;
133: {
134: int rc, cmp, tallersub;
135: struct node *l, *r;
136:
137: comparisons++;
138: if ( *iroot == 0 ) {
139: *iroot = node_next++;
140: (*iroot)->left = 0;
141: (*iroot)->right = 0;
142: (*iroot)->bf = 0;
143: (*iroot)->name = name_next;
144: while ( *(name_next++) = *(name++) );
145: *taller = 1;
146: return (OK);
147: }
148:
149: cmp = strcmp(name, (*iroot)->name);
150: /* equal - duplicate name */
151: if ( cmp == 0 ) {
152: *taller = 0;
153: return (NOTOK);
154: }
155: /* go right */
156: else if ( cmp > 0 ) {
157: rc = avl_insert(&((*iroot)->right), name, &tallersub);
158: if (tallersub)
159: switch ((*iroot)->bf) {
160: case LH : /* left high - balance is restored */
161: (*iroot)->bf = EH;
162: *taller = 0;
163: break;
164: case EH : /* equal height - now right heavy */
165: (*iroot)->bf = RH;
166: *taller = 1;
167: break;
168: case RH : /* right heavy to start - right balance */
169: r = (*iroot)->right;
170: switch (r->bf) {
171: case LH : /* double rotation left */
172: l = r->left;
173: switch (l->bf) {
174: case LH : (*iroot)->bf = EH;
175: r->bf = RH;
176: break;
177: case EH : (*iroot)->bf = EH;
178: r->bf = EH;
179: break;
180: case RH : (*iroot)->bf = LH;
181: r->bf = EH;
182: break;
183: }
184: l->bf = EH;
185: ROTATERIGHT((&r))
186: (*iroot)->right = r;
187: ROTATELEFT(iroot)
188: *taller = 0;
189: break;
190: case EH : /* This should never happen */
191: break;
192: case RH : /* single rotation left */
193: (*iroot)->bf = EH;
194: r->bf = EH;
195: ROTATELEFT(iroot)
196: *taller = 0;
197: break;
198: }
199: break;
200: }
201: else
202: *taller = 0;
203: }
204: /* go left */
205: else {
206: rc = avl_insert(&((*iroot)->left), name, &tallersub);
207: if (tallersub)
208: switch ((*iroot)->bf) {
209: case LH : /* left high to start - left balance */
210: l = (*iroot)->left;
211: switch (l->bf) {
212: case LH : /* single rotation right */
213: (*iroot)->bf = EH;
214: l->bf = EH;
215: ROTATERIGHT(iroot)
216: *taller = 0;
217: break;
218: case EH : /* this should never happen */
219: break;
220: case RH : /* double rotation right */
221: r = l->right;
222: switch (r->bf) {
223: case LH : (*iroot)->bf = RH;
224: l->bf = EH;
225: break;
226: case EH : (*iroot)->bf = EH;
227: l->bf = EH;
228: break;
229: case RH : (*iroot)->bf = EH;
230: l->bf = LH;
231: break;
232: }
233: r->bf = EH;
234: ROTATELEFT((&l))
235: (*iroot)->left = l;
236: ROTATERIGHT(iroot)
237: *taller = 0;
238: break;
239: }
240: break;
241: case EH : /* equal height - now left heavy */
242: (*iroot)->bf = LH;
243: *taller = 1;
244: break;
245: case RH : /* right high - balance is restored */
246: (*iroot)->bf = EH;
247: *taller = 0;
248: break;
249: }
250: else
251: *taller = 0;
252: }
253: return(rc);
254: }
255:
256: turbo_insert(name)
257: RDN name;
258: {
259: int taller;
260:
261: if ( ++count >= entries ) {
262: if (count == entries)
263: LLOG (log_dsap,LLOG_EXCEPTIONS,("turbo botch - decrease turbo_size (currently %d - %d entries read)",turbo_size,entries));
264: /* should realloc */
265: return OK;
266: }
267:
268: if (strlen ((char *) name->rdn_av.av_struct) >= turbo_name_size) {
269: LLOG (log_dsap,LLOG_EXCEPTIONS,("turbo botch - increase turbo_name_size (%d required for '%s', currently %d)",
270: strlen ((char *) name->rdn_av.av_struct),
271: (char *)name->rdn_av.av_struct, turbo_name_size));
272: /* should realloc */
273: return OK;
274: }
275:
276: return (avl_insert(&root, (char *) name->rdn_av.av_struct, &taller));
277: }
278:
279: turbo_end()
280: {
281: int save_heap;
282:
283: DLOG (log_dsap,LLOG_DEBUG,("turbo %d entries unused",entries - count));
284:
285: save_heap = mem_heap;
286: GENERAL_HEAP;
287:
288: free(name_heap);
289: free((char *)node_heap);
290:
291: mem_heap = save_heap;
292: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.