-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathotable.c
More file actions
184 lines (151 loc) · 4.13 KB
/
otable.c
File metadata and controls
184 lines (151 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <stdio.h>
#include <string.h>
#include "lint.h"
#include "config.h"
#include "interpret.h"
#include "object.h"
/*
* Object name hash table. Object names are unique, so no special
* problems - like stralloc.c. For non-unique hashed names, we need
* a better package (if we want to be able to get at them all) - we
* cant move them to the head of the hash chain, for example.
*
* Note: if you change an object name, you must remove it and reenter it.
*/
char * xalloc();
/*
* hash table - list of pointers to heads of object chains.
* Each object in chain has a pointer, next_hash, to the next object.
* OTABLE_SIZE is in config.h, and should be a prime, probably between
* 100 and 1000. You can have a quite small table and still get very good
* performance! Our database is 8Meg; we use about 500.
*/
static struct object ** obj_table = 0;
static void init_otable()
{
int x;
obj_table = (struct object **)
xalloc(sizeof(struct object *) * OTABLE_SIZE);
for (x=0; x<OTABLE_SIZE; x++)
obj_table[x] = 0;
}
/*
* Object hash function, ripped off from stralloc.c.
*/
static int ObjHash(s)
char * s;
{
if (!obj_table)
init_otable();
return hashstr(s, 100, OTABLE_SIZE);
}
/*
* Looks for obj in table, moves it to head.
*/
static int obj_searches = 0, obj_probes = 0, objs_found = 0;
static struct object * find_obj_n(s)
char * s;
{
struct object * curr, *prev;
int h = ObjHash(s);
curr = obj_table[h];
prev = 0;
obj_searches++;
while (curr) {
obj_probes++;
if (!strcmp(curr->name, s)) { /* found it */
if (prev) { /* not at head of list */
prev->next_hash = curr->next_hash;
curr->next_hash = obj_table[h];
obj_table[h] = curr;
}
objs_found++;
return(curr); /* pointer to object */
}
prev = curr;
curr = curr->next_hash;
}
return(0); /* not found */
}
/*
* Add an object to the table - can't have duplicate names.
*/
static int objs_in_table = 0;
void enter_object_hash(ob)
struct object * ob;
{
struct object * s;
int h = ObjHash(ob->name);
s = find_obj_n(ob->name);
if (s) {
if (s != ob)
fatal("Duplicate object \"%s\" in object hash table",
ob->name);
else
fatal("Entering object \"%s\" twice in object table",
ob->name);
}
if (ob->next_hash)
fatal("Object \"%s\" not found in object table but next link not null",
ob->name);
ob->next_hash = obj_table[h];
obj_table[h] = ob;
objs_in_table++;
return;
}
/*
* Remove an object from the table - generally called when it
* is removed from the next_all list - i.e. in destruct.
*/
void remove_object_hash(ob)
struct object *ob;
{
struct object * s;
int h = ObjHash(ob->name);
s = find_obj_n(ob->name);
if (s != ob)
fatal("Remove object \"%s\": found a different object!",
ob->name);
obj_table[h] = ob->next_hash;
ob->next_hash = 0;
objs_in_table--;
return;
}
/*
* Lookup an object in the hash table; if it isn't there, return null.
* This is only different to find_object_n in that it collects different
* stats; more finds are actually done than the user ever asks for.
*/
static int user_obj_lookups = 0, user_obj_found = 0;
struct object * lookup_object_hash(s)
char * s;
{
struct object * ob = find_obj_n(s);
user_obj_lookups++;
if (ob) user_obj_found++;
return(ob);
}
/*
* Print stats, returns the total size of the object table. All objects
* are in table, so their size is included as well.
*/
static char sbuf[100];
int show_otable_status(verbose)
int verbose;
{
if (verbose) {
add_message("\nObject name hash table status:\n");
add_message("------------------------------\n");
sprintf(sbuf, "%.2f", objs_in_table / (float) OTABLE_SIZE);
add_message("Average hash chain length %s\n", sbuf);
sprintf(sbuf, "%.2f", (float)obj_probes / obj_searches);
add_message("Searches/average search length %d (%s)\n",
obj_searches, sbuf);
add_message("External lookups succeeded (succeed) %d (%d)\n",
user_obj_lookups, user_obj_found);
}
add_message("hash table overhead\t\t\t %8d\n",
OTABLE_SIZE * sizeof(struct object *));
return (OTABLE_SIZE * sizeof(struct object *) +
objs_in_table * sizeof(struct object));
}