1 #include "../common/tdb_private.h" 2 #include "../common/io.c" 3 #include "../common/tdb.c" 4 #include "../common/lock.c" 5 #include "../common/freelist.c" 6 #include "../common/traverse.c" 7 #include "../common/transaction.c" 8 #include "../common/error.c" 9 #include "../common/open.c" 10 #include "../common/check.c" 11 #include "../common/hash.c" 12 #include "../common/mutex.c" 13 #include "tap-interface.h" 14 #include <stdlib.h> 15 16 static unsigned int tdb_dumb_hash(TDB_DATA *key) 17 { 18 return key->dsize; 19 } 20 21 static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) 22 { 23 unsigned int *count = tdb_get_logging_private(tdb); 24 if (strstr(fmt, "hash")) 25 (*count)++; 26 } 27 28 static unsigned int hdr_rwlocks(const char *fname) 29 { 30 struct tdb_header hdr; 31 ssize_t nread; 32 33 int fd = open(fname, O_RDONLY); 34 if (fd == -1) 35 return -1; 36 37 nread = read(fd, &hdr, sizeof(hdr)); 38 close(fd); 39 if (nread != sizeof(hdr)) { 40 return -1; 41 } 42 return hdr.rwlocks; 43 } 44 45 int main(int argc, char *argv[]) 46 { 47 struct tdb_context *tdb; 48 unsigned int log_count, flags; 49 TDB_DATA d, r; 50 struct tdb_logging_context log_ctx = { log_fn, &log_count }; 51 52 plan_tests(38 * 2); 53 54 for (flags = 0; flags <= TDB_CONVERT; flags += TDB_CONVERT) { 55 unsigned int rwmagic = TDB_HASH_RWLOCK_MAGIC; 56 57 if (flags & TDB_CONVERT) 58 tdb_convert(&rwmagic, sizeof(rwmagic)); 59 60 /* Create an old-style hash. */ 61 log_count = 0; 62 tdb = tdb_open_ex("run-incompatible.tdb", 0, flags, 63 O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, 64 NULL); 65 ok1(tdb); 66 ok1(log_count == 0); 67 d.dptr = discard_const_p(uint8_t, "Hello"); 68 d.dsize = 5; 69 ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); 70 tdb_close(tdb); 71 72 /* Should not have marked rwlocks field. */ 73 ok1(hdr_rwlocks("run-incompatible.tdb") == 0); 74 75 /* We can still open any old-style with incompat flag. */ 76 log_count = 0; 77 tdb = tdb_open_ex("run-incompatible.tdb", 0, 78 TDB_INCOMPATIBLE_HASH, 79 O_RDWR, 0600, &log_ctx, NULL); 80 ok1(tdb); 81 ok1(log_count == 0); 82 r = tdb_fetch(tdb, d); 83 ok1(r.dsize == 5); 84 free(r.dptr); 85 ok1(tdb_check(tdb, NULL, NULL) == 0); 86 tdb_close(tdb); 87 88 log_count = 0; 89 tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDONLY, 90 0, &log_ctx, tdb_jenkins_hash); 91 ok1(tdb); 92 ok1(log_count == 0); 93 ok1(tdb_check(tdb, NULL, NULL) == 0); 94 tdb_close(tdb); 95 96 log_count = 0; 97 tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDONLY, 98 0, &log_ctx, tdb_jenkins_hash); 99 ok1(tdb); 100 ok1(log_count == 0); 101 ok1(tdb_check(tdb, NULL, NULL) == 0); 102 tdb_close(tdb); 103 104 /* OK, now create with incompatible flag, default hash. */ 105 log_count = 0; 106 tdb = tdb_open_ex("run-incompatible.tdb", 0, 107 flags|TDB_INCOMPATIBLE_HASH, 108 O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, 109 NULL); 110 ok1(tdb); 111 ok1(log_count == 0); 112 d.dptr = discard_const_p(uint8_t, "Hello"); 113 d.dsize = 5; 114 ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); 115 tdb_close(tdb); 116 117 /* Should have marked rwlocks field. */ 118 ok1(hdr_rwlocks("run-incompatible.tdb") == rwmagic); 119 120 /* Cannot open with old hash. */ 121 log_count = 0; 122 tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, 123 O_RDWR, 0600, &log_ctx, tdb_old_hash); 124 ok1(!tdb); 125 ok1(log_count == 1); 126 127 /* Can open with jenkins hash. */ 128 log_count = 0; 129 tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, 130 O_RDWR, 0600, &log_ctx, tdb_jenkins_hash); 131 ok1(tdb); 132 ok1(log_count == 0); 133 r = tdb_fetch(tdb, d); 134 ok1(r.dsize == 5); 135 free(r.dptr); 136 ok1(tdb_check(tdb, NULL, NULL) == 0); 137 tdb_close(tdb); 138 139 /* Can open by letting it figure it out itself. */ 140 log_count = 0; 141 tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, 142 O_RDWR, 0600, &log_ctx, NULL); 143 ok1(tdb); 144 ok1(log_count == 0); 145 r = tdb_fetch(tdb, d); 146 ok1(r.dsize == 5); 147 free(r.dptr); 148 ok1(tdb_check(tdb, NULL, NULL) == 0); 149 tdb_close(tdb); 150 151 /* We can also use incompatible hash with other hashes. */ 152 log_count = 0; 153 tdb = tdb_open_ex("run-incompatible.tdb", 0, 154 flags|TDB_INCOMPATIBLE_HASH, 155 O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, 156 tdb_dumb_hash); 157 ok1(tdb); 158 ok1(log_count == 0); 159 d.dptr = discard_const_p(uint8_t, "Hello"); 160 d.dsize = 5; 161 ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); 162 tdb_close(tdb); 163 164 /* Should have marked rwlocks field. */ 165 ok1(hdr_rwlocks("run-incompatible.tdb") == rwmagic); 166 167 /* It should not open if we don't specify. */ 168 log_count = 0; 169 tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, O_RDWR, 0, 170 &log_ctx, NULL); 171 ok1(!tdb); 172 ok1(log_count == 1); 173 174 /* Should reopen with correct hash. */ 175 log_count = 0; 176 tdb = tdb_open_ex("run-incompatible.tdb", 0, 0, O_RDWR, 0, 177 &log_ctx, tdb_dumb_hash); 178 ok1(tdb); 179 ok1(log_count == 0); 180 r = tdb_fetch(tdb, d); 181 ok1(r.dsize == 5); 182 free(r.dptr); 183 ok1(tdb_check(tdb, NULL, NULL) == 0); 184 tdb_close(tdb); 185 } 186 187 return exit_status(); 188 } 189