2007-11-29 14:18:54 +00:00
|
|
|
#ident "Copyright (c) 2007 Tokutek Inc. All rights reserved."
|
|
|
|
|
2008-04-25 13:45:55 +00:00
|
|
|
#include "brt-internal.h"
|
2008-02-08 03:17:38 +00:00
|
|
|
#include "log.h"
|
|
|
|
#include "toku_assert.h"
|
2008-02-14 19:23:25 +00:00
|
|
|
#include "list.h"
|
2007-08-10 21:15:17 +00:00
|
|
|
#include <stdio.h>
|
2008-03-12 17:55:11 +00:00
|
|
|
#include <pthread.h>
|
2007-09-28 17:11:22 +00:00
|
|
|
#include <sys/types.h>
|
2008-04-02 23:40:36 +00:00
|
|
|
#include <string.h>
|
2007-09-28 17:11:22 +00:00
|
|
|
|
2008-03-12 17:55:11 +00:00
|
|
|
// Locking for the logger
|
|
|
|
// For most purposes we use the big ydb lock.
|
|
|
|
// To log: grab the buf lock
|
|
|
|
// If the buf would overflow, then grab the file lock, swap file&buf, release buf lock, write the file, write the entry, release the file lock
|
|
|
|
// else append to buf & release lock
|
|
|
|
|
2007-10-19 17:05:10 +00:00
|
|
|
#define LOGGER_BUF_SIZE (1<<24)
|
2008-03-12 17:55:11 +00:00
|
|
|
|
|
|
|
struct mylock {
|
|
|
|
pthread_mutex_t lock;
|
|
|
|
int is_locked;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline int ml_init(struct mylock *l) {
|
|
|
|
l->is_locked=0;
|
|
|
|
return pthread_mutex_init(&l->lock, 0);
|
|
|
|
}
|
|
|
|
static inline int ml_lock(struct mylock *l) {
|
|
|
|
int r = pthread_mutex_lock(&l->lock);
|
|
|
|
assert(l->is_locked==0);
|
|
|
|
l->is_locked=1;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
static inline int ml_unlock(struct mylock *l) {
|
|
|
|
assert(l->is_locked==1);
|
|
|
|
l->is_locked=0;
|
|
|
|
return pthread_mutex_unlock(&l->lock);
|
|
|
|
}
|
|
|
|
static inline int ml_destroy(struct mylock *l) {
|
|
|
|
assert(l->is_locked==0);
|
|
|
|
return pthread_mutex_destroy(&l->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-10 19:24:45 +00:00
|
|
|
struct tokulogger {
|
2008-03-12 17:55:11 +00:00
|
|
|
enum typ_tag tag; // must be first
|
|
|
|
struct mylock input_lock, output_lock; // acquired in that order
|
2008-01-08 22:18:42 +00:00
|
|
|
int is_open;
|
|
|
|
int is_panicked;
|
2008-05-19 16:42:38 +00:00
|
|
|
int write_log_files;
|
2008-01-08 22:18:42 +00:00
|
|
|
int panic_errno;
|
2007-08-10 19:24:45 +00:00
|
|
|
char *directory;
|
2007-08-10 21:39:55 +00:00
|
|
|
int fd;
|
2008-01-11 22:24:43 +00:00
|
|
|
CACHETABLE ct;
|
2008-03-08 13:02:32 +00:00
|
|
|
int lg_max; // The size of the single file in the log. Default is 100MB in TokuDB
|
2008-03-12 17:55:11 +00:00
|
|
|
|
|
|
|
// To access these, you must have the input lock
|
|
|
|
struct logbytes *head,*tail;
|
|
|
|
LSN lsn; // the next available lsn
|
|
|
|
struct list live_txns; // just a linked list. Should be a hashtable.
|
|
|
|
int n_in_buf;
|
|
|
|
|
|
|
|
// To access these, you must have the output lock
|
|
|
|
LSN written_lsn; // the last lsn written
|
|
|
|
LSN fsynced_lsn; // What is the LSN of the highest fsynced log entry
|
2008-03-21 19:40:32 +00:00
|
|
|
LSN checkpoint_lsns[2]; // What are the LSNs of the most recent checkpoints. checkpoint_lsn[0] is the most recent one.
|
2008-03-12 17:55:11 +00:00
|
|
|
long long next_log_file_number;
|
|
|
|
char buf[LOGGER_BUF_SIZE]; // used to marshall logbytes so we can use only a single write
|
|
|
|
int n_in_file;
|
|
|
|
|
2007-08-10 19:24:45 +00:00
|
|
|
};
|
2007-08-10 21:15:17 +00:00
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
int toku_logger_find_next_unused_log_file(const char *directory, long long *result);
|
2008-03-21 19:40:32 +00:00
|
|
|
int toku_logger_find_logfiles (const char *directory, char ***resultp);
|
2007-09-28 17:11:22 +00:00
|
|
|
|
2008-04-25 13:45:55 +00:00
|
|
|
struct brtcachefile_pair {
|
|
|
|
BRT brt;
|
|
|
|
CACHEFILE cf;
|
|
|
|
};
|
|
|
|
|
2007-09-28 17:11:22 +00:00
|
|
|
struct tokutxn {
|
2008-02-14 19:23:25 +00:00
|
|
|
enum typ_tag tag;
|
2008-03-21 21:02:30 +00:00
|
|
|
u_int64_t txnid64; /* this happens to be the first lsn */
|
2007-09-28 17:11:22 +00:00
|
|
|
TOKULOGGER logger;
|
2007-10-19 17:05:10 +00:00
|
|
|
TOKUTXN parent;
|
2007-11-24 03:50:28 +00:00
|
|
|
LSN last_lsn; /* Everytime anything is logged, update the LSN. (We need to atomically record the LSN along with writing into the log.) */
|
2008-03-21 21:02:30 +00:00
|
|
|
LSN first_lsn; /* The first lsn in the transaction. */
|
2008-02-26 15:51:15 +00:00
|
|
|
struct roll_entry *oldest_logentry,*newest_logentry; /* Only logentries with rollbacks are here. There is a list going from newest to oldest. */
|
2008-02-14 19:23:25 +00:00
|
|
|
struct list live_txns_link;
|
2008-04-21 04:22:45 +00:00
|
|
|
size_t rollentry_resident_bytecount; // How many bytes for the rollentries that are stored in main memory.
|
|
|
|
char *rollentry_filename;
|
|
|
|
int rollentry_fd; // If we spill the roll_entries, we write them into this fd.
|
|
|
|
off_t rollentry_filesize; // How many bytes are in the rollentry.
|
2008-04-26 03:16:30 +00:00
|
|
|
OMT open_brts; // a collection of the brts that we touched. Indexed by filenum.
|
2007-09-28 17:11:22 +00:00
|
|
|
};
|
2007-11-22 07:13:08 +00:00
|
|
|
|
2008-03-12 17:55:11 +00:00
|
|
|
int toku_logger_finish (TOKULOGGER logger, struct logbytes *logbytes, struct wbuf *wbuf, int do_fsync);
|
2007-11-22 18:45:22 +00:00
|
|
|
|
2007-11-23 17:16:26 +00:00
|
|
|
static inline int toku_logsizeof_u_int8_t (u_int32_t v __attribute__((__unused__))) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2007-11-22 18:45:22 +00:00
|
|
|
static inline int toku_logsizeof_u_int32_t (u_int32_t v __attribute__((__unused__))) {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int toku_logsizeof_FILENUM (FILENUM v __attribute__((__unused__))) {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int toku_logsizeof_DISKOFF (DISKOFF v __attribute__((__unused__))) {
|
|
|
|
return 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int toku_logsizeof_TXNID (TXNID txnid __attribute__((__unused__))) {
|
|
|
|
return 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int toku_logsizeof_BYTESTRING (BYTESTRING bs) {
|
2007-11-22 20:30:38 +00:00
|
|
|
return 4+bs.len;
|
2007-11-22 18:45:22 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 21:11:21 +00:00
|
|
|
static inline int toku_logsizeof_LOGGEDBRTHEADER (LOGGEDBRTHEADER bs) {
|
2008-03-21 19:40:32 +00:00
|
|
|
int in_both = 4+4+4+8+8+4;
|
|
|
|
if (bs.n_named_roots==-1)
|
|
|
|
return in_both+8;
|
|
|
|
else {
|
|
|
|
int sum_of_pieces=0;
|
|
|
|
int i;
|
|
|
|
for (i=0; i<bs.n_named_roots; i++) {
|
2008-03-21 20:43:39 +00:00
|
|
|
sum_of_pieces += 4+8+1+strlen(bs.u.many.names[i]);
|
2008-03-21 19:40:32 +00:00
|
|
|
}
|
|
|
|
return in_both+sum_of_pieces;
|
|
|
|
}
|
|
|
|
|
2007-11-22 21:11:21 +00:00
|
|
|
}
|
2007-12-04 10:02:59 +00:00
|
|
|
|
|
|
|
static inline int toku_logsizeof_INTPAIRARRAY (INTPAIRARRAY pa) {
|
|
|
|
return 4+(4+4)*pa.size;
|
|
|
|
}
|
2008-02-14 19:23:25 +00:00
|
|
|
|
2008-03-14 19:14:31 +00:00
|
|
|
static inline char *fixup_fname(BYTESTRING *f) {
|
|
|
|
assert(f->len>0);
|
|
|
|
char *fname = toku_malloc(f->len+1);
|
|
|
|
memcpy(fname, f->data, f->len);
|
|
|
|
fname[f->len]=0;
|
|
|
|
return fname;
|
|
|
|
}
|
2008-04-21 04:22:45 +00:00
|
|
|
|
2008-07-09 12:00:26 +00:00
|
|
|
int toku_read_rollback_backwards(BREAD, struct roll_entry **item);
|