#include "replace.h"
#include "system/filesys.h"
#include "system/time.h"
#include "system/shmem.h"
#include "system/select.h"
#include "tdb.h"
#ifndef u32
#define u32 unsigned
#endif
#ifndef HAVE_GETPAGESIZE
#define getpagesize() 0x2000
#endif
typedef u32 tdb_len_t;
typedef u32 tdb_off_t;
#ifndef offsetof
#define offsetof(t,f) ((unsigned int)&((t *)0)->f)
#endif
#define TDB_MAGIC_FOOD "TDB file\n"
#define TDB_VERSION (0x26011967 + 6)
#define TDB_MAGIC (0x26011999U)
#define TDB_FREE_MAGIC (~TDB_MAGIC)
#define TDB_DEAD_MAGIC (0xFEE1DEAD)
#define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
#define TDB_ALIGNMENT 4
#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT)
#define DEFAULT_HASH_SIZE 131
#define FREELIST_TOP (sizeof(struct tdb_header))
#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24))
#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t))
#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t))
#define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1)
#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start)
#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number)
#define TDB_PAD_BYTE 0x42
#define TDB_PAD_U32 0x42424242
#define TDB_LOG(x) tdb->log.log_fn x
#define GLOBAL_LOCK 0
#define ACTIVE_LOCK 4
#define TRANSACTION_LOCK 8
#ifndef SAFE_FREE
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
#endif
#define BUCKET(hash) ((hash) % tdb->header.hash_size)
#define DOCONV() (tdb->flags & TDB_CONVERT)
#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x)
struct list_struct {
tdb_off_t next;
tdb_len_t rec_len;
tdb_len_t key_len;
tdb_len_t data_len;
u32 full_hash;
u32 magic;
};
struct tdb_header {
char magic_food[32];
u32 version;
u32 hash_size;
tdb_off_t rwlocks;
tdb_off_t recovery_start;
tdb_off_t sequence_number;
tdb_off_t reserved[29];
};
struct tdb_lock_type {
int list;
u32 count;
u32 ltype;
};
struct tdb_traverse_lock {
struct tdb_traverse_lock *next;
u32 off;
u32 hash;
int lock_rw;
};
struct tdb_methods {
int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int );
int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t);
void (*next_hash_chain)(struct tdb_context *, u32 *);
int (*tdb_oob)(struct tdb_context *, tdb_off_t , int );
int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t );
int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t);
};
struct tdb_context {
char *name;
void *map_ptr;
int fd;
tdb_len_t map_size;
int read_only;
int traverse_read;
struct tdb_lock_type global_lock;
int num_lockrecs;
struct tdb_lock_type *lockrecs;
enum TDB_ERROR ecode;
struct tdb_header header;
u32 flags;
struct tdb_traverse_lock travlocks;
struct tdb_context *next;
dev_t device;
ino_t inode;
struct tdb_logging_context log;
unsigned int (*hash_fn)(TDB_DATA *key);
int open_flags;
unsigned int num_locks;
const struct tdb_methods *methods;
struct tdb_transaction *transaction;
int page_size;
int max_dead_records;
};
int tdb_munmap(struct tdb_context *tdb);
void tdb_mmap(struct tdb_context *tdb);
int tdb_lock(struct tdb_context *tdb, int list, int ltype);
int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
void *tdb_convert(void *buf, u32 size);
int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec);
int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec);
char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
tdb_off_t offset, tdb_len_t len,
int (*parser)(TDB_DATA key, TDB_DATA data,
void *private_data),
void *private_data);
tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
struct list_struct *rec);
void tdb_io_init(struct tdb_context *tdb);
int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
int rec_free_read(struct tdb_context *tdb, tdb_off_t off,
struct list_struct *rec);