cdb_seek.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:3k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* old interface for reading cdb file
  2.  *
  3.  * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
  4.  * Public domain.
  5.  */
  6. #include "common/setup_before.h"
  7. #include <stdio.h>
  8. #include "cdb_int.h"
  9. #include "common/setup_after.h"
  10. #ifndef SEEK_SET
  11. # define SEEK_SET 0
  12. #endif
  13. /* read a chunk from file, ignoring interrupts (EINTR) */
  14. int
  15. cdb_bread(FILE *fd, void *buf, int len)
  16. {
  17.   int l;
  18.   while(len > 0) {
  19.     do l = fread(buf, 1, len, fd);
  20.     while(l < 0 && errno == EINTR);
  21.     if (l <= 0) {
  22.       if (!l)
  23.         errno = EIO;
  24.       return -1;
  25.     }
  26.     buf = (char*)buf + l;
  27.     len -= l;
  28.   }
  29.   return 0;
  30. }
  31. /* find a given key in cdb file, seek a file pointer to it's value and
  32.    place data length to *dlenp. */
  33. int
  34. cdb_seek(FILE *fd, const void *key, unsigned klen, unsigned *dlenp)
  35. {
  36.   unsigned htstart; /* hash table start position */
  37.   unsigned htsize; /* number of elements in a hash table */
  38.   unsigned httodo; /* hash table elements left to look */
  39.   unsigned hti; /* hash table index */
  40.   unsigned pos; /* position in a file */
  41.   unsigned hval; /* key's hash value */
  42.   unsigned char rbuf[64]; /* read buffer */
  43.   int needseek = 1; /* if we should seek to a hash slot */
  44.   hval = cdb_hash(key, klen);
  45.   pos = (hval & 0xff) << 3; /* position in TOC */
  46.   /* read the hash table parameters */
  47.   if (fseek(fd, pos, SEEK_SET) || cdb_bread(fd, rbuf, 8) < 0)
  48.     return -1;
  49.   if ((htsize = cdb_unpack(rbuf + 4)) == 0)
  50.     return 0;
  51.   hti = (hval >> 8) % htsize; /* start position in hash table */
  52.   httodo = htsize;
  53.   htstart = cdb_unpack(rbuf);
  54.   for(;;) {
  55.     if (needseek && fseek(fd, htstart + (hti << 3), SEEK_SET))
  56.       return -1;
  57.     if (cdb_bread(fd, rbuf, 8) < 0)
  58.       return -1;
  59.     if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */
  60.       return 0;
  61.     if (cdb_unpack(rbuf) != hval) /* hash value not matched */
  62.       needseek = 0;
  63.     else { /* hash value matched */
  64.       if (fseek(fd, pos, SEEK_SET) || cdb_bread(fd, rbuf, 8) < 0)
  65. return -1;
  66.       if (cdb_unpack(rbuf) == klen) { /* key length matches */
  67. /* read the key from file and compare with wanted */
  68. unsigned l = klen, c;
  69. const char *k = (const char*)key;
  70. if (*dlenp)
  71.   *dlenp = cdb_unpack(rbuf + 4); /* save value length */
  72. for(;;) {
  73.   if (!l) /* the whole key read and matches, return */
  74.     return 1;
  75.   c = l > sizeof(rbuf) ? sizeof(rbuf) : l;
  76.   if (cdb_bread(fd, rbuf, c) < 0)
  77.     return -1;
  78.   if (memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */
  79.     break;
  80.   k += c; l -= c;
  81. }
  82.       }
  83.       needseek = 1; /* we're looked to other place, should seek back */
  84.     }
  85.     if (!--httodo)
  86.       return 0;
  87.     if (++hti == htsize) {
  88.       hti = 0;
  89.       needseek = 1;
  90.     }
  91.   }
  92. }