enum {
Dptr, /* pointer to database file */
Cptr, /* pointer to first chain entry */
Cptr1, /* pointer to second chain entry */
};
/*
* generate a hash value for an ascii string (val) given
* a hash table length (hlen)
*/
ulong
ndbhash(char *vp, int hlen)
{
ulong hash;
uchar *val = (uchar*)vp;
/*
* read a hash file with buffering
*/
static uchar*
hfread(Ndbhf *hf, long off, int len)
{
if(off < hf->off || off + len > hf->off + hf->len){
if(seek(hf->fd, off, 0) < 0
|| (hf->len = read(hf->fd, hf->buf, sizeof(hf->buf))) < len){
hf->off = -1;
return 0;
}
hf->off = off;
}
return &hf->buf[off-hf->off];
}
/*
* return an opened hash file if one exists for the
* attribute and if it is current vis-a-vis the data
* base file
*/
static Ndbhf*
hfopen(Ndb *db, char *attr)
{
Ndbhf *hf;
char buf[sizeof(hf->attr)+sizeof(db->file)+2];
uchar *p;
Dir *d;
/* try opening the data base if it's closed */
if(db->mtime==0 && ndbreopen(db) < 0)
return 0;
/* if the database has changed, throw out hash files and reopen db */
if((d = dirfstat(Bfildes(&db->b))) == nil || db->qid.path != d->qid.path
|| db->qid.vers != d->qid.vers){
if(ndbreopen(db) < 0){
free(d);
return 0;
}
}
free(d);
if(db->nohash)
return 0;
/* see if a hash file exists for this attribute */
for(hf = db->hf; hf; hf= hf->next){
if(strcmp(hf->attr, attr) == 0)
return hf;
}
/* create a new one */
hf = (Ndbhf*)malloc(sizeof(Ndbhf));
if(hf == 0)
return 0;
memset(hf, 0, sizeof(Ndbhf));