📄 00000016.htm
字号:
for (ptr = key, i = 1; c = *ptr++; i++) <BR> hval += c * i; /* ascii char times its 1-based index */ <BR> return(hval % db->nhash); <BR>} <BR>程序16.9 _db_hash函数 <BR> _db_find调用的下一个函数是_db_readptr(程序16.10)。这个函数能够读取 <BR>以下三种不同的链指针中的任意一种:(1)索引文件最开始的空闲链表指针。( <BR>2)Hash表中指向Hash链的第一条索引记录的指针。(3)每条索引记录头的指向下 <BR>一条记录的指针(这里的索引记录既可以处于一条Hash链表中,也可以处于空闲链 <BR>表中)。这个函数的调用者应做好必要的加锁,此函数不进行任何加锁。 <BR>#include "db.h" <BR>/* Read a chain ptr field from anywhere in the index file: <BR> * the free list pointer, a hash table chain ptr, or an <BR> * index record chain ptr. */ <BR>off_t <BR>_db_readptr(DB *db, off_t offset) <BR>{ <BR> char asciiptr[PTR_SZ + 1]; <BR> if (lseek(db->idxfd, offset, SEEK_SET) == -1) <BR> err_dump("lseek error to ptr field"); <BR> if (read(db->idxfd, asciiptr, PTR_SZ) != PTR_SZ) <BR> err_dump("read error of ptr field"); <BR> asciiptr[PTR_SZ] = 0; /* null terminate */ <BR> return(atol(asciiptr)); <BR>} <BR>程序16.10 _db_readptr函数 <BR> _db_find中的while循环通过调用_db_readidx来读取各条索引记录。_db_rea <BR>didx(程序16.11)是一个较长的函数,这个函数读取索引记录,并将索引记录的 <BR>信息存储到适当的字段中。 <BR>#include "db.h" <BR>#include <sys/uio.h> /* struct iovec */ <BR>/* Read the next index record. We start at the specified offset in <BR> * the index file. We read the index record into db->idxbuf and <BR> * replace the separators with null bytes. If all is OK we set <BR> * db->datoff and db->datlen to the offset and length of the <BR> * corresponding data record in the data file. */ <BR>off_t <BR>_db_readidx(DB *db, off_t offset) <BR>{ <BR> int i; <BR> char *ptr1, *ptr2; <BR> char asciiptr[PTR_SZ + 1], asciilen[IDXLEN_SZ + 1]; <BR> struct iovec iov[2]; <BR> /* Position index file and record the offset. db_nextrec() <BR> calls us with offset==0, meaning read from current offset. <BR> We still need to call lseek() to record the current offset. */ <BR> if ( (db->idxoff = lseek(db->idxfd, offset, <BR> offset == 0 ? SEEK_CUR : SEEK_SET)) == -1) <BR> err_dump("lseek error"); <BR> /* Read the ascii chain ptr and the ascii length at <BR> the front of the index record. This tells us the <BR> remaining size of the index record. */ <BR> iov[0].iov_base = asciiptr; <BR> iov[0].iov_len = PTR_SZ; <BR> iov[1].iov_base = asciilen; <BR> iov[1].iov_len = IDXLEN_SZ; <BR> if ( (i = readv(db->idxfd, &iov[0], 2)) != PTR_SZ + IDXLEN_SZ) { <BR> if (i == 0 && offset == 0) <BR> return(-1); /* EOF for db_nextrec() */ <BR> err_dump("readv error of index record"); <BR> } <BR> asciiptr[PTR_SZ] = 0; /* null terminate */ <BR> db->ptrval = atol(asciiptr); /* offset of next key in chain */ <BR> /* this is our return value; always >= 0 */ <BR> asciilen[IDXLEN_SZ] = 0; /* null terminate */ <BR> if ( (db->idxlen = atoi(asciilen)) < IDXLEN_MIN || <BR> db->idxlen > IDXLEN_MAX) <BR> err_dump("invalid length"); <BR> /* Now read the actual index record. We read it into the key <BR> buffer that we malloced when we opened the database. */ <BR> if ( (i = read(db->idxfd, db->idxbuf, db->idxlen)) != db->idxlen) <BR> err_dump("read error of indexc record"); <BR> if (db->idxbuf[db->idxlen-1] != '\n') <BR> err_dump("missing newline"); /* sanity checks */ <BR> db->idxbuf[db->idxlen-1] = 0; /* replace newline with null */ <BR> /* Find the separators in the index record */ <BR> if ( (ptr1 = strchr(db->idxbuf, SEP)) == NULL) <BR> err_dump("missing first separator"); <BR> *ptr1++ = 0; /* replace SEP with null */ <BR> if ( (ptr2 = strchr(ptr1, SEP)) == NULL) <BR> err_dump("missing second separator"); <BR> *ptr2++ = 0; /* replace SEP with null */ <BR> if (strchr(ptr2, SEP) != NULL) <BR> asciiptr[PTR_SZ] = 0; /* null terminate */ <BR> db->ptrval = atol(asciiptr); /* offset of next key in chain */ <BR> /* this is our return value; always >= 0 */ <BR> asciilen[IDXLEN_SZ] = 0; /* null terminate */ <BR> if ( (db->idxlen = atoi(asciilen)) < IDXLEN_MIN || <BR> db->idxlen > IDXLEN_MAX) <BR> err_dump("invalid length"); <BR> /* Now read the actual index record. We read it into the key <BR> buffer that we malloced when we opened the database. */ <BR> if ( (i = read(db->idxfd, db->idxbuf, db->idxlen)) != db->idxlen) <BR> err_dump("read error of indexc record"); <BR> if (db->idxbuf[db->idxlen-1] != '\n') <BR> err_dump("missing newline"); /* sanity checks */ <BR> db->idxbuf[db->idxlen-1] = 0; /* replace newline with null */ <BR> /* Find the separators in the index record */ <BR> if ( (ptr1 = strchr(db->idxbuf, SEP)) == NULL) <BR> err_dump("missing first separator"); <BR> *ptr1++ = 0; /* replace SEP with null */ <BR> if ( (ptr2 = strchr(ptr1, SEP)) == NULL) <BR> err_dump("missing second separator"); <BR> *ptr2++ = 0; /* replace SEP with null */ <BR> if (strchr(ptr2, SEP) != NULL) <BR> err_dump("too many separators"); <BR> /* Get the starting offset and length of the data record */ <BR> if ( (db->datoff = atol(ptr1)) < 0) <BR> err_dump("starting offset < 0"); <BR> if ( (db->datlen = atol(ptr2)) <= 0 || db->datlen > DATLEN_MAX) <BR> err_dump("invalid length"); <BR> return(db->ptrval); /* return offset of next key in chain */ <BR>} <BR>程序16.11 _db_readidx函数 <BR> 我们调用readv来读取索引记录开始处的两个固定长度的字段:指向下一条索 <BR>引记录的链指针和索引记录剩下的不定长部分的长度。然后,索引记录的剩下的部 <BR>分被读入:主键、数据记录的偏移量和数据记录的长度。我们并不读数据记录,这 <BR>由调用者自己完成。例如,在db_fetch中,在_db_find按主键找到索引记录前是不 <BR>去读取数据记录的。 <BR> 下面我们回到db_fetch。如果_db_find找到了索引记录,我们调用_db_readd <BR>at来读取对应的数据记录。这是一个很简单的函数(见程序16.12)。 <BR>#include "db.h" <BR>/* Read the current data record into the data buffer. <BR> * Return a pointer to the null-terminated data buffer. */ <BR>char * <BR>_db_readdat(DB *db) <BR>{ <BR> if (lseek(db->datfd, db->datoff, SEEK_SET) == -1) <BR> err_dump("lseek error"); <BR> if (read(db->datfd, db->datbuf, db->datlen) != db->datlen) <BR> err_dump("read error"); <BR> if (db->datbuf[db->datlen - 1] != '\n') /* sanity check */ <BR> err_dump("missing newline"); <BR> db->datbuf[db->datlen - 1] = 0; /* replace newline with null */ <BR> return(db->datbuf); /* return pointer to data record */ <BR>} <BR>程序16.12 _de_readdat函数 <BR> 我们从db_fetch开始,现在已经读取了索引记录和对应的数据记录。注意到, <BR>我们只在_db_find中加了一个读
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -