Save us! ... oh boy, I sure hope he doesn't read this)
In any case, stupidsum, although stupid, seems to do pretty well at its job.
-You can find it in _hashsplit.c. Basically, it converts the last 32 bytes
+You can find it in bupsplit.c. Basically, it converts the last 32 bytes
of the file into a 32-bit integer. What we then do is take the lowest 13
bits of the checksum, and if they're all 1's, we consider that to be the end
of a chunk. This happens on average once every 2^13 = 8192 bytes, so the
all: bup Documentation/all
-bup: lib/bup/_version.py lib/bup/_hashsplit$(SOEXT) cmds
+bup: lib/bup/_version.py lib/bup/_faster$(SOEXT) cmds
Documentation/all: bup
%/clean:
$(MAKE) -C $* clean
-lib/bup/_hashsplit$(SOEXT): lib/bup/_hashsplit.c lib/bup/csetup.py
+lib/bup/_faster$(SOEXT): \
+ lib/bup/bupsplit.c lib/bup/_faster.c lib/bup/csetup.py
@rm -f $@
cd lib/bup && $(PYTHON) csetup.py build
- cp lib/bup/build/*/_hashsplit$(SOEXT) lib/bup/
+ cp lib/bup/build/*/_faster$(SOEXT) lib/bup/
.PHONY: lib/bup/_version.py
lib/bup/_version.py:
#!/usr/bin/env python
import sys
-from bup import options, git, _hashsplit
+from bup import options, git, _faster
from bup.helpers import *
if i == last:
continue
#assert(str(i) >= last)
- pm = _hashsplit.bitmatch(last, i)
+ pm = _faster.bitmatch(last, i)
longmatch = max(longmatch, pm)
last = i
print longmatch
#!/usr/bin/env python
import sys, mmap
-from bup import options, _hashsplit
+from bup import options, _faster
from bup.helpers import *
optspec = """
if opt.force or (not os.isatty(1) and
not atoi(os.environ.get('BUP_FORCE_TTY')) & 1):
- _hashsplit.write_random(sys.stdout.fileno(), total, opt.seed)
+ _faster.write_random(sys.stdout.fileno(), total, opt.seed)
else:
log('error: not writing binary data to a terminal. Use -f to force.\n')
sys.exit(1)
--- /dev/null
+#include "bupsplit.h"
+#include <Python.h>
+#include <assert.h>
+#include <stdint.h>
+#include <fcntl.h>
+
+static PyObject *selftest(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ return Py_BuildValue("i", !bupsplit_selftest());
+}
+
+
+static PyObject *blobbits(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ return Py_BuildValue("i", BUP_BLOBBITS);
+}
+
+
+static PyObject *splitbuf(PyObject *self, PyObject *args)
+{
+ unsigned char *buf = NULL;
+ int len = 0, out = 0, bits = -1;
+
+ if (!PyArg_ParseTuple(args, "t#", &buf, &len))
+ return NULL;
+ out = bupsplit_find_ofs(buf, len, &bits);
+ return Py_BuildValue("ii", out, bits);
+}
+
+
+static PyObject *bitmatch(PyObject *self, PyObject *args)
+{
+ unsigned char *buf1 = NULL, *buf2 = NULL;
+ int len1 = 0, len2 = 0;
+ int byte, bit;
+
+ if (!PyArg_ParseTuple(args, "t#t#", &buf1, &len1, &buf2, &len2))
+ return NULL;
+
+ bit = 0;
+ for (byte = 0; byte < len1 && byte < len2; byte++)
+ {
+ int b1 = buf1[byte], b2 = buf2[byte];
+ if (b1 != b2)
+ {
+ for (bit = 0; bit < 8; bit++)
+ if ( (b1 & (0x80 >> bit)) != (b2 & (0x80 >> bit)) )
+ break;
+ break;
+ }
+ }
+
+ return Py_BuildValue("i", byte*8 + bit);
+}
+
+
+// I would have made this a lower-level function that just fills in a buffer
+// with random values, and then written those values from python. But that's
+// about 20% slower in my tests, and since we typically generate random
+// numbers for benchmarking other parts of bup, any slowness in generating
+// random bytes will make our benchmarks inaccurate. Plus nobody wants
+// pseudorandom bytes much except for this anyway.
+static PyObject *write_random(PyObject *self, PyObject *args)
+{
+ uint32_t buf[1024/4];
+ int fd = -1, seed = 0;
+ ssize_t ret;
+ long long len = 0, kbytes = 0, written = 0;
+
+ if (!PyArg_ParseTuple(args, "iLi", &fd, &len, &seed))
+ return NULL;
+
+ srandom(seed);
+
+ for (kbytes = 0; kbytes < len/1024; kbytes++)
+ {
+ unsigned i;
+ for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
+ buf[i] = random();
+ ret = write(fd, buf, sizeof(buf));
+ if (ret < 0)
+ ret = 0;
+ written += ret;
+ if (ret < (int)sizeof(buf))
+ break;
+ if (kbytes/1024 > 0 && !(kbytes%1024))
+ fprintf(stderr, "Random: %lld Mbytes\r", kbytes/1024);
+ }
+
+ // handle non-multiples of 1024
+ if (len % 1024)
+ {
+ unsigned i;
+ for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
+ buf[i] = random();
+ ret = write(fd, buf, len % 1024);
+ if (ret < 0)
+ ret = 0;
+ written += ret;
+ }
+
+ if (kbytes/1024 > 0)
+ fprintf(stderr, "Random: %lld Mbytes, done.\n", kbytes/1024);
+ return Py_BuildValue("L", written);
+}
+
+
+static PyObject *open_noatime(PyObject *self, PyObject *args)
+{
+ char *filename = NULL;
+ int attrs, attrs_noatime, fd;
+ if (!PyArg_ParseTuple(args, "s", &filename))
+ return NULL;
+ attrs = O_RDONLY;
+#ifdef O_NOFOLLOW
+ attrs |= O_NOFOLLOW;
+#endif
+#ifdef O_LARGEFILE
+ attrs |= O_LARGEFILE;
+#endif
+ attrs_noatime = attrs;
+#ifdef O_NOATIME
+ attrs_noatime |= O_NOATIME;
+#endif
+ fd = open(filename, attrs_noatime);
+ if (fd < 0 && errno == EPERM)
+ {
+ // older Linux kernels would return EPERM if you used O_NOATIME
+ // and weren't the file's owner. This pointless restriction was
+ // relaxed eventually, but we have to handle it anyway.
+ // (VERY old kernels didn't recognized O_NOATIME, but they would
+ // just harmlessly ignore it, so this branch won't trigger)
+ fd = open(filename, attrs);
+ }
+ if (fd < 0)
+ return PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
+ return Py_BuildValue("i", fd);
+}
+
+
+static PyObject *fadvise_done(PyObject *self, PyObject *args)
+{
+ int fd = -1;
+ long long ofs = 0;
+ if (!PyArg_ParseTuple(args, "iL", &fd, &ofs))
+ return NULL;
+#ifdef POSIX_FADV_DONTNEED
+ posix_fadvise(fd, 0, ofs, POSIX_FADV_DONTNEED);
+#endif
+ return Py_BuildValue("");
+}
+
+
+static PyMethodDef faster_methods[] = {
+ { "selftest", selftest, METH_VARARGS,
+ "Check that the rolling checksum rolls correctly (for unit tests)." },
+ { "blobbits", blobbits, METH_VARARGS,
+ "Return the number of bits in the rolling checksum." },
+ { "splitbuf", splitbuf, METH_VARARGS,
+ "Split a list of strings based on a rolling checksum." },
+ { "bitmatch", bitmatch, METH_VARARGS,
+ "Count the number of matching prefix bits between two strings." },
+ { "write_random", write_random, METH_VARARGS,
+ "Write random bytes to the given file descriptor" },
+ { "open_noatime", open_noatime, METH_VARARGS,
+ "open() the given filename for read with O_NOATIME if possible" },
+ { "fadvise_done", fadvise_done, METH_VARARGS,
+ "Inform the kernel that we're finished with earlier parts of a file" },
+ { NULL, NULL, 0, NULL }, // sentinel
+};
+
+PyMODINIT_FUNC init_faster(void)
+{
+ Py_InitModule("_faster", faster_methods);
+}
+++ /dev/null
-#include <Python.h>
-#include <assert.h>
-#include <stdint.h>
-#include <fcntl.h>
-
-#define BLOBBITS (13)
-#define BLOBSIZE (1<<BLOBBITS)
-#define WINDOWBITS (7)
-#define WINDOWSIZE (1<<(WINDOWBITS-1))
-
-// According to librsync/rollsum.h:
-// "We should make this something other than zero to improve the
-// checksum algorithm: tridge suggests a prime number."
-// apenwarr: I unscientifically tried 0 and 7919, and they both ended up
-// slightly worse than the librsync value of 31 for my arbitrary test data.
-#define ROLLSUM_CHAR_OFFSET 31
-
-typedef struct {
- unsigned s1, s2;
- uint8_t window[WINDOWSIZE];
- int wofs;
-} Rollsum;
-
-
-// These formulas are based on rollsum.h in the librsync project.
-static void rollsum_add(Rollsum *r, uint8_t drop, uint8_t add)
-{
- r->s1 += add - drop;
- r->s2 += r->s1 - (WINDOWSIZE * (drop + ROLLSUM_CHAR_OFFSET));
-}
-
-
-static void rollsum_init(Rollsum *r)
-{
- r->s1 = WINDOWSIZE * ROLLSUM_CHAR_OFFSET;
- r->s2 = WINDOWSIZE * (WINDOWSIZE-1) * ROLLSUM_CHAR_OFFSET;
- r->wofs = 0;
- memset(r->window, 0, WINDOWSIZE);
-}
-
-
-// For some reason, gcc 4.3 (at least) optimizes badly if find_ofs()
-// is static and rollsum_roll is an inline function. Let's use a macro
-// here instead to help out the optimizer.
-#define rollsum_roll(r, ch) do { \
- rollsum_add((r), (r)->window[(r)->wofs], (ch)); \
- (r)->window[(r)->wofs] = (ch); \
- (r)->wofs = ((r)->wofs + 1) % WINDOWSIZE; \
-} while (0)
-
-
-static uint32_t rollsum_digest(Rollsum *r)
-{
- return (r->s1 << 16) | (r->s2 & 0xffff);
-}
-
-
-static uint32_t rollsum_sum(uint8_t *buf, size_t ofs, size_t len)
-{
- size_t count;
- Rollsum r;
- rollsum_init(&r);
- for (count = ofs; count < len; count++)
- rollsum_roll(&r, buf[count]);
- return rollsum_digest(&r);
-}
-
-
-static PyObject *selftest(PyObject *self, PyObject *args)
-{
- uint8_t buf[100000];
- uint32_t sum1a, sum1b, sum2a, sum2b, sum3a, sum3b;
- unsigned count;
-
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
-
- srandom(1);
- for (count = 0; count < sizeof(buf); count++)
- buf[count] = random();
-
- sum1a = rollsum_sum(buf, 0, sizeof(buf));
- sum1b = rollsum_sum(buf, 1, sizeof(buf));
- sum2a = rollsum_sum(buf, sizeof(buf) - WINDOWSIZE*5/2,
- sizeof(buf) - WINDOWSIZE);
- sum2b = rollsum_sum(buf, 0, sizeof(buf) - WINDOWSIZE);
- sum3a = rollsum_sum(buf, 0, WINDOWSIZE+3);
- sum3b = rollsum_sum(buf, 3, WINDOWSIZE+3);
-
- fprintf(stderr, "sum1a = 0x%08x\n", sum1a);
- fprintf(stderr, "sum1b = 0x%08x\n", sum1b);
- fprintf(stderr, "sum2a = 0x%08x\n", sum2a);
- fprintf(stderr, "sum2b = 0x%08x\n", sum2b);
- fprintf(stderr, "sum3a = 0x%08x\n", sum3a);
- fprintf(stderr, "sum3b = 0x%08x\n", sum3b);
-
- return Py_BuildValue("i", sum1a==sum1b && sum2a==sum2b && sum3a==sum3b);
-}
-
-
-static int find_ofs(const unsigned char *buf, int len, int *bits)
-{
- Rollsum r;
- int count;
-
- rollsum_init(&r);
- for (count = 0; count < len; count++)
- {
- rollsum_roll(&r, buf[count]);
- if ((r.s2 & (BLOBSIZE-1)) == ((~0) & (BLOBSIZE-1)))
- {
- if (bits)
- {
- unsigned rsum = rollsum_digest(&r);
- *bits = BLOBBITS;
- rsum >>= BLOBBITS;
- for (*bits = BLOBBITS; (rsum >>= 1) & 1; (*bits)++)
- ;
- }
- return count+1;
- }
- }
- return 0;
-}
-
-
-static PyObject *blobbits(PyObject *self, PyObject *args)
-{
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- return Py_BuildValue("i", BLOBBITS);
-}
-
-
-static PyObject *splitbuf(PyObject *self, PyObject *args)
-{
- unsigned char *buf = NULL;
- int len = 0, out = 0, bits = -1;
-
- if (!PyArg_ParseTuple(args, "t#", &buf, &len))
- return NULL;
- out = find_ofs(buf, len, &bits);
- return Py_BuildValue("ii", out, bits);
-}
-
-
-static PyObject *bitmatch(PyObject *self, PyObject *args)
-{
- unsigned char *buf1 = NULL, *buf2 = NULL;
- int len1 = 0, len2 = 0;
- int byte, bit;
-
- if (!PyArg_ParseTuple(args, "t#t#", &buf1, &len1, &buf2, &len2))
- return NULL;
-
- bit = 0;
- for (byte = 0; byte < len1 && byte < len2; byte++)
- {
- int b1 = buf1[byte], b2 = buf2[byte];
- if (b1 != b2)
- {
- for (bit = 0; bit < 8; bit++)
- if ( (b1 & (0x80 >> bit)) != (b2 & (0x80 >> bit)) )
- break;
- break;
- }
- }
-
- return Py_BuildValue("i", byte*8 + bit);
-}
-
-
-// I would have made this a lower-level function that just fills in a buffer
-// with random values, and then written those values from python. But that's
-// about 20% slower in my tests, and since we typically generate random
-// numbers for benchmarking other parts of bup, any slowness in generating
-// random bytes will make our benchmarks inaccurate. Plus nobody wants
-// pseudorandom bytes much except for this anyway.
-static PyObject *write_random(PyObject *self, PyObject *args)
-{
- uint32_t buf[1024/4];
- int fd = -1, seed = 0;
- ssize_t ret;
- long long len = 0, kbytes = 0, written = 0;
-
- if (!PyArg_ParseTuple(args, "iLi", &fd, &len, &seed))
- return NULL;
-
- srandom(seed);
-
- for (kbytes = 0; kbytes < len/1024; kbytes++)
- {
- unsigned i;
- for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
- buf[i] = random();
- ret = write(fd, buf, sizeof(buf));
- if (ret < 0)
- ret = 0;
- written += ret;
- if (ret < (int)sizeof(buf))
- break;
- if (kbytes/1024 > 0 && !(kbytes%1024))
- fprintf(stderr, "Random: %lld Mbytes\r", kbytes/1024);
- }
-
- // handle non-multiples of 1024
- if (len % 1024)
- {
- unsigned i;
- for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
- buf[i] = random();
- ret = write(fd, buf, len % 1024);
- if (ret < 0)
- ret = 0;
- written += ret;
- }
-
- if (kbytes/1024 > 0)
- fprintf(stderr, "Random: %lld Mbytes, done.\n", kbytes/1024);
- return Py_BuildValue("L", written);
-}
-
-
-static PyObject *open_noatime(PyObject *self, PyObject *args)
-{
- char *filename = NULL;
- int attrs, attrs_noatime, fd;
- if (!PyArg_ParseTuple(args, "s", &filename))
- return NULL;
- attrs = O_RDONLY;
-#ifdef O_NOFOLLOW
- attrs |= O_NOFOLLOW;
-#endif
-#ifdef O_LARGEFILE
- attrs |= O_LARGEFILE;
-#endif
- attrs_noatime = attrs;
-#ifdef O_NOATIME
- attrs_noatime |= O_NOATIME;
-#endif
- fd = open(filename, attrs_noatime);
- if (fd < 0 && errno == EPERM)
- {
- // older Linux kernels would return EPERM if you used O_NOATIME
- // and weren't the file's owner. This pointless restriction was
- // relaxed eventually, but we have to handle it anyway.
- // (VERY old kernels didn't recognized O_NOATIME, but they would
- // just harmlessly ignore it, so this branch won't trigger)
- fd = open(filename, attrs);
- }
- if (fd < 0)
- return PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
- return Py_BuildValue("i", fd);
-}
-
-
-static PyObject *fadvise_done(PyObject *self, PyObject *args)
-{
- int fd = -1;
- long long ofs = 0;
- if (!PyArg_ParseTuple(args, "iL", &fd, &ofs))
- return NULL;
-#ifdef POSIX_FADV_DONTNEED
- posix_fadvise(fd, 0, ofs, POSIX_FADV_DONTNEED);
-#endif
- return Py_BuildValue("");
-}
-
-
-static PyMethodDef hashsplit_methods[] = {
- { "selftest", selftest, METH_VARARGS,
- "Check that the rolling checksum rolls correctly (for unit tests)." },
- { "blobbits", blobbits, METH_VARARGS,
- "Return the number of bits in the rolling checksum." },
- { "splitbuf", splitbuf, METH_VARARGS,
- "Split a list of strings based on a rolling checksum." },
- { "bitmatch", bitmatch, METH_VARARGS,
- "Count the number of matching prefix bits between two strings." },
- { "write_random", write_random, METH_VARARGS,
- "Write random bytes to the given file descriptor" },
- { "open_noatime", open_noatime, METH_VARARGS,
- "open() the given filename for read with O_NOATIME if possible" },
- { "fadvise_done", fadvise_done, METH_VARARGS,
- "Inform the kernel that we're finished with earlier parts of a file" },
- { NULL, NULL, 0, NULL }, // sentinel
-};
-
-PyMODINIT_FUNC init_hashsplit(void)
-{
- Py_InitModule("_hashsplit", hashsplit_methods);
-}
--- /dev/null
+#include "bupsplit.h"
+#include <assert.h>
+#include <stdint.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+// According to librsync/rollsum.h:
+// "We should make this something other than zero to improve the
+// checksum algorithm: tridge suggests a prime number."
+// apenwarr: I unscientifically tried 0 and 7919, and they both ended up
+// slightly worse than the librsync value of 31 for my arbitrary test data.
+#define ROLLSUM_CHAR_OFFSET 31
+
+typedef struct {
+ unsigned s1, s2;
+ uint8_t window[BUP_WINDOWSIZE];
+ int wofs;
+} Rollsum;
+
+
+// These formulas are based on rollsum.h in the librsync project.
+static void rollsum_add(Rollsum *r, uint8_t drop, uint8_t add)
+{
+ r->s1 += add - drop;
+ r->s2 += r->s1 - (BUP_WINDOWSIZE * (drop + ROLLSUM_CHAR_OFFSET));
+}
+
+
+static void rollsum_init(Rollsum *r)
+{
+ r->s1 = BUP_WINDOWSIZE * ROLLSUM_CHAR_OFFSET;
+ r->s2 = BUP_WINDOWSIZE * (BUP_WINDOWSIZE-1) * ROLLSUM_CHAR_OFFSET;
+ r->wofs = 0;
+ memset(r->window, 0, BUP_WINDOWSIZE);
+}
+
+
+// For some reason, gcc 4.3 (at least) optimizes badly if find_ofs()
+// is static and rollsum_roll is an inline function. Let's use a macro
+// here instead to help out the optimizer.
+#define rollsum_roll(r, ch) do { \
+ rollsum_add((r), (r)->window[(r)->wofs], (ch)); \
+ (r)->window[(r)->wofs] = (ch); \
+ (r)->wofs = ((r)->wofs + 1) % BUP_WINDOWSIZE; \
+} while (0)
+
+
+static uint32_t rollsum_digest(Rollsum *r)
+{
+ return (r->s1 << 16) | (r->s2 & 0xffff);
+}
+
+
+static uint32_t rollsum_sum(uint8_t *buf, size_t ofs, size_t len)
+{
+ size_t count;
+ Rollsum r;
+ rollsum_init(&r);
+ for (count = ofs; count < len; count++)
+ rollsum_roll(&r, buf[count]);
+ return rollsum_digest(&r);
+}
+
+
+int bupsplit_find_ofs(const unsigned char *buf, int len, int *bits)
+{
+ Rollsum r;
+ int count;
+
+ rollsum_init(&r);
+ for (count = 0; count < len; count++)
+ {
+ rollsum_roll(&r, buf[count]);
+ if ((r.s2 & (BUP_BLOBSIZE-1)) == ((~0) & (BUP_BLOBSIZE-1)))
+ {
+ if (bits)
+ {
+ unsigned rsum = rollsum_digest(&r);
+ *bits = BUP_BLOBBITS;
+ rsum >>= BUP_BLOBBITS;
+ for (*bits = BUP_BLOBBITS; (rsum >>= 1) & 1; (*bits)++)
+ ;
+ }
+ return count+1;
+ }
+ }
+ return 0;
+}
+
+
+#ifndef BUP_NO_SELFTEST
+
+int bupsplit_selftest()
+{
+ uint8_t buf[100000];
+ uint32_t sum1a, sum1b, sum2a, sum2b, sum3a, sum3b;
+ unsigned count;
+
+ srandom(1);
+ for (count = 0; count < sizeof(buf); count++)
+ buf[count] = random();
+
+ sum1a = rollsum_sum(buf, 0, sizeof(buf));
+ sum1b = rollsum_sum(buf, 1, sizeof(buf));
+ sum2a = rollsum_sum(buf, sizeof(buf) - BUP_WINDOWSIZE*5/2,
+ sizeof(buf) - BUP_WINDOWSIZE);
+ sum2b = rollsum_sum(buf, 0, sizeof(buf) - BUP_WINDOWSIZE);
+ sum3a = rollsum_sum(buf, 0, BUP_WINDOWSIZE+3);
+ sum3b = rollsum_sum(buf, 3, BUP_WINDOWSIZE+3);
+
+ fprintf(stderr, "sum1a = 0x%08x\n", sum1a);
+ fprintf(stderr, "sum1b = 0x%08x\n", sum1b);
+ fprintf(stderr, "sum2a = 0x%08x\n", sum2a);
+ fprintf(stderr, "sum2b = 0x%08x\n", sum2b);
+ fprintf(stderr, "sum3a = 0x%08x\n", sum3a);
+ fprintf(stderr, "sum3b = 0x%08x\n", sum3b);
+
+ return sum1a!=sum1b || sum2a!=sum2b || sum3a!=sum3b;
+}
+
+#endif // !BUP_NO_SELFTEST
--- /dev/null
+#ifndef __BUPSPLIT_H
+#define __BUPSPLIT_H
+
+#define BUP_BLOBBITS (13)
+#define BUP_BLOBSIZE (1<<BUP_BLOBBITS)
+#define BUP_WINDOWBITS (7)
+#define BUP_WINDOWSIZE (1<<(BUP_WINDOWBITS-1))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int bupsplit_find_ofs(const unsigned char *buf, int len, int *bits);
+int bupsplit_selftest(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BUPSPLIT_H */
from distutils.core import setup, Extension
-_hashsplit_mod = Extension('_hashsplit', sources=['_hashsplit.c'])
+_faster_mod = Extension('_faster', sources=['_faster.c', 'bupsplit.c'])
-setup(name='_hashsplit',
+setup(name='_faster',
version='0.1',
- description='hashsplit helper library for bup',
- ext_modules=[_hashsplit_mod])
+ description='accelerator library for bup',
+ ext_modules=[_faster_mod])
import sys, math
-from bup import _hashsplit
+from bup import _faster
from bup.helpers import *
BLOB_LWM = 8192*2
def splitbuf(buf):
b = buf.peek(buf.used())
- (ofs, bits) = _hashsplit.splitbuf(b)
+ (ofs, bits) = _faster.splitbuf(b)
if ofs:
buf.eat(ofs)
return (buffer(b, 0, ofs), bits)
shal.append(('100644', sha, size))
return _make_shalist(shal)[0]
else:
- base_bits = _hashsplit.blobbits()
+ base_bits = _faster.blobbits()
fanout_bits = int(math.log(fanout, 2))
def bits_to_idx(n):
assert(n >= base_bits)
def open_noatime(name):
- fd = _hashsplit.open_noatime(name)
+ fd = _faster.open_noatime(name)
try:
return os.fdopen(fd, 'rb', 1024*1024)
except:
def fadvise_done(f, ofs):
assert(ofs >= 0)
if ofs > 0:
- _hashsplit.fadvise_done(f.fileno(), ofs)
+ _faster.fadvise_done(f.fileno(), ofs)
-from bup import hashsplit, _hashsplit
+from bup import hashsplit, _faster
from wvtest import *
@wvtest
def test_rolling_sums():
- WVPASS(_hashsplit.selftest())
+ WVPASS(_faster.selftest())