cdb.c
author "Tomas Zeman <tomas.zeman@sun.com>"
Fri, 19 Oct 2007 11:01:15 +0200
changeset 0 eeadadee24f6
permissions -rw-r--r--
Imported cdb-0.75
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     1
/* Public domain. */
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     2
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     3
#include <sys/types.h>
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     4
#include <sys/stat.h>
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     5
#include <sys/mman.h>
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     6
#include "readwrite.h"
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     7
#include "error.h"
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     8
#include "seek.h"
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     9
#include "byte.h"
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    10
#include "cdb.h"
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    11
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    12
void cdb_free(struct cdb *c)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    13
{
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    14
  if (c->map) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    15
    munmap(c->map,c->size);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    16
    c->map = 0;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    17
  }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    18
}
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    19
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    20
void cdb_findstart(struct cdb *c)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    21
{
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    22
  c->loop = 0;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    23
}
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    24
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    25
void cdb_init(struct cdb *c,int fd)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    26
{
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    27
  struct stat st;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    28
  char *x;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    29
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    30
  cdb_free(c);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    31
  cdb_findstart(c);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    32
  c->fd = fd;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    33
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    34
  if (fstat(fd,&st) == 0)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    35
    if (st.st_size <= 0xffffffff) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    36
      x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    37
      if (x + 1) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    38
	c->size = st.st_size;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    39
	c->map = x;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    40
      }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    41
    }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    42
}
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    43
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    44
int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    45
{
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    46
  if (c->map) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    47
    if ((pos > c->size) || (c->size - pos < len)) goto FORMAT;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    48
    byte_copy(buf,len,c->map + pos);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    49
  }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    50
  else {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    51
    if (seek_set(c->fd,pos) == -1) return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    52
    while (len > 0) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    53
      int r;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    54
      do
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    55
        r = read(c->fd,buf,len);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    56
      while ((r == -1) && (errno == error_intr));
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    57
      if (r == -1) return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    58
      if (r == 0) goto FORMAT;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    59
      buf += r;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    60
      len -= r;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    61
    }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    62
  }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    63
  return 0;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    64
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    65
  FORMAT:
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    66
  errno = error_proto;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    67
  return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    68
}
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    69
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    70
static int match(struct cdb *c,char *key,unsigned int len,uint32 pos)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    71
{
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    72
  char buf[32];
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    73
  int n;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    74
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    75
  while (len > 0) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    76
    n = sizeof buf;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    77
    if (n > len) n = len;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    78
    if (cdb_read(c,buf,n,pos) == -1) return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    79
    if (byte_diff(buf,n,key)) return 0;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    80
    pos += n;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    81
    key += n;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    82
    len -= n;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    83
  }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    84
  return 1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    85
}
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    86
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    87
int cdb_findnext(struct cdb *c,char *key,unsigned int len)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    88
{
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    89
  char buf[8];
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    90
  uint32 pos;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    91
  uint32 u;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    92
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    93
  if (!c->loop) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    94
    u = cdb_hash(key,len);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    95
    if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    96
    uint32_unpack(buf + 4,&c->hslots);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    97
    if (!c->hslots) return 0;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    98
    uint32_unpack(buf,&c->hpos);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    99
    c->khash = u;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   100
    u >>= 8;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   101
    u %= c->hslots;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   102
    u <<= 3;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   103
    c->kpos = c->hpos + u;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   104
  }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   105
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   106
  while (c->loop < c->hslots) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   107
    if (cdb_read(c,buf,8,c->kpos) == -1) return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   108
    uint32_unpack(buf + 4,&pos);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   109
    if (!pos) return 0;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   110
    c->loop += 1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   111
    c->kpos += 8;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   112
    if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   113
    uint32_unpack(buf,&u);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   114
    if (u == c->khash) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   115
      if (cdb_read(c,buf,8,pos) == -1) return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   116
      uint32_unpack(buf,&u);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   117
      if (u == len)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   118
	switch(match(c,key,len,pos + 8)) {
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   119
	  case -1:
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   120
	    return -1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   121
	  case 1:
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   122
	    uint32_unpack(buf + 4,&c->dlen);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   123
	    c->dpos = pos + 8 + len;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   124
	    return 1;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   125
	}
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   126
    }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   127
  }
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   128
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   129
  return 0;
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   130
}
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   131
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   132
int cdb_find(struct cdb *c,char *key,unsigned int len)
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   133
{
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   134
  cdb_findstart(c);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   135
  return cdb_findnext(c,key,len);
eeadadee24f6 Imported cdb-0.75
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   136
}