You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cdb_init.c 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* $Id: cdb_init.c,v 1.12 2008-11-06 18:07:04 mjt Exp $
  2. * cdb_init, cdb_free and cdb_read routines
  3. *
  4. * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
  5. * Public domain.
  6. */
  7. #include "cdb.h"
  8. unsigned
  9. cdb_hash(const void *buf, unsigned len)
  10. {
  11. register const unsigned char *p = (const unsigned char *) buf;
  12. register const unsigned char *end = p + len;
  13. register unsigned hash = 5381; /* start value */
  14. while (p < end)
  15. hash = (hash + (hash << 5)) ^ *p++;
  16. return hash;
  17. }
  18. int cdb_init(struct cdb *cdbp, int fd)
  19. {
  20. struct stat st;
  21. unsigned char *mem;
  22. unsigned fsize, dend;
  23. #ifdef _WIN32
  24. HANDLE hFile, hMapping;
  25. #endif
  26. /* get file size */
  27. if (fstat(fd, &st) < 0)
  28. return -1;
  29. /* trivial sanity check: at least toc should be here */
  30. if (st.st_size < 2048)
  31. return errno = EPROTO, -1;
  32. fsize = (unsigned) (st.st_size & 0xffffffffu);
  33. /* memory-map file */
  34. #ifdef _WIN32
  35. hFile = (HANDLE) _get_osfhandle(fd);
  36. if (hFile == (HANDLE) -1)
  37. return -1;
  38. hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  39. if (!hMapping)
  40. return -1;
  41. mem = (unsigned char *) MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  42. CloseHandle(hMapping);
  43. if (!mem)
  44. return -1;
  45. #else
  46. mem = (unsigned char *) mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
  47. if (mem == MAP_FAILED)
  48. return -1;
  49. #endif /* _WIN32 */
  50. cdbp->cdb_fd = fd;
  51. cdbp->cdb_fsize = fsize;
  52. cdbp->cdb_mem = mem;
  53. cdbp->mtime = st.st_mtime;
  54. cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
  55. cdbp->cdb_kpos = cdbp->cdb_klen = 0;
  56. dend = cdb_unpack(mem);
  57. if (dend < 2048)
  58. dend = 2048;
  59. else if (dend >= fsize)
  60. dend = fsize;
  61. cdbp->cdb_dend = dend;
  62. return 0;
  63. }
  64. void cdb_free(struct cdb *cdbp)
  65. {
  66. if (cdbp->cdb_mem) {
  67. #ifdef _WIN32
  68. UnmapViewOfFile((void *) cdbp->cdb_mem);
  69. #else
  70. munmap((void *) cdbp->cdb_mem, cdbp->cdb_fsize);
  71. #endif /* _WIN32 */
  72. cdbp->cdb_mem = NULL;
  73. }
  74. cdbp->cdb_fsize = 0;
  75. if (cdbp->loop) {
  76. ev_stat_stop(cdbp->loop, &cdbp->stat_ev);
  77. }
  78. }
  79. const void *
  80. cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
  81. {
  82. if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
  83. errno = EPROTO;
  84. return NULL;
  85. }
  86. return cdbp->cdb_mem + pos;
  87. }
  88. int cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos)
  89. {
  90. const void *data = cdb_get(cdbp, len, pos);
  91. if (!data)
  92. return -1;
  93. memcpy(buf, data, len);
  94. return 0;
  95. }
  96. static void
  97. cdb_timer_callback(EV_P_ ev_stat *w, int revents)
  98. {
  99. struct cdb *cdbp = w->data;
  100. int nfd;
  101. /* Check cdb file for modifications */
  102. if ((nfd = open(cdbp->filename, O_RDONLY)) != -1) {
  103. if (cdbp->cdb_mem) {
  104. #ifdef _WIN32
  105. UnmapViewOfFile((void *) cdbp->cdb_mem);
  106. #else
  107. munmap((void *) cdbp->cdb_mem, cdbp->cdb_fsize);
  108. #endif /* _WIN32 */
  109. cdbp->cdb_mem = NULL;
  110. }
  111. (void) close(cdbp->cdb_fd);
  112. cdbp->cdb_fsize = 0;
  113. (void) cdb_init(cdbp, nfd);
  114. }
  115. }
  116. void cdb_add_timer(struct cdb *cdbp, EV_P_ ev_tstamp seconds)
  117. {
  118. cdbp->loop = loop;
  119. ev_stat_init(&cdbp->stat_ev, cdb_timer_callback, cdbp->filename, seconds);
  120. cdbp->stat_ev.data = cdbp;
  121. ev_stat_start(EV_A_ & cdbp->stat_ev);
  122. }