void tdb_htrie_test_varsz(const char *fname) { int r __attribute__((unused)); int t, fd; char *addr; TdbHdr *dbh; struct timeval tv0, tv1; pthread_t thr[THR_N]; printf("\n----------- Variable size records test -------------\n"); addr = tdb_htrie_open(TDB_MAP_ADDR1, fname, TDB_VSF_SZ, &fd); dbh = tdb_htrie_init(addr, TDB_VSF_SZ, 0); if (!dbh) TDB_ERR("cannot initialize htrie for urls"); r = gettimeofday(&tv0, NULL); assert(!r); for (t = 0; t < THR_N; ++t) if (spawn_thread(thr + t, varsz_thr_f, dbh)) perror("cannot spawn varsz thread"); for (t = 0; t < THR_N; ++t) pthread_join(thr[t], NULL); r = gettimeofday(&tv1, NULL); assert(!r); printf("tdb htrie urls test: time=%lums\n", tv_to_ms(&tv1) - tv_to_ms(&tv0)); tdb_htrie_exit(dbh); tdb_htrie_pure_close(addr, TDB_VSF_SZ, fd); printf("\n **** Variable size records test reopen ****\n"); addr = tdb_htrie_open(TDB_MAP_ADDR2, fname, TDB_VSF_SZ, &fd); dbh = tdb_htrie_init(addr, TDB_VSF_SZ, 0); if (!dbh) TDB_ERR("cannot initialize htrie for urls"); lookup_varsz_records(dbh); tdb_htrie_exit(dbh); tdb_htrie_pure_close(addr, TDB_VSF_SZ, fd); }
/** * Open, mmap and mlock the specified file to be able to read and * write to it in softirqs. * Use MAP_SHARED to synchronize the mapping with underlying file. * * The function must not be called from softirq! */ int tdb_file_open(TDB *db, unsigned long size) { unsigned long ret, addr; struct file *filp; struct inode *inode; filp = filp_open(db->path, O_CREAT | O_RDWR, 0600); if (IS_ERR(filp)) { TDB_ERR("Cannot open db file %s\n", db->path); return PTR_ERR(filp); } BUG_ON(!filp || !filp->f_path.dentry); if (!filp->f_op->fallocate) { TDB_ERR("TDB requires filesystem with fallocate support\n"); filp_close(db->filp, NULL); return -EBADF; } /* Allocate continuous extents. */ inode = file_inode(filp); sb_start_write(inode->i_sb); ret = filp->f_op->fallocate(filp, 0, 0, size); sb_end_write(inode->i_sb); if (ret) { TDB_ERR("Cannot fallocate file, %ld\n", ret); filp_close(db->filp, NULL); return ret; } addr = tempesta_map_file(filp, size, db->node); if (IS_ERR((void *)addr)) { TDB_ERR("Cannot map file\n"); filp_close(filp, NULL); return (int)addr; } db->filp = filp; db->hdr = (TdbHdr *)addr; file_accessed(filp); return 0; }
TdbRec * tdb_entry_create(TDB *db, unsigned long key, void *data, size_t *len) { TdbRec *r = tdb_htrie_insert(db->hdr, key, data, len); if (!r) TDB_ERR("Cannot create cache entry for %.*s, key=%#lx\n", (int)*len, (char *)data, key); return r; }
/** * Search for already opened handler for the database or allocate a new one. * * The path to table must end with table name (not more than TDB_TBLNAME_LEN * characters in long) followed by TDB_SUFFIX. */ static TDB * tdb_get_db(const char *path, int node) { int full_len, len; char *slash; TDB *db; full_len = strlen(path); if (strncmp(path + full_len - sizeof(TDB_SUFFIX) + 1, TDB_SUFFIX, sizeof(TDB_SUFFIX) - 1)) { TDB_ERR("Bad table suffix for %s\n", path); return NULL; } slash = strrchr(path, '/'); if (!slash) { TDB_ERR("Please specify absolute path to %s\n", path); return NULL; } len = full_len - (slash - path) - sizeof(TDB_SUFFIX); if (len >= TDB_TBLNAME_LEN) { TDB_ERR("Too long table name %s\n", path); return NULL; } db = tdb_tbl_lookup(slash + 1, len); if (db) return db; db = kzalloc(sizeof(TDB), GFP_KERNEL); if (!db) { TDB_ERR("Cannot allocate new db handler\n"); return NULL; } snprintf(db->path, TDB_PATH_LEN, "%.*s%X.tdb", (int)(full_len - sizeof(TDB_SUFFIX)), path, node); snprintf(db->tbl_name, TDB_TBLNAME_LEN, "%.*s%X.tdb", (int)(len - sizeof(TDB_SUFFIX)), slash + 1, node); return tdb_get(db); }
int main(int argc, char *argv[]) { unsigned int eax, ebx, ecx = 0, edx; struct rlimit rlim = { TDB_VSF_SZ, TDB_VSF_SZ * 2}; if (argc < 3) { printf("\nUsage: %s <vsf> <fsf>\n" " vsf - file name for variable-size records test\n" " fsf - file name for fixed-size records test\n\n", argv[0]); return 1; } /* Don't forget to set appropriate system hard limit. */ if (setrlimit(RLIMIT_MEMLOCK, &rlim)) TDB_ERR("cannot set RLIMIT_MEMLOCK"); __get_cpuid(1, &eax, &ebx, &ecx, &edx); if (!(ecx & bit_SSE4_2)) TDB_ERR("SSE4.2 is not supported"); printf("Run test with parameters:\n" "\tfix rec db size: %lu\n" "\tvar rec db size: %lu\n" "\textent size: %lu\n" "\tthreads number: %d\n" "\tdata size: %d\n" "\tloops: %d\n", TDB_FSF_SZ, TDB_VSF_SZ, TDB_EXT_SZ, THR_N, DATA_N, LOOP_N); init_test_data_for_hash(); hash_calc_benchmark(); init_test_data_for_htrie(); tdb_htrie_test(argv[1], argv[2]); return 0; }
static void ma_free(unsigned long addr, int node) { MArea *ma; ma = ma_lookup(addr, node); if (!ma) { TDB_ERR("Cannot find memory area for %#lx address at node %d\n", addr, node); return; } __ma_free(ma); }
/** * Open database file and @return its descriptor. * If the database is already opened, then returns the handler. * * The function must not be called from softirq! */ TDB * tdb_open(const char *path, size_t fsize, unsigned int rec_size, int node) { TDB *db; if ((fsize & ~TDB_EXT_MASK) || fsize < TDB_EXT_SZ) { TDB_ERR("Bad table size: %lu\n", fsize); return NULL; } db = tdb_get_db(path, node); if (!db) return NULL; db->node = node; if (tdb_file_open(db, fsize)) { TDB_ERR("Cannot open db\n"); goto err; } db->hdr = tdb_htrie_init(db->hdr, db->filp->f_inode->i_size, rec_size); if (!db->hdr) { TDB_ERR("Cannot initialize db header\n"); goto err_init; } tdb_tbl_enumerate(db); TDB_LOG("Opened table %s: size=%lu rec_size=%u base=%p\n", path, fsize, rec_size, db->hdr); return db; err_init: tdb_file_close(db); err: tdb_put(db); return NULL; }
int tdb_init_mappings(void) { int node; TempestaMapping *tm; for_each_node_with_cpus(node) { if (tempesta_get_mapping(node, &tm)) { TDB_ERR("Cannot get mapping for node %d\n", node); return -ENOMEM; } mas[node].start = tm->addr; mas[node].pages = tm->pages; } return 0; }