hashindex.pyx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. # -*- coding: utf-8 -*-
  2. cdef extern from "_hashindex.c":
  3. ctypedef struct HashIndex:
  4. pass
  5. HashIndex *hashindex_open(char *path)
  6. HashIndex *hashindex_create(char *path, int capacity, int key_size, int value_size)
  7. int hashindex_get_size(HashIndex *index)
  8. void hashindex_clear(HashIndex *index)
  9. void hashindex_close(HashIndex *index)
  10. void hashindex_flush(HashIndex *index)
  11. void *hashindex_get(HashIndex *index, void *key)
  12. void *hashindex_next_key(HashIndex *index, void *key)
  13. void hashindex_delete(HashIndex *index, void *key)
  14. void hashindex_set(HashIndex *index, void *key, void *value)
  15. _NoDefault = object()
  16. cdef class IndexBase:
  17. cdef HashIndex *index
  18. def __cinit__(self, path):
  19. self.index = hashindex_open(path)
  20. if not self.index:
  21. raise Exception('Failed to open %s' % path)
  22. def __dealloc__(self):
  23. if self.index:
  24. hashindex_close(self.index)
  25. def clear(self):
  26. hashindex_clear(self.index)
  27. def flush(self):
  28. hashindex_flush(self.index)
  29. def setdefault(self, key, value):
  30. if not key in self:
  31. self[key] = value
  32. def get(self, key, default=None):
  33. try:
  34. return self[key]
  35. except KeyError:
  36. return default
  37. def pop(self, key, default=_NoDefault):
  38. try:
  39. value = self[key]
  40. del self[key]
  41. return value
  42. except KeyError:
  43. if default != _NoDefault:
  44. return default
  45. raise
  46. def __len__(self):
  47. return hashindex_get_size(self.index)
  48. cdef class NSIndex(IndexBase):
  49. @classmethod
  50. def create(cls, path, capacity=16):
  51. index = hashindex_create(path, capacity, 32, 8)
  52. if not index:
  53. raise Exception('Failed to create %s' % path)
  54. hashindex_close(index)
  55. return cls(path)
  56. def __getitem__(self, key):
  57. assert len(key) == 32
  58. data = <int *>hashindex_get(self.index, <char *>key)
  59. if not data:
  60. raise KeyError
  61. return data[0], data[1]
  62. def __delitem__(self, key):
  63. assert len(key) == 32
  64. hashindex_delete(self.index, <char *>key)
  65. def __setitem__(self, key, value):
  66. assert len(key) == 32
  67. cdef int[2] data
  68. data[0] = value[0]
  69. data[1] = value[1]
  70. hashindex_set(self.index, <char *>key, data)
  71. def __contains__(self, key):
  72. assert len(key) == 32
  73. data = <int *>hashindex_get(self.index, <char *>key)
  74. return data != NULL
  75. def iteritems(self, marker=None, limit=0):
  76. iter = NSKeyIterator()
  77. iter.index = self.index
  78. return iter
  79. cdef class NSKeyIterator:
  80. cdef HashIndex *index
  81. cdef char *key
  82. def __cinit__(self):
  83. self.key = NULL
  84. def __iter__(self):
  85. return self
  86. def __next__(self):
  87. self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
  88. if not self.key:
  89. raise StopIteration
  90. cdef int *value = <int *>(self.key + 32)
  91. return self.key[:32], (value[0], value[1])
  92. cdef class ChunkIndex(IndexBase):
  93. @classmethod
  94. def create(cls, path, capacity=16):
  95. index = hashindex_create(path, capacity, 32, 12)
  96. hashindex_close(index)
  97. return cls(path)
  98. def __getitem__(self, key):
  99. assert len(key) == 32
  100. data = <int *>hashindex_get(self.index, <char *>key)
  101. if not data:
  102. raise KeyError
  103. return data[0], data[1], data[2]
  104. def __delitem__(self, key):
  105. assert len(key) == 32
  106. hashindex_delete(self.index, <char *>key)
  107. def __setitem__(self, key, value):
  108. assert len(key) == 32
  109. cdef int[3] data
  110. data[0] = value[0]
  111. data[1] = value[1]
  112. data[2] = value[2]
  113. hashindex_set(self.index, <char *>key, data)
  114. def __contains__(self, key):
  115. assert len(key) == 32
  116. data = <int *>hashindex_get(self.index, <char *>key)
  117. return data != NULL
  118. def iteritems(self, marker=None, limit=0):
  119. iter = ChunkKeyIterator()
  120. iter.index = self.index
  121. return iter
  122. cdef class ChunkKeyIterator:
  123. cdef HashIndex *index
  124. cdef char *key
  125. def __cinit__(self):
  126. self.key = NULL
  127. def __iter__(self):
  128. return self
  129. def __next__(self):
  130. self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
  131. if not self.key:
  132. raise StopIteration
  133. cdef int *value = <int *>(self.key + 32)
  134. return self.key[:32], (value[0], value[1], value[2])
  135. cdef class BandIndex(IndexBase):
  136. @classmethod
  137. def create(cls, path, capacity=16):
  138. index = hashindex_create(path, capacity, 4, 4)
  139. hashindex_close(index)
  140. return cls(path)
  141. def __getitem__(self, key):
  142. cdef int k = key
  143. data = <int *>hashindex_get(self.index, &k)
  144. if not data:
  145. raise KeyError
  146. return data[0]
  147. def __delitem__(self, key):
  148. cdef int k = key
  149. hashindex_delete(self.index, &k)
  150. def __setitem__(self, key, value):
  151. cdef int k = key
  152. cdef int v = value
  153. hashindex_set(self.index, &k, &v)
  154. def __contains__(self, key):
  155. cdef int k = key
  156. data = <int *>hashindex_get(self.index, &k)
  157. return data != NULL
  158. def iteritems(self, marker=None, limit=0):
  159. iter = BandKeyIterator()
  160. iter.index = self.index
  161. return iter
  162. cdef class BandKeyIterator:
  163. cdef HashIndex *index
  164. cdef int *key
  165. def __cinit__(self):
  166. self.key = NULL
  167. def __iter__(self):
  168. return self
  169. def __next__(self):
  170. self.key = <int *>hashindex_next_key(self.index, <char *>self.key)
  171. if not self.key:
  172. raise StopIteration
  173. return self.key[0], self.key[1]