Permalink
Browse files

Add some error checking to see whether we succeeded building hash table

  • Loading branch information...
1 parent bf203db commit d23053053481ee35145bb1177475597d0bbd9285 @markflorisson markflorisson committed Apr 8, 2013
Showing with 37 additions and 10 deletions.
  1. +16 −7 deps/pyextensibletype/extensibletype/methodtable.pyx
  2. +21 −3 deps/pyextensibletype/include/perfecthash.h
View
23 deps/pyextensibletype/extensibletype/methodtable.pyx
@@ -19,6 +19,11 @@ def roundup(x):
x += 1
return x
+class HashingError(Exception):
+ """
+ Raised when we can't create a perfect hash-based function table.
+ """
+
cdef PyCustomSlots_Table *allocate_hash_table(uint16_t size) except NULL:
cdef PyCustomSlots_Table *table
@@ -70,7 +75,7 @@ cdef class PerfectHashMethodTable(object):
cdef uint16_t *displacements
cdef Hasher hasher
- cdef object id_to_signature, signatures
+ cdef object id_to_signature, signatures, fs, gs
def __init__(self, hasher):
self.hasher = hasher
@@ -90,6 +95,8 @@ cdef class PerfectHashMethodTable(object):
intern.global_intern_initialize()
# Initialize hash table entries, build hash ids
+ assert len(ids) == len(flags) == len(funcs)
+
for i, (signature, flag, func) in enumerate(zip(ids, flags, funcs)):
id = self.hasher.hash_signature(signature)
@@ -103,10 +110,12 @@ cdef class PerfectHashMethodTable(object):
self.table.n - n)
# Perfect hash our table
- PyCustomSlots_PerfectHash(self.table, &hashes[0])
+ if PyCustomSlots_PerfectHash(self.table, &hashes[0]) < 0:
+ # TODO: sensible error messages
+ raise HashingError("Unable to create perfect hash table")
- for signature in ids:
- assert self.find_method(signature)
+ for i, signature in enumerate(ids):
+ assert self.find_method(signature), (i, signature)
# For debugging
self.signatures = ids
@@ -118,8 +127,8 @@ cdef class PerfectHashMethodTable(object):
"""
cdef uint64_t prehash = intern.global_intern(make_bytes(signature))
- cdef int idx = (((prehash >> self.table.r) & self.table.m_f) ^
- self.displacements[prehash & self.table.m_g])
+ cdef uint64_t idx = (((prehash >> self.table.r) & self.table.m_f) ^
+ self.displacements[prehash & self.table.m_g])
assert 0 <= idx < self.size
@@ -135,7 +144,7 @@ cdef class PerfectHashMethodTable(object):
id = self.table.entries[i].id
ptr = <uintptr_t> self.table.entries[i].ptr
sig = self.id_to_signature.get(id, "<empty>")
- s = " id: %20d funcptr: %20d signature: %s" % (id, ptr, sig)
+ s = " id: 0x%-16x funcptr: %20d signature: %s" % (id, ptr, sig)
buf.append(s)
buf.append(")")
View
24 deps/pyextensibletype/include/perfecthash.h
@@ -133,6 +133,7 @@ int _PyCustomSlots_FindDisplacements(PyCustomSlots_Table *table,
}
int PyCustomSlots_PerfectHash(PyCustomSlots_Table *table, uint64_t *hashes) {
+ int result;
uint16_t bin, j;
uint8_t binsize;
uint16_t i, n = table->n, b = table->b;
@@ -145,10 +146,13 @@ int PyCustomSlots_PerfectHash(PyCustomSlots_Table *table, uint64_t *hashes) {
uint8_t number_of_bins_by_size[BIN_LIMIT];
PyCustomSlots_Entry *entries_copy = malloc(sizeof(PyCustomSlots_Entry) * n);
+ if (!bins || !binsizes || !p || !taken || !entries_copy)
+ goto error;
+
for (i = 0; i != n; ++i) {
entries_copy[i] = table->entries[i];
}
-
+
/* Bin the n hashes into b bins based on the g hash. Also count the
number of bins of each size. */
for (bin = 0; bin != b; ++bin) {
@@ -163,7 +167,7 @@ int PyCustomSlots_PerfectHash(PyCustomSlots_Table *table, uint64_t *hashes) {
binsize = ++binsizes[bin];
if (binsize == BIN_LIMIT) {
printf("ERROR 1\n");
- return -1;
+ goto error;
}
bins[BIN_LIMIT * bin + binsize - 1] = i;
number_of_bins_by_size[binsize - 1]--;
@@ -187,12 +191,26 @@ int PyCustomSlots_PerfectHash(PyCustomSlots_Table *table, uint64_t *hashes) {
}
}
+ if (retcode != 0) {
+ printf("no suitable table found\n");
+ goto error;
+ }
+
+ result = 0;
+ goto cleanup;
+
+error:
+
+ result = -1;
+
+cleanup:
+
/*TODO does not free on error... */
free(bins);
free(binsizes);
free(p);
free(taken);
free(entries_copy);
- return 0;
+ return result;
}

0 comments on commit d230530

Please sign in to comment.