int wr_equal_ptr_primitives(glb* g, gint a, gint b, int uniquestrflag) { gint t1,t2; gint l1,l2,ol; char* s1; char* s2; //printf("equal_ptr_primitives called with %d and %d\n",a,b); switch(a&NORMALPTRMASK) { // last 3 bits case FULLINTBITSV0: case FULLINTBITSV1: if (isfullint(b) && (dbfetch(g->db,decode_fullint_offset(a))==dbfetch(g->db,decode_fullint_offset(b))) ) return 1; else return 0; case FULLDOUBLEBITS: if (isfulldouble(b) && wg_decode_double(g->db,a)==wg_decode_double(g->db,b) ) return 1; else return 0; case SHORTSTRBITS: //printf("shortstrbits \n"); if (isshortstr(b) && !memcmp((void*)(offsettoptr(g->db,decode_shortstr_offset(a))), (void*)(offsettoptr(g->db,decode_shortstr_offset(b))), SHORTSTR_SIZE)) return 1; else return 0; case LONGSTRBITS: if (uniquestrflag) { if (a==b) return 1; else return 0; } else { t1=wg_get_encoded_type(g->db,a); t2=wg_get_encoded_type(g->db,b); if (t1!=t2) return 0; l1=wg_decode_unistr_lang_len(g->db,a,t1); l2=wg_decode_unistr_lang_len(g->db,b,t2); if (11!=l2) return 0; ol=l1; l1=wg_decode_unistr_len(g->db,a,t1); l2=wg_decode_unistr_len(g->db,b,t2); if (11!=l2) return 0; s1=wg_decode_unistr_lang(g->db,a,t1); s2=wg_decode_unistr_lang(g->db,b,t2); if (s1!=s2 && (s1==NULL || s2==NULL || memcmp(s1,s2,ol))) return 0; s1=wg_decode_unistr(g->db,a,t1); s2=wg_decode_unistr(g->db,b,t2); if (s1!=s2 && (s1==NULL || s2==NULL || memcmp(s1,s2,l1))) return 0; return 1; } } return 0; }
gint wg_remove_from_strhash(void* db, gint longstr) { db_memsegment_header* dbh = dbmemsegh(db); gint type; gint* extrastrptr; char* extrastr; char* data; gint length; gint hash; gint chainoffset; gint hashchain; gint nextchain; gint offset; gint* objptr; gint fldval; gint objsize; gint strsize; gint* typeptr; //printf("wg_remove_from_strhash called on %d\n",longstr); //wg_debug_print_value(db,longstr); //printf("\n\n"); offset=decode_longstr_offset(longstr); objptr=(gint*) offsettoptr(db,offset); // get string data elements //type=objptr=offsettoptr(db,decode_longstr_offset(data)); extrastrptr=(gint *) (((char*)(objptr))+(LONGSTR_EXTRASTR_POS*sizeof(gint))); fldval=*extrastrptr; if (fldval==0) extrastr=NULL; else extrastr=wg_decode_str(db,fldval); data=((char*)(objptr))+(LONGSTR_HEADER_GINTS*sizeof(gint)); objsize=getusedobjectsize(*objptr); strsize=objsize-(((*(objptr+LONGSTR_META_POS))&LONGSTR_META_LENDIFMASK)>>LONGSTR_META_LENDIFSHFT); length=strsize; typeptr=(gint*)(((char*)(objptr))+(+LONGSTR_META_POS*sizeof(gint))); type=(*typeptr)&LONGSTR_META_TYPEMASK; //type=wg_get_encoded_type(db,longstr); // get hash of data elements and find the location in hashtable/chains hash=wg_hash_typedstr(db,data,extrastr,type,length); chainoffset=((dbh->strhash_area_header).arraystart)+(sizeof(gint)*hash); hashchain=dbfetch(db,chainoffset); while(hashchain!=0) { if (hashchain==longstr) { nextchain=dbfetch(db,decode_longstr_offset(hashchain)+(LONGSTR_HASHCHAIN_POS*sizeof(gint))); dbstore(db,chainoffset,nextchain); break; //return 0; } chainoffset=decode_longstr_offset(hashchain)+(LONGSTR_HASHCHAIN_POS*sizeof(gint)); hashchain=dbfetch(db,chainoffset); } //HEAP: this part is modified, there probably some bug, since ignoring the non-exists hash ptr, which is not caused by heap blob // show_consistency_error_nr(db,"string not found in hash during deletion, offset",offset); // return -1; return 0; }
/* * Remove an offset from the index hash. * * Returns 0 on success * Returns -1 on error. */ gint wg_idxhash_remove(void* db, db_hash_area_header *ha, char* data, gint length, gint offset) { wg_uint hash; gint bucket_offset, bucket; gint *next_offset, *reclist_offset; hash = hash_bytes(db, data, length, ha->arraylength); bucket_offset = (ha->arraystart)+(sizeof(gint) * hash); /* points to head */ /* Find the correct bucket. */ bucket = find_idxhash_bucket(db, data, length, &bucket_offset); if(!bucket) { return show_hash_error(db, "wg_idxhash_remove: Hash value not found."); } /* Remove the record offset from the list. */ reclist_offset = offsettoptr(db, bucket + HASHIDX_RECLIST_POS*sizeof(gint)); next_offset = reclist_offset; while(*next_offset) { gcell *rec_cell = (gcell *) offsettoptr(db, *next_offset); if(rec_cell->car == offset) { gint rec_offset = *next_offset; *next_offset = rec_cell->cdr; /* remove from list chain */ wg_free_listcell(db, rec_offset); /* free storage */ goto is_bucket_empty; } next_offset = &(rec_cell->cdr); } return show_hash_error(db, "wg_idxhash_remove: Offset not found"); is_bucket_empty: if(!(*reclist_offset)) { gint nextchain = dbfetch(db, bucket + HASHIDX_HASHCHAIN_POS*sizeof(gint)); dbstore(db, bucket_offset, nextchain); wg_free_object(db, &(dbmemsegh(db)->indexhash_area_header), bucket); } return 0; }
/* * Finds a matching bucket in hash chain. * chainoffset should point to the offset storing the chain head. * If the call is successful, it will point to the offset storing * the matching bucket. */ static gint find_idxhash_bucket(void *db, char *data, gint length, gint *chainoffset) { gint bucket = dbfetch(db, *chainoffset); while(bucket) { gint meta = dbfetch(db, bucket + HASHIDX_META_POS*sizeof(gint)); if(meta == length) { /* Currently, meta stores just size */ char *bucket_data = offsettoptr(db, bucket + \ HASHIDX_HEADER_SIZE*sizeof(gint)); if(!memcmp(bucket_data, data, length)) return bucket; } *chainoffset = bucket + HASHIDX_HASHCHAIN_POS*sizeof(gint); bucket = dbfetch(db, *chainoffset); } return 0; }
/* * Store a hash string and an offset to the index hash. * Based on longstr hash, with some simplifications. * * Returns 0 on success * Returns -1 on error. */ gint wg_idxhash_store(void* db, db_hash_area_header *ha, char* data, gint length, gint offset) { db_memsegment_header* dbh = dbmemsegh(db); wg_uint hash; gint head_offset, head, bucket; gint rec_head, rec_offset; gcell *rec_cell; hash = hash_bytes(db, data, length, ha->arraylength); head_offset = (ha->arraystart)+(sizeof(gint) * hash); head = dbfetch(db, head_offset); /* Traverse the hash chain to check if there is a matching * hash string already */ bucket = find_idxhash_bucket(db, data, length, &head_offset); if(!bucket) { size_t i; gint lengints, lenrest; char* dptr; /* Make a new bucket */ lengints = length / sizeof(gint); lenrest = length % sizeof(gint); if(lenrest) lengints++; bucket = wg_alloc_gints(db, &(dbh->indexhash_area_header), lengints + HASHIDX_HEADER_SIZE); if(!bucket) { return -1; } /* Copy the byte data */ dptr = (char *) (offsettoptr(db, bucket + HASHIDX_HEADER_SIZE*sizeof(gint))); memcpy(dptr, data, length); for(i=0;lenrest && i<sizeof(gint)-lenrest;i++) { *(dptr + length + i)=0; /* XXX: since we have the length, in meta, * this is possibly unnecessary. */ } /* Metadata */ dbstore(db, bucket + HASHIDX_META_POS*sizeof(gint), length); dbstore(db, bucket + HASHIDX_RECLIST_POS*sizeof(gint), 0); /* Prepend to hash chain */ dbstore(db, ((ha->arraystart)+(sizeof(gint) * hash)), bucket); dbstore(db, bucket + HASHIDX_HASHCHAIN_POS*sizeof(gint), head); } /* Add the record offset to the list. */ rec_head = dbfetch(db, bucket + HASHIDX_RECLIST_POS*sizeof(gint)); rec_offset = wg_alloc_fixlen_object(db, &(dbh->listcell_area_header)); rec_cell = (gcell *) offsettoptr(db, rec_offset); rec_cell->car = offset; rec_cell->cdr = rec_head; dbstore(db, bucket + HASHIDX_RECLIST_POS*sizeof(gint), rec_offset); return 0; }