tmain() { Dt_t* dt; Obj_t *o, proto; long i, k, count, n; for(i = 0; i < N_OBJ; i = k) { for(k = i; k < i+R_OBJ && k < N_OBJ; ++k) { Obj[k].key = i; Obj[k].ord = k; } } for(k = 0; k < 2; ++k) { if(!(dt = dtopen(&Disc, k == 0 ? Dtrhbag : Dtobag)) ) terror("Opening dictionary"); dtcustomize(dt, DT_SHARE, 1); /* turn on sharing */ for(i = 0; i < N_OBJ; ++i) { if(dtinsert(dt, Obj+i) != Obj+i) terror("Insert %d,%d", Obj[i].key, Obj[i].ord); if(i > 0 && (i%N_CHK) == 0) if((count = dtsize(dt)) != i+1) terror("Bad size %d (need %d)", count, i+1); } count = n = 0; /* count the group of elements with key == 0 */ for(o = (Obj_t*)dtflatten(dt); o; o = (Obj_t*)dtlink(dt,o), count += 1) if(o->key == 0) n += 1; if(count != N_OBJ || n != R_OBJ) terror("flatten %s: count=%d(need=%d) n=%d(need=%d)", k == 0 ? "bag" : "obag", count, N_OBJ, n, R_OBJ); /* delete a bunch of objects */ for(n = 0, i = 0; i < N_OBJ; i += R_OBJ, n += 1) if(!dtdelete(dt, Obj+i)) terror("delete %s: i=%d", k == 0 ? "bag" : "obag", i); count = 0; /* count the left over */ for(o = (Obj_t*)dtflatten(dt); o; o = (Obj_t*)dtlink(dt,o)) count += 1; if(count != N_OBJ-n) terror("%s wrong count %d", k == 0 ? "bag" : "obag", count); dtclose(dt); } texit(0); }
// Open a shared dictionary. static Dt_t *opendictionary(Mydisc_t *dc) { // Discipline for objects identified by their decimal values. dc->disc.key = DTOFFSET(Obj_t, value); dc->disc.size = sizeof(int); dc->disc.link = -1; dc->disc.makef = NULL; dc->disc.freef = NULL; dc->disc.comparf = mycompare; dc->disc.hashf = myhash; dc->disc.memoryf = mymemory; dc->disc.eventf = NULL; Dt_t *dt = dtopen(&dc->disc, Dtrhset); // open dictionary with hash-trie if (!dt) terror("Can't open dictionary"); dtcustomize(dt, DT_SHARE, 1); // turn on concurrent access mode return dt; }
tmain() { Dt_t *dt; Dtstat_t stat; Obj_t *p, *o, *obj, proto; char *name; long i, k, mid, n_mid, n_obj, meth; /* construct repetitive objects */ for(i = 0; i < N_OBJ; i += R_OBJ) { for(k = 0; k < R_OBJ; ++k) { Obj[i+k].key = i; Obj[i+k].ord = k; } } for(meth = 0; meth < 4; ++meth) { switch(meth) { case 0: name = "Dtobag"; if(!(dt = dtopen(&Disc, Dtobag)) ) terror("%s: Can't open dictionary", name); break; case 1: name = "Dtbag"; if(!(dt = dtopen(&Disc, Dtbag)) ) terror("%s: Can't open dictionary", name); break; case 2: name = "Dtrhbag"; if(!(dt = dtopen(&Disc, Dtrhbag)) ) terror("%s: Can't open dictionary", name); break; case 3: name = "Dtlist"; if(!(dt = dtopen(&Disc, Dtlist)) ) terror("%s: Can't open dictionary", name); break; default: terror("Unknown storage method"); break; } tinfo("Testing method %s:", name); dtcustomize(dt, DT_SHARE, 1); /* make it more interesting */ /* add all objects into dictionary */ for(k = 0; k < R_OBJ; ++k) for(i = 0; i < N_OBJ/R_OBJ; ++i) { obj = Obj + i*R_OBJ + k; o = (meth == 3 || i%2 == 0) ? dtappend(dt,obj) : dtinsert(dt,obj); if(o != obj) terror("%s: dtappend (key=%d,ord=%d) failed", name, obj->key, obj->ord); } mid = ((N_OBJ/R_OBJ)/2) * R_OBJ; /* key for middle group */ proto.key = mid; proto.ord = -1; if(meth == 3) /* testing ATMOST/ATLEAST for Dtlist */ { /* note that dtappend() was used to keep objects in order of insertion */ if(!(o = dtatmost(dt, &proto)) ) terror("%s: dtatmost (key=%d) failed", name, mid); if(o->ord != 0) terror("%s: dtatmost (key=%d) but ord=%d > 0", name, o->key, o->ord); if(!(o = dtatleast(dt, &proto)) ) terror("%s: dtatleast (key=%d) failed", name, mid); if(o->ord != R_OBJ-1) terror("%s: dtatleast (key=%d) but ord=%d > 0", name, o->key, o->ord); n_obj = 0; /* test ordering */ for(p = NIL(Obj_t*), o = dtfirst(dt); o; p = o, o = dtnext(dt,o) ) { n_obj += 1; if(p && p->ord > o->ord) terror("%s: objects not ordered correctly p=%d > o=%d", name, p->ord, o->ord); } if(n_obj != N_OBJ) terror("%s: Bad object count %d != %d", n_obj, N_OBJ); } if(meth == 0) /* testing ordering properties of Dtobag */ { n_obj = 0; /* test atmost/next */ for(o = dtatmost(dt, &proto); o; o = dtnext(dt,o) ) { if(o->key == mid) n_obj += 1; else break; } if(n_obj != R_OBJ) terror("%s: dtatmost/dtnext count n_obj=%d != %d", name, n_obj, R_OBJ); n_obj = 0; /* test atleast/prev */ for(o = dtatleast(dt, &proto); o; o = dtprev(dt,o) ) { if(o->key == mid) n_obj += 1; else break; } if(n_obj != R_OBJ) terror("%s: dtatleast/dtprev count n_obj=%d != %d", name, n_obj, R_OBJ); n_obj = 0; /* test linear order */ for(p = NIL(Obj_t*), o = dtfirst(dt); o; p = o, o = dtnext(dt,o) ) { n_obj += 1; if(p && p->key > o->key) terror("%s: objects not ordered correctly p=%d > o=%d", name, p->key, o->key); } if(n_obj != N_OBJ) terror("%s: Bad object count %d != %d", n_obj, N_OBJ); } n_mid = n_obj = 0; /* walk forward and count objects */ for(o = dtfirst(dt); o; o = dtnext(dt,o)) { n_obj += 1; if(o->key == mid) n_mid += 1; } if(n_obj != N_OBJ) terror("%s: Walk forward n_obj=%d != %d", name, n_obj, N_OBJ); if(n_mid != R_OBJ) terror("%s: Walk forward n_mid=%d != %d", name, n_mid, R_OBJ); n_mid = n_obj = 0; /* walk backward and count objects */ for(o = dtlast(dt); o; o = dtprev(dt,o)) { n_obj += 1; if(o->key == mid) n_mid += 1; } if(n_obj != N_OBJ) terror("%s: Walk backward n_obj=%d != %d", name, n_obj, N_OBJ); if(n_mid != R_OBJ) terror("%s: Walk backward n_mid=%d != %d", name, n_mid, R_OBJ); n_mid = n_obj = 0; /* walk flattened list and count objects */ for(o = (Obj_t*)dtflatten(dt); o; o = (Obj_t*)dtlink(dt,o) ) { n_obj += 1; if(o->key == mid) n_mid += 1; } if(n_obj != N_OBJ) terror("%s: Walk flattened list n_obj=%d != %d", name, n_obj, N_OBJ); if(n_mid != R_OBJ) terror("%s: Walk flattened list n_mid=%d != %d", name, n_mid, R_OBJ); n_mid = 0; /* delete a bunch of objects */ for(i = 0; i < N_OBJ-1; i += R_OBJ) { obj = Obj + i + R_OBJ/2; /* use the one in the middle of group */ if((o = dtremove(dt, obj)) == obj ) n_mid += 1; else terror("%s: dtremove (key=%d,ord=%d) wrongly yielded (key=%d,ord=%d)", name, obj->key, obj->ord, o->key, o->ord); if((o = dtremove(dt, obj)) != NIL(Obj_t*) ) terror("%s: dtremove (key=%d,ord=%d) wrongly yielded (key=%d,ord=%d)", name, obj->key, obj->ord, o->key, o->ord); if((o = dtdelete(dt, obj)) != NIL(Obj_t*) ) n_mid += 1; else terror("%s: dtdelete matching object to (key=%d,ord=%d) failed", name, obj->key, obj->ord); }