borg/attic/hashindex.pyx

179 lines
4.9 KiB
Cython
Raw Normal View History

2010-12-16 19:23:22 +00:00
# -*- coding: utf-8 -*-
import os
2010-12-16 19:23:22 +00:00
2013-05-28 12:35:55 +00:00
cdef extern from "_hashindex.c":
2010-12-16 19:23:22 +00:00
ctypedef struct HashIndex:
pass
HashIndex *hashindex_open(char *path, int readonly)
2010-12-16 19:23:22 +00:00
HashIndex *hashindex_create(char *path, int capacity, int key_size, int value_size)
int hashindex_get_size(HashIndex *index)
2013-07-03 10:19:16 +00:00
int hashindex_clear(HashIndex *index)
int hashindex_close(HashIndex *index)
int hashindex_flush(HashIndex *index)
2010-12-16 19:23:22 +00:00
void *hashindex_get(HashIndex *index, void *key)
void *hashindex_next_key(HashIndex *index, void *key)
2013-07-03 10:19:16 +00:00
int hashindex_delete(HashIndex *index, void *key)
int hashindex_set(HashIndex *index, void *key, void *value)
int htole32(int v)
int le32toh(int v)
2010-12-16 19:23:22 +00:00
2013-05-28 12:35:55 +00:00
_NoDefault = object()
2010-12-16 19:23:22 +00:00
cdef class IndexBase:
cdef HashIndex *index
2013-07-03 10:19:16 +00:00
key_size = 32
2010-12-16 19:23:22 +00:00
def __cinit__(self, path, readonly=False):
self.index = hashindex_open(<bytes>os.fsencode(path), readonly)
2010-12-16 19:23:22 +00:00
if not self.index:
raise Exception('Failed to open %s' % path)
def __dealloc__(self):
2013-06-03 11:45:48 +00:00
if self.index:
2013-07-03 10:19:16 +00:00
if not hashindex_close(self.index):
raise Exception('hashindex_close failed')
@classmethod
def create(cls, path):
index = hashindex_create(<bytes>os.fsencode(path), 0, cls.key_size, cls.value_size)
if not index:
raise Exception('Failed to create %s' % path)
hashindex_close(index)
return cls(path)
2010-12-16 19:23:22 +00:00
def clear(self):
2013-07-03 10:19:16 +00:00
if not hashindex_clear(self.index):
raise Exception('hashindex_clear failed')
2010-12-16 19:23:22 +00:00
def flush(self):
2013-07-03 10:19:16 +00:00
if not hashindex_flush(self.index):
raise Exception('hashindex_flush failed')
2010-12-16 19:23:22 +00:00
def setdefault(self, key, value):
if not key in self:
self[key] = value
2013-07-03 10:19:16 +00:00
def __delitem__(self, key):
assert len(key) == 32
if not hashindex_delete(self.index, <char *>key):
raise Exception('hashindex_delete failed')
2010-12-21 20:29:09 +00:00
def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default
def pop(self, key, default=_NoDefault):
try:
value = self[key]
del self[key]
return value
except KeyError:
if default != _NoDefault:
return default
raise
2010-12-16 19:23:22 +00:00
def __len__(self):
return hashindex_get_size(self.index)
cdef class NSIndex(IndexBase):
2013-07-03 10:19:16 +00:00
value_size = 8
2010-12-16 19:23:22 +00:00
def __getitem__(self, key):
assert len(key) == 32
data = <int *>hashindex_get(self.index, <char *>key)
if not data:
raise KeyError
return le32toh(data[0]), le32toh(data[1])
2010-12-16 19:23:22 +00:00
def __setitem__(self, key, value):
assert len(key) == 32
cdef int[2] data
data[0] = htole32(value[0])
data[1] = htole32(value[1])
2013-07-03 10:19:16 +00:00
if not hashindex_set(self.index, <char *>key, data):
raise Exception('hashindex_set failed')
2010-12-16 19:23:22 +00:00
def __contains__(self, key):
assert len(key) == 32
data = <int *>hashindex_get(self.index, <char *>key)
return data != NULL
def iteritems(self, marker=None, limit=0):
iter = NSKeyIterator()
iter.index = self.index
return iter
cdef class NSKeyIterator:
cdef HashIndex *index
cdef char *key
def __cinit__(self):
self.key = NULL
def __iter__(self):
return self
def __next__(self):
self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
if not self.key:
raise StopIteration
cdef int *value = <int *>(self.key + 32)
return self.key[:32], (le32toh(value[0]), le32toh(value[1]))
2010-12-16 19:23:22 +00:00
cdef class ChunkIndex(IndexBase):
2013-07-03 10:19:16 +00:00
value_size = 12
def __getitem__(self, key):
assert len(key) == 32
data = <int *>hashindex_get(self.index, <char *>key)
if not data:
raise KeyError
return le32toh(data[0]), le32toh(data[1]), le32toh(data[2])
def __setitem__(self, key, value):
assert len(key) == 32
cdef int[3] data
data[0] = htole32(value[0])
data[1] = htole32(value[1])
data[2] = htole32(value[2])
2013-07-03 10:19:16 +00:00
if not hashindex_set(self.index, <char *>key, data):
raise Exception('hashindex_set failed')
def __contains__(self, key):
assert len(key) == 32
data = <int *>hashindex_get(self.index, <char *>key)
return data != NULL
def iteritems(self, marker=None, limit=0):
iter = ChunkKeyIterator()
iter.index = self.index
return iter
cdef class ChunkKeyIterator:
cdef HashIndex *index
cdef char *key
def __cinit__(self):
self.key = NULL
def __iter__(self):
return self
def __next__(self):
self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
if not self.key:
raise StopIteration
cdef int *value = <int *>(self.key + 32)
return self.key[:32], (le32toh(value[0]), le32toh(value[1]), le32toh(value[2]))