hashindex.pyx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. hashindex_close(index)
  53. return cls(path)
  54. def __getitem__(self, key):
  55. assert len(key) == 32
  56. data = <int *>hashindex_get(self.index, <char *>key)
  57. if not data:
  58. raise KeyError
  59. return data[0], data[1]
  60. def __delitem__(self, key):
  61. assert len(key) == 32
  62. hashindex_delete(self.index, <char *>key)
  63. def __setitem__(self, key, value):
  64. assert len(key) == 32
  65. cdef int[2] data
  66. data[0] = value[0]
  67. data[1] = value[1]
  68. hashindex_set(self.index, <char *>key, data)
  69. def __contains__(self, key):
  70. assert len(key) == 32
  71. data = <int *>hashindex_get(self.index, <char *>key)
  72. return data != NULL
  73. def iteritems(self, marker=None, limit=0):
  74. iter = NSKeyIterator()
  75. iter.index = self.index
  76. return iter
  77. cdef class NSKeyIterator:
  78. cdef HashIndex *index
  79. cdef char *key
  80. def __cinit__(self):
  81. self.key = NULL
  82. def __iter__(self):
  83. return self
  84. def __next__(self):
  85. self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
  86. if not self.key:
  87. raise StopIteration
  88. cdef int *value = <int *>(self.key + 32)
  89. return self.key[:32], (value[0], value[1])
  90. cdef class ChunkIndex(IndexBase):
  91. @classmethod
  92. def create(cls, path, capacity=16):
  93. index = hashindex_create(path, capacity, 32, 12)
  94. hashindex_close(index)
  95. return cls(path)
  96. def __getitem__(self, key):
  97. assert len(key) == 32
  98. data = <int *>hashindex_get(self.index, <char *>key)
  99. if not data:
  100. raise KeyError
  101. return data[0], data[1], data[2]
  102. def __delitem__(self, key):
  103. assert len(key) == 32
  104. hashindex_delete(self.index, <char *>key)
  105. def __setitem__(self, key, value):
  106. assert len(key) == 32
  107. cdef int[3] data
  108. data[0] = value[0]
  109. data[1] = value[1]
  110. data[2] = value[2]
  111. hashindex_set(self.index, <char *>key, data)
  112. def __contains__(self, key):
  113. assert len(key) == 32
  114. data = <int *>hashindex_get(self.index, <char *>key)
  115. return data != NULL
  116. def iteritems(self, marker=None, limit=0):
  117. iter = ChunkKeyIterator()
  118. iter.index = self.index
  119. return iter
  120. cdef class ChunkKeyIterator:
  121. cdef HashIndex *index
  122. cdef char *key
  123. def __cinit__(self):
  124. self.key = NULL
  125. def __iter__(self):
  126. return self
  127. def __next__(self):
  128. self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
  129. if not self.key:
  130. raise StopIteration
  131. cdef int *value = <int *>(self.key + 32)
  132. return self.key[:32], (value[0], value[1], value[2])
  133. cdef class BandIndex(IndexBase):
  134. @classmethod
  135. def create(cls, path, capacity=16):
  136. index = hashindex_create(path, capacity, 4, 4)
  137. hashindex_close(index)
  138. return cls(path)
  139. def __getitem__(self, key):
  140. cdef int k = key
  141. data = <int *>hashindex_get(self.index, &k)
  142. if not data:
  143. raise KeyError
  144. return data[0]
  145. def __delitem__(self, key):
  146. cdef int k = key
  147. hashindex_delete(self.index, &k)
  148. def __setitem__(self, key, value):
  149. cdef int k = key
  150. cdef int v = value
  151. hashindex_set(self.index, &k, &v)
  152. def __contains__(self, key):
  153. cdef int k = key
  154. data = <int *>hashindex_get(self.index, &k)
  155. return data != NULL
  156. def iteritems(self, marker=None, limit=0):
  157. iter = BandKeyIterator()
  158. iter.index = self.index
  159. return iter
  160. cdef class BandKeyIterator:
  161. cdef HashIndex *index
  162. cdef int *key
  163. def __cinit__(self):
  164. self.key = NULL
  165. def __iter__(self):
  166. return self
  167. def __next__(self):
  168. self.key = <int *>hashindex_next_key(self.index, <char *>self.key)
  169. if not self.key:
  170. raise StopIteration
  171. return self.key[0], self.key[1]