Browse Source

Merge branch 'master' of github.com:jborg/attic

Thomas Waldmann 10 years ago
parent
commit
91e10fec5f
2 changed files with 52 additions and 35 deletions
  1. 7 0
      CHANGES
  2. 45 35
      borg/_hashindex.c

+ 7 - 0
CHANGES

@@ -58,6 +58,13 @@ Attic Changelog
 Here you can see the full list of changes between each Attic release until Borg
 Here you can see the full list of changes between each Attic release until Borg
 forked from Attic:
 forked from Attic:
 
 
+Version 0.17
+------------
+
+(bugfix release, released on X)
+- Fix hashindex ARM memory alignment issue (#309)
+- Improve hashindex error messages (#298)
+
 Version 0.16
 Version 0.16
 ------------
 ------------
 
 

+ 45 - 35
borg/_hashindex.c

@@ -27,7 +27,6 @@ typedef struct {
 } __attribute__((__packed__)) HashHeader;
 } __attribute__((__packed__)) HashHeader;
 
 
 typedef struct {
 typedef struct {
-    void *data;
     void *buckets;
     void *buckets;
     int num_entries;
     int num_entries;
     int num_buckets;
     int num_buckets;
@@ -36,7 +35,6 @@ typedef struct {
     off_t bucket_size;
     off_t bucket_size;
     int lower_limit;
     int lower_limit;
     int upper_limit;
     int upper_limit;
-    off_t data_len;
 } HashIndex;
 } HashIndex;
 
 
 #define MAGIC "BORG_IDX"
 #define MAGIC "BORG_IDX"
@@ -57,8 +55,10 @@ typedef struct {
 #define BUCKET_MARK_DELETED(index, idx) (*((uint32_t *)(BUCKET_ADDR(index, idx) + index->key_size)) = DELETED)
 #define BUCKET_MARK_DELETED(index, idx) (*((uint32_t *)(BUCKET_ADDR(index, idx) + index->key_size)) = DELETED)
 #define BUCKET_MARK_EMPTY(index, idx) (*((uint32_t *)(BUCKET_ADDR(index, idx) + index->key_size)) = EMPTY)
 #define BUCKET_MARK_EMPTY(index, idx) (*((uint32_t *)(BUCKET_ADDR(index, idx) + index->key_size)) = EMPTY)
 
 
-#define EPRINTF(msg, ...) fprintf(stderr, "hashindex: " msg "\n", ##__VA_ARGS__)
-#define EPRINTF_PATH(path, msg, ...) fprintf(stderr, "hashindex: %s: " msg "\n", path, ##__VA_ARGS__)
+#define EPRINTF_MSG(msg, ...) fprintf(stderr, "hashindex: " msg "\n", ##__VA_ARGS__)
+#define EPRINTF_MSG_PATH(path, msg, ...) fprintf(stderr, "hashindex: %s: " msg "\n", path, ##__VA_ARGS__)
+#define EPRINTF(msg, ...) fprintf(stderr, "hashindex: " msg "(%s)\n", ##__VA_ARGS__, strerror(errno))
+#define EPRINTF_PATH(path, msg, ...) fprintf(stderr, "hashindex: %s: " msg " (%s)\n", path, ##__VA_ARGS__, strerror(errno))
 
 
 static HashIndex *hashindex_read(const char *path);
 static HashIndex *hashindex_read(const char *path);
 static int hashindex_write(HashIndex *index, const char *path);
 static int hashindex_write(HashIndex *index, const char *path);
@@ -118,13 +118,11 @@ hashindex_resize(HashIndex *index, int capacity)
     while((key = hashindex_next_key(index, key))) {
     while((key = hashindex_next_key(index, key))) {
         hashindex_set(new, key, hashindex_get(index, key));
         hashindex_set(new, key, hashindex_get(index, key));
     }
     }
-    free(index->data);
-    index->data = new->data;
-    index->data_len = new->data_len;
+    free(index->buckets);
+    index->buckets = new->buckets;
     index->num_buckets = new->num_buckets;
     index->num_buckets = new->num_buckets;
     index->lower_limit = new->lower_limit;
     index->lower_limit = new->lower_limit;
     index->upper_limit = new->upper_limit;
     index->upper_limit = new->upper_limit;
-    index->buckets = new->buckets;
     free(new);
     free(new);
     return 1;
     return 1;
 }
 }
@@ -134,8 +132,7 @@ static HashIndex *
 hashindex_read(const char *path)
 hashindex_read(const char *path)
 {
 {
     FILE *fd;
     FILE *fd;
-    off_t length;
-    off_t bytes_read;
+    off_t length, buckets_length, bytes_read;
     HashHeader header;
     HashHeader header;
     HashIndex *index = NULL;
     HashIndex *index = NULL;
 
 
@@ -145,7 +142,12 @@ hashindex_read(const char *path)
     }
     }
     bytes_read = fread(&header, 1, sizeof(HashHeader), fd);
     bytes_read = fread(&header, 1, sizeof(HashHeader), fd);
     if(bytes_read != sizeof(HashHeader)) {
     if(bytes_read != sizeof(HashHeader)) {
-        EPRINTF_PATH(path, "fread header failed (expected %ld, got %ld)", sizeof(HashHeader), bytes_read);
+        if(ferror(fd)) {
+            EPRINTF_PATH(path, "fread header failed (expected %ld, got %ld)", sizeof(HashHeader), bytes_read);
+        }
+        else {
+            EPRINTF_MSG_PATH(path, "fread header failed (expected %ld, got %ld)", sizeof(HashHeader), bytes_read);
+        }
         goto fail;
         goto fail;
     }
     }
     if(fseek(fd, 0, SEEK_END) < 0) {
     if(fseek(fd, 0, SEEK_END) < 0) {
@@ -156,43 +158,47 @@ hashindex_read(const char *path)
         EPRINTF_PATH(path, "ftell failed");
         EPRINTF_PATH(path, "ftell failed");
         goto fail;
         goto fail;
     }
     }
-    if(fseek(fd, 0, SEEK_SET) < 0) {
+    if(fseek(fd, sizeof(HashHeader), SEEK_SET) < 0) {
         EPRINTF_PATH(path, "fseek failed");
         EPRINTF_PATH(path, "fseek failed");
         goto fail;
         goto fail;
     }
     }
     if(memcmp(header.magic, MAGIC, 8)) {
     if(memcmp(header.magic, MAGIC, 8)) {
-        EPRINTF_PATH(path, "Unknown file header");
+        EPRINTF_MSG_PATH(path, "Unknown file header");
         goto fail;
         goto fail;
     }
     }
-    if(length != sizeof(HashHeader) + (off_t)_le32toh(header.num_buckets) * (header.key_size + header.value_size)) {
-        EPRINTF_PATH(path, "Incorrect file length");
+    buckets_length = (off_t)_le32toh(header.num_buckets) * (header.key_size + header.value_size);
+    if(length != sizeof(HashHeader) + buckets_length) {
+        EPRINTF_MSG_PATH(path, "Incorrect file length");
         goto fail;
         goto fail;
     }
     }
     if(!(index = malloc(sizeof(HashIndex)))) {
     if(!(index = malloc(sizeof(HashIndex)))) {
         EPRINTF_PATH(path, "malloc failed");
         EPRINTF_PATH(path, "malloc failed");
         goto fail;
         goto fail;
     }
     }
-    if(!(index->data = malloc(length))) {
+    if(!(index->buckets = malloc(buckets_length))) {
         EPRINTF_PATH(path, "malloc failed");
         EPRINTF_PATH(path, "malloc failed");
         free(index);
         free(index);
         index = NULL;
         index = NULL;
         goto fail;
         goto fail;
     }
     }
-    bytes_read = fread(index->data, 1, length, fd);
-    if(bytes_read != length) {
-        EPRINTF_PATH(path, "fread hashindex failed (expected %ld, got %ld)", length, bytes_read);
-        free(index->data);
+    bytes_read = fread(index->buckets, 1, buckets_length, fd);
+    if(bytes_read != buckets_length) {
+        if(ferror(fd)) {
+            EPRINTF_PATH(path, "fread buckets failed (expected %ld, got %ld)", buckets_length, bytes_read);
+        }
+        else {
+            EPRINTF_MSG_PATH(path, "fread buckets failed (expected %ld, got %ld)", buckets_length, bytes_read);
+        }
+        free(index->buckets);
         free(index);
         free(index);
         index = NULL;
         index = NULL;
         goto fail;
         goto fail;
     }
     }
-    index->data_len = length;
     index->num_entries = _le32toh(header.num_entries);
     index->num_entries = _le32toh(header.num_entries);
     index->num_buckets = _le32toh(header.num_buckets);
     index->num_buckets = _le32toh(header.num_buckets);
     index->key_size = header.key_size;
     index->key_size = header.key_size;
     index->value_size = header.value_size;
     index->value_size = header.value_size;
     index->bucket_size = index->key_size + index->value_size;
     index->bucket_size = index->key_size + index->value_size;
-    index->buckets = index->data + sizeof(HashHeader);
     index->lower_limit = index->num_buckets > MIN_BUCKETS ? ((int)(index->num_buckets * BUCKET_LOWER_LIMIT)) : 0;
     index->lower_limit = index->num_buckets > MIN_BUCKETS ? ((int)(index->num_buckets * BUCKET_LOWER_LIMIT)) : 0;
     index->upper_limit = (int)(index->num_buckets * BUCKET_UPPER_LIMIT);
     index->upper_limit = (int)(index->num_buckets * BUCKET_UPPER_LIMIT);
 fail:
 fail:
@@ -205,10 +211,8 @@ fail:
 static HashIndex *
 static HashIndex *
 hashindex_init(int capacity, int key_size, int value_size)
 hashindex_init(int capacity, int key_size, int value_size)
 {
 {
+    off_t buckets_length;
     HashIndex *index;
     HashIndex *index;
-    HashHeader header = {
-        .magic = MAGIC, .num_entries = 0, .key_size = key_size, .value_size = value_size
-    };
     int i;
     int i;
     capacity = MAX(MIN_BUCKETS, capacity);
     capacity = MAX(MIN_BUCKETS, capacity);
 
 
@@ -216,8 +220,8 @@ hashindex_init(int capacity, int key_size, int value_size)
         EPRINTF("malloc failed");
         EPRINTF("malloc failed");
         return NULL;
         return NULL;
     }
     }
-    index->data_len = sizeof(HashHeader) + (off_t)capacity * (key_size + value_size);
-    if(!(index->data = calloc(index->data_len, 1))) {
+    buckets_length = (off_t)capacity * (key_size + value_size);
+    if(!(index->buckets = calloc(buckets_length, 1))) {
         EPRINTF("malloc failed");
         EPRINTF("malloc failed");
         free(index);
         free(index);
         return NULL;
         return NULL;
@@ -229,8 +233,6 @@ hashindex_init(int capacity, int key_size, int value_size)
     index->bucket_size = index->key_size + index->value_size;
     index->bucket_size = index->key_size + index->value_size;
     index->lower_limit = index->num_buckets > MIN_BUCKETS ? ((int)(index->num_buckets * BUCKET_LOWER_LIMIT)) : 0;
     index->lower_limit = index->num_buckets > MIN_BUCKETS ? ((int)(index->num_buckets * BUCKET_LOWER_LIMIT)) : 0;
     index->upper_limit = (int)(index->num_buckets * BUCKET_UPPER_LIMIT);
     index->upper_limit = (int)(index->num_buckets * BUCKET_UPPER_LIMIT);
-    index->buckets = index->data + sizeof(HashHeader);
-    memcpy(index->data, &header, sizeof(HashHeader));
     for(i = 0; i < capacity; i++) {
     for(i = 0; i < capacity; i++) {
         BUCKET_MARK_EMPTY(index, i);
         BUCKET_MARK_EMPTY(index, i);
     }
     }
@@ -240,24 +242,33 @@ hashindex_init(int capacity, int key_size, int value_size)
 static void
 static void
 hashindex_free(HashIndex *index)
 hashindex_free(HashIndex *index)
 {
 {
-    free(index->data);
+    free(index->buckets);
     free(index);
     free(index);
 }
 }
 
 
 static int
 static int
 hashindex_write(HashIndex *index, const char *path)
 hashindex_write(HashIndex *index, const char *path)
 {
 {
+    off_t buckets_length = (off_t)index->num_buckets * index->bucket_size;
     FILE *fd;
     FILE *fd;
+    HashHeader header = {
+        .magic = MAGIC,
+        .num_entries = _htole32(index->num_entries),
+        .num_buckets = _htole32(index->num_buckets),
+        .key_size = index->key_size,
+        .value_size = index->value_size
+    };
     int ret = 1;
     int ret = 1;
 
 
     if((fd = fopen(path, "w")) == NULL) {
     if((fd = fopen(path, "w")) == NULL) {
         EPRINTF_PATH(path, "open failed");
         EPRINTF_PATH(path, "open failed");
-        fprintf(stderr, "Failed to open %s for writing\n", path);
         return 0;
         return 0;
     }
     }
-    *((uint32_t *)(index->data + 8)) = _htole32(index->num_entries);
-    *((uint32_t *)(index->data + 12)) = _htole32(index->num_buckets);
-    if(fwrite(index->data, 1, index->data_len, fd) != index->data_len) {
+    if(fwrite(&header, 1, sizeof(header), fd) != sizeof(header)) {
+        EPRINTF_PATH(path, "fwrite failed");
+        ret = 0;
+    }
+    if(fwrite(index->buckets, 1, buckets_length, fd) != buckets_length) {
         EPRINTF_PATH(path, "fwrite failed");
         EPRINTF_PATH(path, "fwrite failed");
         ret = 0;
         ret = 0;
     }
     }
@@ -366,4 +377,3 @@ hashindex_summarize(HashIndex *index, long long *total_size, long long *total_cs
     *total_unique_size = unique_size;
     *total_unique_size = unique_size;
     *total_unique_csize = unique_csize;
     *total_unique_csize = unique_csize;
 }
 }
-