浏览代码

get rid of the CacheSynchronizer

Lots of low-level code written back then to optimize runtime of some
functions.

We'll solve this differently by doing less stats, esp. if it is expensive to compute.
Thomas Waldmann 11 月之前
父节点
当前提交
0306ba9a63

+ 0 - 10
scripts/fuzz-cache-sync/HOWTO

@@ -1,10 +0,0 @@
-- Install AFL and the requirements for LLVM mode (see docs)
-- Compile the fuzzing target, e.g.
-
-  AFL_HARDEN=1 afl-clang-fast main.c -o fuzz-target -O3
-
-  (other options, like using ASan or MSan are possible as well)
-- Add additional test cases to testcase_dir
-- Run afl, easiest (but inefficient) way;
-
-  afl-fuzz -i testcase_dir -o findings_dir ./fuzz-target

+ 0 - 33
scripts/fuzz-cache-sync/main.c

@@ -1,33 +0,0 @@
-
-#define BORG_NO_PYTHON
-
-#include "../../src/borg/_hashindex.c"
-#include "../../src/borg/cache_sync/cache_sync.c"
-
-#define BUFSZ 32768
-
-int main() {
-    char buf[BUFSZ];
-    int len, ret;
-    CacheSyncCtx *ctx;
-    HashIndex *idx;
-
-    /* capacity, key size, value size */
-    idx = hashindex_init(0, 32, 12);
-    ctx = cache_sync_init(idx);
-
-    while (1) {
-        len = read(0, buf, BUFSZ);
-        if (!len) {
-            break;
-        }
-        ret = cache_sync_feed(ctx, buf, len);
-        if(!ret && cache_sync_error(ctx)) {
-            fprintf(stderr, "error: %s\n", cache_sync_error(ctx));
-            return 1;
-        }
-    }
-    hashindex_free(idx);
-    cache_sync_free(ctx);
-    return 0;
-}

二进制
scripts/fuzz-cache-sync/testcase_dir/test_simple


+ 0 - 138
src/borg/cache_sync/cache_sync.c

@@ -1,138 +0,0 @@
-/*
- * Borg cache synchronizer,
- * high level interface.
- *
- * These routines parse msgpacked item metadata and update a HashIndex
- * with all chunks that are referenced from the items.
- *
- * This file only contains some initialization and buffer management.
- *
- * The parser is split in two parts, somewhat similar to lexer/parser combinations:
- *
- * unpack_template.h munches msgpack and calls a specific callback for each object
- * encountered (e.g. beginning of a map, an integer, a string, a map item etc.).
- *
- * unpack.h implements these callbacks and uses another state machine to
- * extract chunk references from it.
- */
-
-#include "unpack.h"
-
-typedef struct {
-    unpack_context ctx;
-
-    char *buf;
-    size_t head;
-    size_t tail;
-    size_t size;
-} CacheSyncCtx;
-
-static CacheSyncCtx *
-cache_sync_init(HashIndex *chunks)
-{
-    CacheSyncCtx *ctx;
-    if (!(ctx = (CacheSyncCtx*)malloc(sizeof(CacheSyncCtx)))) {
-        return NULL;
-    }
-
-    unpack_init(&ctx->ctx);
-    /* needs to be set only once */
-    ctx->ctx.user.chunks = chunks;
-    ctx->ctx.user.totals.size = 0;
-    ctx->ctx.user.totals.num_files = 0;
-    ctx->buf = NULL;
-    ctx->head = 0;
-    ctx->tail = 0;
-    ctx->size = 0;
-
-    return ctx;
-}
-
-static void
-cache_sync_free(CacheSyncCtx *ctx)
-{
-    if(ctx->buf) {
-        free(ctx->buf);
-    }
-    free(ctx);
-}
-
-static const char *
-cache_sync_error(const CacheSyncCtx *ctx)
-{
-    return ctx->ctx.user.last_error;
-}
-
-static uint64_t
-cache_sync_num_files_totals(const CacheSyncCtx *ctx)
-{
-    return ctx->ctx.user.totals.num_files;
-}
-
-static uint64_t
-cache_sync_size_totals(const CacheSyncCtx *ctx)
-{
-    return ctx->ctx.user.totals.size;
-}
-
-/**
- * feed data to the cache synchronizer
- * 0 = abort, 1 = continue
- * abort is a regular condition, check cache_sync_error
- */
-static int
-cache_sync_feed(CacheSyncCtx *ctx, void *data, uint32_t length)
-{
-    size_t new_size;
-    int ret;
-    char *new_buf;
-
-    if(ctx->tail + length > ctx->size) {
-        if((ctx->tail - ctx->head) + length <= ctx->size) {
-            /* |  XXXXX| -> move data in buffer backwards -> |XXXXX  | */
-            memmove(ctx->buf, ctx->buf + ctx->head, ctx->tail - ctx->head);
-            ctx->tail -= ctx->head;
-            ctx->head = 0;
-        } else {
-            /* must expand buffer to fit all data */
-            new_size = (ctx->tail - ctx->head) + length;
-            new_buf = (char*) malloc(new_size);
-            if(!new_buf) {
-                ctx->ctx.user.last_error = "cache_sync_feed: unable to allocate buffer";
-                return 0;
-            }
-            if(ctx->buf) {
-                memcpy(new_buf, ctx->buf + ctx->head, ctx->tail - ctx->head);
-                free(ctx->buf);
-            }
-            ctx->buf = new_buf;
-            ctx->tail -= ctx->head;
-            ctx->head = 0;
-            ctx->size = new_size;
-        }
-    }
-
-    memcpy(ctx->buf + ctx->tail, data, length);
-    ctx->tail += length;
-
-    while(1) {
-        if(ctx->head >= ctx->tail) {
-            return 1;  /* request more bytes */
-        }
-
-        ret = unpack_execute(&ctx->ctx, ctx->buf, ctx->tail, &ctx->head);
-        if(ret == 1) {
-            unpack_init(&ctx->ctx);
-            continue;
-        } else if(ret == 0) {
-            return 1;
-        } else {
-            if(!ctx->ctx.user.last_error) {
-                ctx->ctx.user.last_error = "Unknown error";
-            }
-            return 0;
-        }
-    }
-    /* unreachable */
-    return 1;
-}

+ 0 - 194
src/borg/cache_sync/sysdep.h

@@ -1,194 +0,0 @@
-/*
- * MessagePack system dependencies
- *
- * Copyright (C) 2008-2010 FURUHASHI Sadayuki
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        https://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-#ifndef MSGPACK_SYSDEP_H__
-#define MSGPACK_SYSDEP_H__
-
-#include <stdlib.h>
-#include <stddef.h>
-#if defined(_MSC_VER) && _MSC_VER < 1600
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-#elif defined(_MSC_VER)  // && _MSC_VER >= 1600
-#include <stdint.h>
-#else
-#include <stdint.h>
-#include <stdbool.h>
-#endif
-
-#ifdef _WIN32
-#define _msgpack_atomic_counter_header <windows.h>
-typedef long _msgpack_atomic_counter_t;
-#define _msgpack_sync_decr_and_fetch(ptr) InterlockedDecrement(ptr)
-#define _msgpack_sync_incr_and_fetch(ptr) InterlockedIncrement(ptr)
-#elif defined(__GNUC__) && ((__GNUC__*10 + __GNUC_MINOR__) < 41)
-#define _msgpack_atomic_counter_header "gcc_atomic.h"
-#else
-typedef unsigned int _msgpack_atomic_counter_t;
-#define _msgpack_sync_decr_and_fetch(ptr) __sync_sub_and_fetch(ptr, 1)
-#define _msgpack_sync_incr_and_fetch(ptr) __sync_add_and_fetch(ptr, 1)
-#endif
-
-#ifdef _WIN32
-
-#ifdef __cplusplus
-/* numeric_limits<T>::min,max */
-#ifdef max
-#undef max
-#endif
-#ifdef min
-#undef min
-#endif
-#endif
-
-#else
-#include <arpa/inet.h>  /* __BYTE_ORDER */
-#endif
-
-#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define __LITTLE_ENDIAN__
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define __BIG_ENDIAN__
-#elif _WIN32
-#define __LITTLE_ENDIAN__
-#endif
-#endif
-
-
-#ifdef __LITTLE_ENDIAN__
-
-#ifdef _WIN32
-#  if defined(ntohs)
-#    define _msgpack_be16(x) ntohs(x)
-#  elif defined(_byteswap_ushort) || (defined(_MSC_VER) && _MSC_VER >= 1400)
-#    define _msgpack_be16(x) ((uint16_t)_byteswap_ushort((unsigned short)x))
-#  else
-#    define _msgpack_be16(x) ( \
-        ((((uint16_t)x) <<  8) ) | \
-        ((((uint16_t)x) >>  8) ) )
-#  endif
-#else
-#  define _msgpack_be16(x) ntohs(x)
-#endif
-
-#ifdef _WIN32
-#  if defined(ntohl)
-#    define _msgpack_be32(x) ntohl(x)
-#  elif defined(_byteswap_ulong) || (defined(_MSC_VER) && _MSC_VER >= 1400)
-#    define _msgpack_be32(x) ((uint32_t)_byteswap_ulong((unsigned long)x))
-#  else
-#    define _msgpack_be32(x) \
-        ( ((((uint32_t)x) << 24)               ) | \
-          ((((uint32_t)x) <<  8) & 0x00ff0000U ) | \
-          ((((uint32_t)x) >>  8) & 0x0000ff00U ) | \
-          ((((uint32_t)x) >> 24)               ) )
-#  endif
-#else
-#  define _msgpack_be32(x) ntohl(x)
-#endif
-
-#if defined(_byteswap_uint64) || (defined(_MSC_VER) && _MSC_VER >= 1400)
-#  define _msgpack_be64(x) (_byteswap_uint64(x))
-#elif defined(bswap_64)
-#  define _msgpack_be64(x) bswap_64(x)
-#elif defined(__DARWIN_OSSwapInt64)
-#  define _msgpack_be64(x) __DARWIN_OSSwapInt64(x)
-#else
-#define _msgpack_be64(x) \
-    ( ((((uint64_t)x) << 56)                         ) | \
-      ((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \
-      ((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \
-      ((((uint64_t)x) <<  8) & 0x000000ff00000000ULL ) | \
-      ((((uint64_t)x) >>  8) & 0x00000000ff000000ULL ) | \
-      ((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \
-      ((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \
-      ((((uint64_t)x) >> 56)                         ) )
-#endif
-
-#define _msgpack_load16(cast, from) ((cast)( \
-        (((uint16_t)((uint8_t*)(from))[0]) << 8) | \
-        (((uint16_t)((uint8_t*)(from))[1])     ) ))
-
-#define _msgpack_load32(cast, from) ((cast)( \
-        (((uint32_t)((uint8_t*)(from))[0]) << 24) | \
-        (((uint32_t)((uint8_t*)(from))[1]) << 16) | \
-        (((uint32_t)((uint8_t*)(from))[2]) <<  8) | \
-        (((uint32_t)((uint8_t*)(from))[3])      ) ))
-
-#define _msgpack_load64(cast, from) ((cast)( \
-        (((uint64_t)((uint8_t*)(from))[0]) << 56) | \
-        (((uint64_t)((uint8_t*)(from))[1]) << 48) | \
-        (((uint64_t)((uint8_t*)(from))[2]) << 40) | \
-        (((uint64_t)((uint8_t*)(from))[3]) << 32) | \
-        (((uint64_t)((uint8_t*)(from))[4]) << 24) | \
-        (((uint64_t)((uint8_t*)(from))[5]) << 16) | \
-        (((uint64_t)((uint8_t*)(from))[6]) << 8)  | \
-        (((uint64_t)((uint8_t*)(from))[7])     )  ))
-
-#else
-
-#define _msgpack_be16(x) (x)
-#define _msgpack_be32(x) (x)
-#define _msgpack_be64(x) (x)
-
-#define _msgpack_load16(cast, from) ((cast)( \
-        (((uint16_t)((uint8_t*)from)[0]) << 8) | \
-        (((uint16_t)((uint8_t*)from)[1])     ) ))
-
-#define _msgpack_load32(cast, from) ((cast)( \
-        (((uint32_t)((uint8_t*)from)[0]) << 24) | \
-        (((uint32_t)((uint8_t*)from)[1]) << 16) | \
-        (((uint32_t)((uint8_t*)from)[2]) <<  8) | \
-        (((uint32_t)((uint8_t*)from)[3])      ) ))
-
-#define _msgpack_load64(cast, from) ((cast)( \
-        (((uint64_t)((uint8_t*)from)[0]) << 56) | \
-        (((uint64_t)((uint8_t*)from)[1]) << 48) | \
-        (((uint64_t)((uint8_t*)from)[2]) << 40) | \
-        (((uint64_t)((uint8_t*)from)[3]) << 32) | \
-        (((uint64_t)((uint8_t*)from)[4]) << 24) | \
-        (((uint64_t)((uint8_t*)from)[5]) << 16) | \
-        (((uint64_t)((uint8_t*)from)[6]) << 8)  | \
-        (((uint64_t)((uint8_t*)from)[7])     )  ))
-#endif
-
-
-#define _msgpack_store16(to, num) \
-    do { uint16_t val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0)
-#define _msgpack_store32(to, num) \
-    do { uint32_t val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0)
-#define _msgpack_store64(to, num) \
-    do { uint64_t val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0)
-
-/*
-#define _msgpack_load16(cast, from) \
-    ({ cast val; memcpy(&val, (char*)from, 2); _msgpack_be16(val); })
-#define _msgpack_load32(cast, from) \
-    ({ cast val; memcpy(&val, (char*)from, 4); _msgpack_be32(val); })
-#define _msgpack_load64(cast, from) \
-    ({ cast val; memcpy(&val, (char*)from, 8); _msgpack_be64(val); })
-*/
-
-
-#endif /* msgpack/sysdep.h */

+ 0 - 416
src/borg/cache_sync/unpack.h

@@ -1,416 +0,0 @@
-/*
- * Borg cache synchronizer,
- * based on a MessagePack for Python unpacking routine
- *
- * Copyright (C) 2009 Naoki INADA
- * Copyright (c) 2017 Marian Beermann
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        https://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-/*
- * This limits the depth of the structures we can unpack, i.e. how many containers
- * are nestable.
- */
-#define MSGPACK_EMBED_STACK_SIZE  (16)
-#include "unpack_define.h"
-
-// 2**32 - 1025
-#define _MAX_VALUE ( (uint32_t) 4294966271UL )
-
-#define MIN(x, y) ((x) < (y) ? (x): (y))
-
-#ifdef DEBUG
-#define SET_LAST_ERROR(msg) \
-  fprintf(stderr, "cache_sync parse error: %s\n", (msg)); \
-  u->last_error = (msg);
-#else
-#define SET_LAST_ERROR(msg) \
-  u->last_error = (msg);
-#endif
-
-typedef struct unpack_user {
-    /* Item.chunks is at the top level; we don't care about anything else,
-     * only need to track the current level to navigate arbitrary and unknown structure.
-     * To discern keys from everything else on the top level we use expect_map_item_end.
-     */
-    int level;
-
-    const char *last_error;
-
-    HashIndex *chunks;
-
-    /*
-     * We don't care about most stuff. This flag tells us whether we're at the chunks structure,
-     * meaning:
-     * {'foo': 'bar', 'chunks': [...], 'stuff': ... }
-     *                        ^-HERE-^
-     */
-    int inside_chunks;
-
-    /* does this item have a chunks list in it? */
-    int has_chunks;
-
-    enum {
-        /* the next thing is a map key at the Item root level,
-         * and it might be e.g. the "chunks" key we're looking for */
-        expect_map_key,
-
-        /* blocking state to expect_map_key
-         * {     'stuff': <complex and arbitrary structure>,     'chunks': [
-         * emk     ->   emie    ->   ->       ->      ->   emk   ecb       eeboce
-         *                (nested containers are tracked via level)
-         * emk=expect_map_key, emie=expect_map_item_end, ecb=expect_chunks_begin,
-         * eeboce=expect_entry_begin_or_chunks_end
-         */
-        expect_map_item_end,
-
-        /* next thing must be the chunks array (array) */
-        expect_chunks_begin,
-
-        /* next thing must either be another CLE (array) or end of Item.chunks (array_end) */
-        expect_entry_begin_or_chunks_end,
-
-        /*
-         * processing ChunkListEntry tuple:
-         * expect_key, expect_size, expect_entry_end
-         */
-        /* next thing must be the key (raw, l=32) */
-        expect_key,
-        /* next thing must be the size (int) */
-        expect_size,
-        /* next thing must be the end of the CLE (array_end) */
-        expect_entry_end,
-
-        expect_item_begin
-    } expect;
-
-    /* collect values here for current chunklist entry */
-    struct {
-        unsigned char key[32];
-        uint32_t size;
-    } current;
-
-    /* summing up chunks sizes here within a single item */
-    struct {
-        uint64_t size;
-    } item;
-
-    /* total sizes and files count coming from all files */
-    struct {
-        uint64_t size, num_files;
-    } totals;
-
-} unpack_user;
-
-struct unpack_context;
-typedef struct unpack_context unpack_context;
-typedef int (*execute_fn)(unpack_context *ctx, const char* data, size_t len, size_t* off);
-
-#define UNEXPECTED(what)                                            \
-    if(u->inside_chunks || u->expect == expect_map_key) { \
-        SET_LAST_ERROR("Unexpected object: " what);                 \
-        return -1;                                                  \
-    }
-
-static inline void unpack_init_user_state(unpack_user *u)
-{
-    u->last_error = NULL;
-    u->level = 0;
-    u->inside_chunks = 0;
-    u->expect = expect_item_begin;
-}
-
-static inline int unpack_callback_uint64(unpack_user* u, int64_t d)
-{
-    switch(u->expect) {
-        case expect_size:
-            u->current.size = d;
-            u->expect = expect_entry_end;
-            break;
-        default:
-            UNEXPECTED("integer");
-    }
-    return 0;
-}
-
-static inline int unpack_callback_uint32(unpack_user* u, uint32_t d)
-{
-    return unpack_callback_uint64(u, d);
-}
-
-static inline int unpack_callback_uint16(unpack_user* u, uint16_t d)
-{
-    return unpack_callback_uint64(u, d);
-}
-
-static inline int unpack_callback_uint8(unpack_user* u, uint8_t d)
-{
-    return unpack_callback_uint64(u, d);
-}
-
-static inline int unpack_callback_int64(unpack_user* u, uint64_t d)
-{
-    return unpack_callback_uint64(u, d);
-}
-
-static inline int unpack_callback_int32(unpack_user* u, int32_t d)
-{
-    return unpack_callback_uint64(u, d);
-}
-
-static inline int unpack_callback_int16(unpack_user* u, int16_t d)
-{
-    return unpack_callback_uint64(u, d);
-}
-
-static inline int unpack_callback_int8(unpack_user* u, int8_t d)
-{
-    return unpack_callback_uint64(u, d);
-}
-
-/* Ain't got anything to do with those floats */
-static inline int unpack_callback_double(unpack_user* u, double d)
-{
-    (void)d;
-    UNEXPECTED("double");
-    return 0;
-}
-
-static inline int unpack_callback_float(unpack_user* u, float d)
-{
-    (void)d;
-    UNEXPECTED("float");
-    return 0;
-}
-
-/* nil/true/false — I/don't/care */
-static inline int unpack_callback_nil(unpack_user* u)
-{
-    UNEXPECTED("nil");
-    return 0;
-}
-
-static inline int unpack_callback_true(unpack_user* u)
-{
-    UNEXPECTED("true");
-    return 0;
-}
-
-static inline int unpack_callback_false(unpack_user* u)
-{
-    UNEXPECTED("false");
-    return 0;
-}
-
-static inline int unpack_callback_array(unpack_user* u, unsigned int n)
-{
-    switch(u->expect) {
-    case expect_chunks_begin:
-        /* b'chunks': [
-         *            ^ */
-        u->expect = expect_entry_begin_or_chunks_end;
-        break;
-    case expect_entry_begin_or_chunks_end:
-        /* b'chunks': [ (
-         *              ^ */
-        if(n != 2) {
-            SET_LAST_ERROR("Invalid chunk list entry length");
-            return -1;
-        }
-        u->expect = expect_key;
-        break;
-    default:
-        if(u->inside_chunks) {
-            SET_LAST_ERROR("Unexpected array start");
-            return -1;
-        } else {
-            u->level++;
-            return 0;
-        }
-    }
-    return 0;
-}
-
-static inline int unpack_callback_array_item(unpack_user* u, unsigned int current)
-{
-    (void)u; (void)current;
-    return 0;
-}
-
-static inline int unpack_callback_array_end(unpack_user* u)
-{
-    uint32_t *cache_entry;
-    uint32_t cache_values[3];
-    uint64_t refcount;
-
-    switch(u->expect) {
-    case expect_entry_end:
-        /* b'chunks': [ ( b'1234...', 123, 345 )
-         *                                     ^ */
-        cache_entry = (uint32_t*) hashindex_get(u->chunks, u->current.key);
-        if(cache_entry) {
-            refcount = _le32toh(cache_entry[0]);
-            if(refcount > _MAX_VALUE) {
-                SET_LAST_ERROR("invalid reference count");
-                return -1;
-            }
-            refcount += 1;
-            cache_entry[0] = _htole32(MIN(refcount, _MAX_VALUE));
-        } else {
-            /* refcount, size */
-            cache_values[0] = _htole32(1);
-            cache_values[1] = _htole32(u->current.size);
-            if(!hashindex_set(u->chunks, u->current.key, cache_values)) {
-                SET_LAST_ERROR("hashindex_set failed");
-                return -1;
-            }
-        }
-        u->item.size += u->current.size;
-        u->expect = expect_entry_begin_or_chunks_end;
-        break;
-    case expect_entry_begin_or_chunks_end:
-        /* b'chunks': [ ]
-         *              ^ */
-        /* end of Item.chunks */
-        u->inside_chunks = 0;
-        u->expect = expect_map_item_end;
-        break;
-    default:
-        if(u->inside_chunks) {
-            SET_LAST_ERROR("Invalid state transition (unexpected array end)");
-            return -1;
-        } else {
-            u->level--;
-            return 0;
-        }
-    }
-    return 0;
-}
-
-static inline int unpack_callback_map(unpack_user* u, unsigned int n)
-{
-    (void)n;
-
-    if(u->level == 0) {
-        if(u->expect != expect_item_begin) {
-            SET_LAST_ERROR("Invalid state transition");  /* unreachable */
-            return -1;
-        }
-        /* This begins a new Item */
-        u->expect = expect_map_key;
-        u->has_chunks = 0;
-        u->item.size = 0;
-    }
-
-    if(u->inside_chunks) {
-        UNEXPECTED("map");
-    }
-
-    u->level++;
-
-    return 0;
-}
-
-static inline int unpack_callback_map_item(unpack_user* u, unsigned int current)
-{
-    (void)u; (void)current;
-
-    if(u->level == 1) {
-        switch(u->expect) {
-        case expect_map_item_end:
-            u->expect = expect_map_key;
-            break;
-        default:
-            SET_LAST_ERROR("Unexpected map item");
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static inline int unpack_callback_map_end(unpack_user* u)
-{
-    u->level--;
-    if(u->inside_chunks) {
-        SET_LAST_ERROR("Unexpected map end");
-        return -1;
-    }
-    if(u->level == 0) {
-        /* This ends processing of an Item */
-        if(u->has_chunks) {
-            u->totals.num_files += 1;
-            u->totals.size += u->item.size;
-        }
-    }
-    return 0;
-}
-
-static inline int unpack_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int length)
-{
-    /* raw = what Borg uses for text stuff */
-    /* Note: p points to an internal buffer which contains l bytes. */
-    (void)b;
-
-    switch(u->expect) {
-    case expect_map_key:
-        if(length == 6 && !memcmp("chunks", p, 6)) {
-            u->expect = expect_chunks_begin;
-            u->inside_chunks = 1;
-            u->has_chunks = 1;
-        } else {
-            u->expect = expect_map_item_end;
-        }
-        break;
-    default:
-        if(u->inside_chunks) {
-            SET_LAST_ERROR("Unexpected raw in chunks structure");
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static inline int unpack_callback_bin(unpack_user* u, const char* b, const char* p, unsigned int length)
-{
-    /* bin = what Borg uses for binary stuff */
-    /* Note: p points to an internal buffer which contains l bytes. */
-    (void)b;
-
-    switch(u->expect) {
-    case expect_key:
-        if(length != 32) {
-            SET_LAST_ERROR("Incorrect key length");
-            return -1;
-        }
-        memcpy(u->current.key, p, 32);
-        u->expect = expect_size;
-        break;
-    default:
-        if(u->inside_chunks) {
-            SET_LAST_ERROR("Unexpected bytes in chunks structure");
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static inline int unpack_callback_ext(unpack_user* u, const char* base, const char* pos,
-                                      unsigned int length)
-{
-    (void)u; (void)base; (void)pos; (void)length;
-    UNEXPECTED("ext");
-    return 0;
-}
-
-#include "unpack_template.h"

+ 0 - 95
src/borg/cache_sync/unpack_define.h

@@ -1,95 +0,0 @@
-/*
- * MessagePack unpacking routine template
- *
- * Copyright (C) 2008-2010 FURUHASHI Sadayuki
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        https://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-#ifndef MSGPACK_UNPACK_DEFINE_H__
-#define MSGPACK_UNPACK_DEFINE_H__
-
-#include "sysdep.h"
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifndef MSGPACK_EMBED_STACK_SIZE
-#define MSGPACK_EMBED_STACK_SIZE 32
-#endif
-
-
-// CS is first byte & 0x1f
-typedef enum {
-    CS_HEADER            = 0x00,  // nil
-
-    //CS_                = 0x01,
-    //CS_                = 0x02,  // false
-    //CS_                = 0x03,  // true
-
-    CS_BIN_8             = 0x04,
-    CS_BIN_16            = 0x05,
-    CS_BIN_32            = 0x06,
-
-    CS_EXT_8             = 0x07,
-    CS_EXT_16            = 0x08,
-    CS_EXT_32            = 0x09,
-
-    CS_FLOAT             = 0x0a,
-    CS_DOUBLE            = 0x0b,
-    CS_UINT_8            = 0x0c,
-    CS_UINT_16           = 0x0d,
-    CS_UINT_32           = 0x0e,
-    CS_UINT_64           = 0x0f,
-    CS_INT_8             = 0x10,
-    CS_INT_16            = 0x11,
-    CS_INT_32            = 0x12,
-    CS_INT_64            = 0x13,
-
-    //CS_FIXEXT1           = 0x14,
-    //CS_FIXEXT2           = 0x15,
-    //CS_FIXEXT4           = 0x16,
-    //CS_FIXEXT8           = 0x17,
-    //CS_FIXEXT16          = 0x18,
-
-    CS_RAW_8             = 0x19,
-    CS_RAW_16            = 0x1a,
-    CS_RAW_32            = 0x1b,
-    CS_ARRAY_16          = 0x1c,
-    CS_ARRAY_32          = 0x1d,
-    CS_MAP_16            = 0x1e,
-    CS_MAP_32            = 0x1f,
-
-    ACS_RAW_VALUE,
-    ACS_BIN_VALUE,
-    ACS_EXT_VALUE,
-} msgpack_unpack_state;
-
-
-typedef enum {
-    CT_ARRAY_ITEM,
-    CT_MAP_KEY,
-    CT_MAP_VALUE,
-} msgpack_container_type;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* msgpack/unpack_define.h */

+ 0 - 365
src/borg/cache_sync/unpack_template.h

@@ -1,365 +0,0 @@
-/*
- * MessagePack unpacking routine template
- *
- * Copyright (C) 2008-2010 FURUHASHI Sadayuki
- * Copyright (c) 2017 Marian Beermann
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        https://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- *
- *
- * This has been slightly adapted from the vanilla msgpack-{c, python} version.
- * Since cache_sync does not intend to build an output data structure,
- * msgpack_unpack_object and all of its uses was removed.
- */
-
-#ifndef USE_CASE_RANGE
-#if !defined(_MSC_VER)
-#define USE_CASE_RANGE
-#endif
-#endif
-
-typedef struct unpack_stack {
-    size_t size;
-    size_t count;
-    unsigned int ct;
-} unpack_stack;
-
-struct unpack_context {
-    unpack_user user;
-    unsigned int cs;
-    unsigned int trail;
-    unsigned int top;
-    unpack_stack stack[MSGPACK_EMBED_STACK_SIZE];
-};
-
-static inline void unpack_init(unpack_context* ctx)
-{
-    ctx->cs = CS_HEADER;
-    ctx->trail = 0;
-    ctx->top = 0;
-    unpack_init_user_state(&ctx->user);
-}
-
-#define construct 1
-
-static inline int unpack_execute(unpack_context* ctx, const char* data, size_t len, size_t* off)
-{
-    const unsigned char* p = (unsigned char*)data + *off;
-    const unsigned char* const pe = (unsigned char*)data + len;
-    const void* n = NULL;
-
-    unsigned int trail = ctx->trail;
-    unsigned int cs = ctx->cs;
-    unsigned int top = ctx->top;
-    unpack_stack* stack = ctx->stack;
-    unpack_user* user = &ctx->user;
-
-    unpack_stack* c = NULL;
-
-    int ret;
-
-    assert(len >= *off);
-
-#define construct_cb(name) \
-    construct && unpack_callback ## name
-
-#define push_simple_value(func) \
-    if(construct_cb(func)(user) < 0) { goto _failed; } \
-    goto _push
-#define push_fixed_value(func, arg) \
-    if(construct_cb(func)(user, arg) < 0) { goto _failed; } \
-    goto _push
-#define push_variable_value(func, base, pos, len) \
-    if(construct_cb(func)(user, \
-        (const char*)base, (const char*)pos, len) < 0) { goto _failed; } \
-    goto _push
-
-#define again_fixed_trail(_cs, trail_len) \
-    trail = trail_len; \
-    cs = _cs; \
-    goto _fixed_trail_again
-#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
-    trail = trail_len; \
-    if(trail == 0) { goto ifzero; } \
-    cs = _cs; \
-    goto _fixed_trail_again
-
-#define start_container(func, count_, ct_) \
-    if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \
-    if(construct_cb(func)(user, count_) < 0) { goto _failed; } \
-    if((count_) == 0) { \
-        if (construct_cb(func##_end)(user) < 0) { goto _failed; } \
-        goto _push; } \
-    stack[top].ct = ct_; \
-    stack[top].size  = count_; \
-    stack[top].count = 0; \
-    ++top; \
-    goto _header_again
-
-#define NEXT_CS(p)  ((unsigned int)*p & 0x1f)
-
-#ifdef USE_CASE_RANGE
-#define SWITCH_RANGE_BEGIN     switch(*p) {
-#define SWITCH_RANGE(FROM, TO) case FROM ... TO:
-#define SWITCH_RANGE_DEFAULT   default:
-#define SWITCH_RANGE_END       }
-#else
-#define SWITCH_RANGE_BEGIN     { if(0) {
-#define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) {
-#define SWITCH_RANGE_DEFAULT   } else {
-#define SWITCH_RANGE_END       } }
-#endif
-
-    if(p == pe) { goto _out; }
-    do {
-        switch(cs) {
-        case CS_HEADER:
-            SWITCH_RANGE_BEGIN
-            SWITCH_RANGE(0x00, 0x7f)  // Positive Fixnum
-                push_fixed_value(_uint8, *(uint8_t*)p);
-            SWITCH_RANGE(0xe0, 0xff)  // Negative Fixnum
-                push_fixed_value(_int8, *(int8_t*)p);
-            SWITCH_RANGE(0xc0, 0xdf)  // Variable
-                switch(*p) {
-                case 0xc0:  // nil
-                    push_simple_value(_nil);
-                //case 0xc1:  // never used
-                case 0xc2:  // false
-                    push_simple_value(_false);
-                case 0xc3:  // true
-                    push_simple_value(_true);
-                case 0xc4:  // bin 8
-                    again_fixed_trail(NEXT_CS(p), 1);
-                case 0xc5:  // bin 16
-                    again_fixed_trail(NEXT_CS(p), 2);
-                case 0xc6:  // bin 32
-                    again_fixed_trail(NEXT_CS(p), 4);
-                case 0xc7:  // ext 8
-                    again_fixed_trail(NEXT_CS(p), 1);
-                case 0xc8:  // ext 16
-                    again_fixed_trail(NEXT_CS(p), 2);
-                case 0xc9:  // ext 32
-                    again_fixed_trail(NEXT_CS(p), 4);
-                case 0xca:  // float
-                case 0xcb:  // double
-                case 0xcc:  // unsigned int  8
-                case 0xcd:  // unsigned int 16
-                case 0xce:  // unsigned int 32
-                case 0xcf:  // unsigned int 64
-                case 0xd0:  // signed int  8
-                case 0xd1:  // signed int 16
-                case 0xd2:  // signed int 32
-                case 0xd3:  // signed int 64
-                    again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
-                case 0xd4:  // fixext 1
-                case 0xd5:  // fixext 2
-                case 0xd6:  // fixext 4
-                case 0xd7:  // fixext 8
-                    again_fixed_trail_if_zero(ACS_EXT_VALUE, 
-                                              (1 << (((unsigned int)*p) & 0x03))+1,
-                                              _ext_zero);
-                case 0xd8:  // fixext 16
-                    again_fixed_trail_if_zero(ACS_EXT_VALUE, 16+1, _ext_zero);
-                case 0xd9:  // str 8
-                    again_fixed_trail(NEXT_CS(p), 1);
-                case 0xda:  // raw 16
-                case 0xdb:  // raw 32
-                case 0xdc:  // array 16
-                case 0xdd:  // array 32
-                case 0xde:  // map 16
-                case 0xdf:  // map 32
-                    again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01));
-                default:
-                    goto _failed;
-                }
-            SWITCH_RANGE(0xa0, 0xbf)  // FixRaw
-                again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero);
-            SWITCH_RANGE(0x90, 0x9f)  // FixArray
-                start_container(_array, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM);
-            SWITCH_RANGE(0x80, 0x8f)  // FixMap
-                start_container(_map, ((unsigned int)*p) & 0x0f, CT_MAP_KEY);
-
-            SWITCH_RANGE_DEFAULT
-                goto _failed;
-            SWITCH_RANGE_END
-            // end CS_HEADER
-
-
-        _fixed_trail_again:
-            ++p; // fallthrough
-
-        default:
-            if((size_t)(pe - p) < trail) { goto _out; }
-            n = p;  p += trail - 1;
-            switch(cs) {
-            case CS_EXT_8:
-                again_fixed_trail_if_zero(ACS_EXT_VALUE, *(uint8_t*)n+1, _ext_zero);
-            case CS_EXT_16:
-                again_fixed_trail_if_zero(ACS_EXT_VALUE,
-                                          _msgpack_load16(uint16_t,n)+1,
-                                          _ext_zero);
-            case CS_EXT_32:
-                again_fixed_trail_if_zero(ACS_EXT_VALUE,
-                                          _msgpack_load32(uint32_t,n)+1,
-                                          _ext_zero);
-            case CS_FLOAT: {
-                    union { uint32_t i; float f; } mem;
-                    mem.i = _msgpack_load32(uint32_t,n);
-                    push_fixed_value(_float, mem.f); }
-            case CS_DOUBLE: {
-                    union { uint64_t i; double f; } mem;
-                    mem.i = _msgpack_load64(uint64_t,n);
-#if defined(__arm__) && !(__ARM_EABI__) // arm-oabi
-                    // https://github.com/msgpack/msgpack-perl/pull/1
-                    mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
-#endif
-                    push_fixed_value(_double, mem.f); }
-            case CS_UINT_8:
-                push_fixed_value(_uint8, *(uint8_t*)n);
-            case CS_UINT_16:
-                push_fixed_value(_uint16, _msgpack_load16(uint16_t,n));
-            case CS_UINT_32:
-                push_fixed_value(_uint32, _msgpack_load32(uint32_t,n));
-            case CS_UINT_64:
-                push_fixed_value(_uint64, _msgpack_load64(uint64_t,n));
-
-            case CS_INT_8:
-                push_fixed_value(_int8, *(int8_t*)n);
-            case CS_INT_16:
-                push_fixed_value(_int16, _msgpack_load16(int16_t,n));
-            case CS_INT_32:
-                push_fixed_value(_int32, _msgpack_load32(int32_t,n));
-            case CS_INT_64:
-                push_fixed_value(_int64, _msgpack_load64(int64_t,n));
-
-            case CS_BIN_8:
-                again_fixed_trail_if_zero(ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero);
-            case CS_BIN_16:
-                again_fixed_trail_if_zero(ACS_BIN_VALUE, _msgpack_load16(uint16_t,n), _bin_zero);
-            case CS_BIN_32:
-                again_fixed_trail_if_zero(ACS_BIN_VALUE, _msgpack_load32(uint32_t,n), _bin_zero);
-            case ACS_BIN_VALUE:
-            _bin_zero:
-                push_variable_value(_bin, data, n, trail);
-
-            case CS_RAW_8:
-                again_fixed_trail_if_zero(ACS_RAW_VALUE, *(uint8_t*)n, _raw_zero);
-            case CS_RAW_16:
-                again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load16(uint16_t,n), _raw_zero);
-            case CS_RAW_32:
-                again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load32(uint32_t,n), _raw_zero);
-            case ACS_RAW_VALUE:
-            _raw_zero:
-                push_variable_value(_raw, data, n, trail);
-
-            case ACS_EXT_VALUE:
-            _ext_zero:
-                push_variable_value(_ext, data, n, trail);
-
-            case CS_ARRAY_16:
-                start_container(_array, _msgpack_load16(uint16_t,n), CT_ARRAY_ITEM);
-            case CS_ARRAY_32:
-                /* FIXME security guard */
-                start_container(_array, _msgpack_load32(uint32_t,n), CT_ARRAY_ITEM);
-
-            case CS_MAP_16:
-                start_container(_map, _msgpack_load16(uint16_t,n), CT_MAP_KEY);
-            case CS_MAP_32:
-                /* FIXME security guard */
-                start_container(_map, _msgpack_load32(uint32_t,n), CT_MAP_KEY);
-
-            default:
-                goto _failed;
-            }
-        }
-
-_push:
-    if(top == 0) { goto _finish; }
-    c = &stack[top-1];
-    switch(c->ct) {
-    case CT_ARRAY_ITEM:
-        if(construct_cb(_array_item)(user, c->count) < 0) { goto _failed; }
-        if(++c->count == c->size) {
-            if (construct_cb(_array_end)(user) < 0) { goto _failed; }
-            --top;
-            /*printf("stack pop %d\n", top);*/
-            goto _push;
-        }
-        goto _header_again;
-    case CT_MAP_KEY:
-        c->ct = CT_MAP_VALUE;
-        goto _header_again;
-    case CT_MAP_VALUE:
-        if(construct_cb(_map_item)(user, c->count) < 0) { goto _failed; }
-        if(++c->count == c->size) {
-            if (construct_cb(_map_end)(user) < 0) { goto _failed; }
-            --top;
-            /*printf("stack pop %d\n", top);*/
-            goto _push;
-        }
-        c->ct = CT_MAP_KEY;
-        goto _header_again;
-
-    default:
-        goto _failed;
-    }
-
-_header_again:
-        cs = CS_HEADER;
-        ++p;
-    } while(p != pe);
-    goto _out;
-
-
-_finish:
-    if (!construct)
-        unpack_callback_nil(user);
-    ++p;
-    ret = 1;
-    /* printf("-- finish --\n"); */
-    goto _end;
-
-_failed:
-    /* printf("** FAILED **\n"); */
-    ret = -1;
-    goto _end;
-
-_out:
-    ret = 0;
-    goto _end;
-
-_end:
-    ctx->cs = cs;
-    ctx->trail = trail;
-    ctx->top = top;
-    *off = p - (const unsigned char*)data;
-
-    return ret;
-#undef construct_cb
-}
-
-#undef SWITCH_RANGE_BEGIN
-#undef SWITCH_RANGE
-#undef SWITCH_RANGE_DEFAULT
-#undef SWITCH_RANGE_END
-#undef push_simple_value
-#undef push_fixed_value
-#undef push_variable_value
-#undef again_fixed_trail
-#undef again_fixed_trail_if_zero
-#undef start_container
-#undef construct
-
-#undef NEXT_CS
-
-/* vim: set ts=4 sw=4 sts=4 expandtab  */

+ 1 - 52
src/borg/hashindex.pyx

@@ -34,19 +34,7 @@ cdef extern from "_hashindex.c":
     double HASH_MAX_LOAD
 
 
-cdef extern from "cache_sync/cache_sync.c":
-    ctypedef struct CacheSyncCtx:
-        pass
-
-    CacheSyncCtx *cache_sync_init(HashIndex *chunks)
-    const char *cache_sync_error(const CacheSyncCtx *ctx)
-    uint64_t cache_sync_num_files_totals(const CacheSyncCtx *ctx)
-    uint64_t cache_sync_size_totals(const CacheSyncCtx *ctx)
-    int cache_sync_feed(CacheSyncCtx *ctx, void *data, uint32_t length)
-    void cache_sync_free(CacheSyncCtx *ctx)
-
-    uint32_t _MAX_VALUE
-
+_MAX_VALUE = 4294966271UL  # 2**32 - 1025
 
 cdef _NoDefault = object()
 
@@ -592,42 +580,3 @@ cdef class ChunkKeyIterator:
         cdef uint32_t refcount = _le32toh(value[0])
         assert refcount <= _MAX_VALUE, "invalid reference count"
         return (<char *>self.key)[:self.key_size], ChunkIndexEntry(refcount, _le32toh(value[1]))
-
-
-cdef Py_buffer ro_buffer(object data) except *:
-    cdef Py_buffer view
-    PyObject_GetBuffer(data, &view, PyBUF_SIMPLE)
-    return view
-
-
-cdef class CacheSynchronizer:
-    cdef ChunkIndex chunks
-    cdef CacheSyncCtx *sync
-
-    def __cinit__(self, chunks):
-        self.chunks = chunks
-        self.sync = cache_sync_init(self.chunks.index)
-        if not self.sync:
-            raise Exception('cache_sync_init failed')
-
-    def __dealloc__(self):
-        if self.sync:
-            cache_sync_free(self.sync)
-
-    def feed(self, chunk):
-        cdef Py_buffer chunk_buf = ro_buffer(chunk)
-        cdef int rc
-        rc = cache_sync_feed(self.sync, chunk_buf.buf, chunk_buf.len)
-        PyBuffer_Release(&chunk_buf)
-        if not rc:
-            error = cache_sync_error(self.sync)
-            if error != NULL:
-                raise ValueError('cache_sync_feed failed: ' + error.decode('ascii'))
-
-    @property
-    def num_files_totals(self):
-        return cache_sync_num_files_totals(self.sync)
-
-    @property
-    def size_totals(self):
-        return cache_sync_size_totals(self.sync)

+ 1 - 146
src/borg/testsuite/cache.py

@@ -10,156 +10,11 @@ from .key import TestKey
 from ..archive import Statistics
 from ..cache import AdHocCache
 from ..crypto.key import AESOCBRepoKey
-from ..hashindex import ChunkIndex, CacheSynchronizer
+from ..hashindex import ChunkIndex
 from ..manifest import Manifest
 from ..repository3 import Repository3
 
 
-class TestCacheSynchronizer:
-    @pytest.fixture
-    def index(self):
-        return ChunkIndex()
-
-    @pytest.fixture
-    def sync(self, index):
-        return CacheSynchronizer(index)
-
-    def test_no_chunks(self, index, sync):
-        data = packb({"foo": "bar", "baz": 1234, "bar": 5678, "user": "chunks", "chunks": []})
-        sync.feed(data)
-        assert not len(index)
-
-    def test_simple(self, index, sync):
-        data = packb({"foo": "bar", "baz": 1234, "bar": 5678, "user": "chunks", "chunks": [(H(1), 1), (H(2), 2)]})
-        sync.feed(data)
-        assert len(index) == 2
-        assert index[H(1)] == (1, 1)
-        assert index[H(2)] == (1, 2)
-
-    def test_multiple(self, index, sync):
-        data = packb({"foo": "bar", "baz": 1234, "bar": 5678, "user": "chunks", "chunks": [(H(1), 1), (H(2), 2)]})
-        data += packb({"xattrs": {"security.foo": "bar", "chunks": "123456"}, "stuff": [(1, 2, 3)]})
-        data += packb(
-            {
-                "xattrs": {"security.foo": "bar", "chunks": "123456"},
-                "chunks": [(H(1), 1), (H(2), 2)],
-                "stuff": [(1, 2, 3)],
-            }
-        )
-        data += packb({"chunks": [(H(3), 1)]})
-        data += packb({"chunks": [(H(1), 1)]})
-
-        part1 = data[:70]
-        part2 = data[70:120]
-        part3 = data[120:]
-        sync.feed(part1)
-        sync.feed(part2)
-        sync.feed(part3)
-        assert len(index) == 3
-        assert index[H(1)] == (3, 1)
-        assert index[H(2)] == (2, 2)
-        assert index[H(3)] == (1, 1)
-
-    @pytest.mark.parametrize(
-        "elem,error",
-        (
-            ({1: 2}, "Unexpected object: map"),
-            (
-                bytes(213),
-                ["Unexpected bytes in chunks structure", "Incorrect key length"],  # structure 2/3
-            ),  # structure 3/3
-            (1, "Unexpected object: integer"),
-            (1.0, "Unexpected object: double"),
-            (True, "Unexpected object: true"),
-            (False, "Unexpected object: false"),
-            (None, "Unexpected object: nil"),
-        ),
-        ids=["map", "bytes", "int", "double", "true", "false", "none"],
-    )
-    @pytest.mark.parametrize(
-        "structure",
-        (lambda elem: {"chunks": elem}, lambda elem: {"chunks": [elem]}, lambda elem: {"chunks": [(elem, 1)]}),
-    )
-    def test_corrupted(self, sync, structure, elem, error):
-        packed = packb(structure(elem))
-        with pytest.raises(ValueError) as excinfo:
-            sync.feed(packed)
-        if isinstance(error, str):
-            error = [error]
-        possible_errors = ["cache_sync_feed failed: " + error for error in error]
-        assert str(excinfo.value) in possible_errors
-
-    @pytest.mark.parametrize(
-        "data,error",
-        (
-            # Incorrect tuple length
-            ({"chunks": [(bytes(32), 2, 3, 4)]}, "Invalid chunk list entry length"),
-            ({"chunks": [(bytes(32),)]}, "Invalid chunk list entry length"),
-            # Incorrect types
-            ({"chunks": [(1, 2)]}, "Unexpected object: integer"),
-            ({"chunks": [(1, bytes(32))]}, "Unexpected object: integer"),
-            ({"chunks": [(bytes(32), 1.0)]}, "Unexpected object: double"),
-        ),
-    )
-    def test_corrupted_ancillary(self, index, sync, data, error):
-        packed = packb(data)
-        with pytest.raises(ValueError) as excinfo:
-            sync.feed(packed)
-        assert str(excinfo.value) == "cache_sync_feed failed: " + error
-
-    def make_index_with_refcount(self, refcount):
-        index_data = io.BytesIO()
-        index_data.write(b"BORG2IDX")
-        # version
-        index_data.write((2).to_bytes(4, "little"))
-        # num_entries
-        index_data.write((1).to_bytes(4, "little"))
-        # num_buckets
-        index_data.write((1).to_bytes(4, "little"))
-        # num_empty
-        index_data.write((0).to_bytes(4, "little"))
-        # key_size
-        index_data.write((32).to_bytes(4, "little"))
-        # value_size
-        index_data.write((3 * 4).to_bytes(4, "little"))
-        # reserved
-        index_data.write(bytes(1024 - 32))
-
-        index_data.write(H(0))
-        index_data.write(refcount.to_bytes(4, "little"))
-        index_data.write((1234).to_bytes(4, "little"))
-        index_data.write((5678).to_bytes(4, "little"))
-
-        index_data.seek(0)
-        index = ChunkIndex.read(index_data)
-        return index
-
-    def test_corrupted_refcount(self):
-        index = self.make_index_with_refcount(ChunkIndex.MAX_VALUE + 1)
-        sync = CacheSynchronizer(index)
-        data = packb({"chunks": [(H(0), 1)]})
-        with pytest.raises(ValueError) as excinfo:
-            sync.feed(data)
-        assert str(excinfo.value) == "cache_sync_feed failed: invalid reference count"
-
-    def test_refcount_max_value(self):
-        index = self.make_index_with_refcount(ChunkIndex.MAX_VALUE)
-        sync = CacheSynchronizer(index)
-        data = packb({"chunks": [(H(0), 1)]})
-        sync.feed(data)
-        assert index[H(0)] == (ChunkIndex.MAX_VALUE, 1234)
-
-    def test_refcount_one_below_max_value(self):
-        index = self.make_index_with_refcount(ChunkIndex.MAX_VALUE - 1)
-        sync = CacheSynchronizer(index)
-        data = packb({"chunks": [(H(0), 1)]})
-        sync.feed(data)
-        # Incremented to maximum
-        assert index[H(0)] == (ChunkIndex.MAX_VALUE, 1234)
-        sync.feed(data)
-        assert index[H(0)] == (ChunkIndex.MAX_VALUE, 1234)
-
-
 class TestAdHocCache:
     @pytest.fixture
     def repository(self, tmpdir):