mirror of
https://github.com/borgbackup/borg.git
synced 2024-12-25 01:06:50 +00:00
221 lines
5.6 KiB
Cython
221 lines
5.6 KiB
Cython
# -*- coding: utf-8 -*-
|
|
|
|
cdef extern from "hashindex.h":
|
|
ctypedef struct HashIndex:
|
|
pass
|
|
|
|
HashIndex *hashindex_open(char *path)
|
|
HashIndex *hashindex_create(char *path, int capacity, int key_size, int value_size)
|
|
int hashindex_get_size(HashIndex *index)
|
|
void hashindex_clear(HashIndex *index)
|
|
void hashindex_close(HashIndex *index)
|
|
void hashindex_flush(HashIndex *index)
|
|
void *hashindex_get(HashIndex *index, void *key)
|
|
void *hashindex_next_key(HashIndex *index, void *key)
|
|
void hashindex_delete(HashIndex *index, void *key)
|
|
void hashindex_set(HashIndex *index, void *key, void *value)
|
|
|
|
_NoDefault = object()
|
|
|
|
cdef class IndexBase:
|
|
cdef HashIndex *index
|
|
|
|
def __cinit__(self, path):
|
|
self.index = hashindex_open(path)
|
|
if not self.index:
|
|
raise Exception('Failed to open %s' % path)
|
|
|
|
def __dealloc__(self):
|
|
hashindex_close(self.index)
|
|
|
|
def clear(self):
|
|
hashindex_clear(self.index)
|
|
|
|
def flush(self):
|
|
hashindex_flush(self.index)
|
|
|
|
def setdefault(self, key, value):
|
|
if not key in self:
|
|
self[key] = value
|
|
|
|
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
|
|
|
|
def __len__(self):
|
|
return hashindex_get_size(self.index)
|
|
|
|
|
|
cdef class NSIndex(IndexBase):
|
|
|
|
@classmethod
|
|
def create(cls, path, capacity=16):
|
|
index = hashindex_create(path, capacity, 32, 8)
|
|
hashindex_close(index)
|
|
return cls(path)
|
|
|
|
def __getitem__(self, key):
|
|
assert len(key) == 32
|
|
data = <int *>hashindex_get(self.index, <char *>key)
|
|
if not data:
|
|
raise KeyError
|
|
return data[0], data[1]
|
|
|
|
def __delitem__(self, key):
|
|
assert len(key) == 32
|
|
hashindex_delete(self.index, <char *>key)
|
|
|
|
def __setitem__(self, key, value):
|
|
assert len(key) == 32
|
|
cdef int[2] data
|
|
data[0] = value[0]
|
|
data[1] = value[1]
|
|
hashindex_set(self.index, <char *>key, data)
|
|
|
|
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], (value[0], value[1])
|
|
|
|
|
|
cdef class ChunkIndex(IndexBase):
|
|
|
|
@classmethod
|
|
def create(cls, path, capacity=16):
|
|
index = hashindex_create(path, capacity, 32, 12)
|
|
hashindex_close(index)
|
|
return cls(path)
|
|
|
|
def __getitem__(self, key):
|
|
assert len(key) == 32
|
|
data = <int *>hashindex_get(self.index, <char *>key)
|
|
if not data:
|
|
raise KeyError
|
|
return data[0], data[1], data[2]
|
|
|
|
def __delitem__(self, key):
|
|
assert len(key) == 32
|
|
hashindex_delete(self.index, <char *>key)
|
|
|
|
def __setitem__(self, key, value):
|
|
assert len(key) == 32
|
|
cdef int[3] data
|
|
data[0] = value[0]
|
|
data[1] = value[1]
|
|
data[2] = value[2]
|
|
hashindex_set(self.index, <char *>key, data)
|
|
|
|
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], (value[0], value[1], value[2])
|
|
|
|
|
|
cdef class BandIndex(IndexBase):
|
|
|
|
@classmethod
|
|
def create(cls, path, capacity=16):
|
|
index = hashindex_create(path, capacity, 4, 4)
|
|
hashindex_close(index)
|
|
return cls(path)
|
|
|
|
def __getitem__(self, key):
|
|
cdef int k = key
|
|
data = <int *>hashindex_get(self.index, &k)
|
|
if not data:
|
|
raise KeyError
|
|
return data[0]
|
|
|
|
def __delitem__(self, key):
|
|
cdef int k = key
|
|
hashindex_delete(self.index, &k)
|
|
|
|
def __setitem__(self, key, value):
|
|
cdef int k = key
|
|
cdef int v = value
|
|
hashindex_set(self.index, &k, &v)
|
|
|
|
def __contains__(self, key):
|
|
cdef int k = key
|
|
data = <int *>hashindex_get(self.index, &k)
|
|
return data != NULL
|
|
|
|
def iteritems(self, marker=None, limit=0):
|
|
iter = BandKeyIterator()
|
|
iter.index = self.index
|
|
return iter
|
|
|
|
|
|
cdef class BandKeyIterator:
|
|
cdef HashIndex *index
|
|
cdef int *key
|
|
|
|
def __cinit__(self):
|
|
self.key = NULL
|
|
|
|
def __iter__(self):
|
|
return self
|
|
|
|
def __next__(self):
|
|
self.key = <int *>hashindex_next_key(self.index, <char *>self.key)
|
|
if not self.key:
|
|
raise StopIteration
|
|
return self.key[0], self.key[1]
|