1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6 
7 
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9 
10     PerconaFT is free software: you can redistribute it and/or modify
11     it under the terms of the GNU General Public License, version 2,
12     as published by the Free Software Foundation.
13 
14     PerconaFT is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
21 
22 ----------------------------------------
23 
24     PerconaFT is free software: you can redistribute it and/or modify
25     it under the terms of the GNU Affero General Public License, version 3,
26     as published by the Free Software Foundation.
27 
28     PerconaFT is distributed in the hope that it will be useful,
29     but WITHOUT ANY WARRANTY; without even the implied warranty of
30     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31     GNU Affero General Public License for more details.
32 
33     You should have received a copy of the GNU Affero General Public License
34     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36 
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38 
39 #pragma once
40 
41 #include <stdio.h>
42 #include <sys/types.h>
43 #include <string.h>
44 #include <dirent.h>
45 
46 #include "portability/toku_list.h"
47 #include "portability/toku_pthread.h"
48 #include "ft/ft-internal.h"
49 #include "ft/logger/log.h"
50 #include "ft/logger/logfilemgr.h"
51 #include "ft/txn/txn.h"
52 #include "ft/txn/txn_manager.h"
53 #include "ft/txn/rollback_log_node_cache.h"
54 
55 #include "util/memarena.h"
56 #include "util/omt.h"
57 
58 using namespace toku;
59 // Locking for the logger
60 //  For most purposes we use the big ydb lock.
61 // To log: grab the buf lock
62 //  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
63 //  else append to buf & release lock
64 
65 #define LOGGER_MIN_BUF_SIZE (1<<24)
66 
67 // TODO: Remove mylock, it has no value
68 struct mylock {
69     toku_mutex_t lock;
70 };
71 
ml_init(struct mylock * l)72 static inline void ml_init(struct mylock *l) {
73     toku_mutex_init(*log_internal_lock_mutex_key, &l->lock, nullptr);
74 }
75 // TODO: source location info might have be to be pulled up one caller
76 // to be useful
ml_lock(struct mylock * l)77 static inline void ml_lock(struct mylock *l) { toku_mutex_lock(&l->lock); }
ml_unlock(struct mylock * l)78 static inline void ml_unlock(struct mylock *l) {
79     toku_mutex_unlock(&l->lock);
80 }
ml_destroy(struct mylock * l)81 static inline void ml_destroy(struct mylock *l) {
82     toku_mutex_destroy(&l->lock);
83 }
84 
85 struct logbuf {
86     int n_in_buf;
87     int buf_size;
88     char *buf;
89     LSN  max_lsn_in_buf;
90 };
91 
92 struct tokulogger {
93     struct mylock  input_lock;
94 
95     toku_mutex_t output_condition_lock; // if you need both this lock and input_lock, acquire the output_lock first, then input_lock. More typical is to get the output_is_available condition to be false, and then acquire the input_lock.
96     toku_cond_t  output_condition;      //
97     bool output_is_available;           // this is part of the predicate for the output condition.  It's true if no thread is modifying the output (either doing an fsync or otherwise fiddling with the output).
98 
99     bool is_open;
100     bool write_log_files;
101     bool trim_log_files; // for test purposes
102     char *directory;  // file system directory
103     DIR *dir; // descriptor for directory
104     int fd;
105     CACHETABLE ct;
106     int lg_max; // The size of the single file in the log.  Default is 100MB.
107 
108     // To access these, you must have the input lock
109     LSN lsn; // the next available lsn
110     struct logbuf inbuf; // data being accumulated for the write
111 
112     // To access these, you must have the output condition lock.
113     LSN written_lsn; // the last lsn written
114     LSN fsynced_lsn; // What is the LSN of the highest fsynced log entry  (accessed only while holding the output lock, and updated only when the output lock and output permission are held)
115     LSN last_completed_checkpoint_lsn;     // What is the LSN of the most recent completed checkpoint.
116     long long next_log_file_number;
117     struct logbuf outbuf; // data being written to the file
118     int  n_in_file; // The amount of data in the current file
119 
120     // To access the logfilemgr you must have the output condition lock.
121     TOKULOGFILEMGR logfilemgr;
122 
123     uint32_t write_block_size;       // How big should the blocks be written to various logs?
124 
125     uint64_t num_writes_to_disk;         // how many times did we write to disk?
126     uint64_t bytes_written_to_disk;        // how many bytes have been written to disk?
127     tokutime_t time_spent_writing_to_disk; // how much tokutime did we spend writing to disk?
128     uint64_t num_wait_buf_long;            // how many times we waited >= 100ms for the in buf
129 
130     CACHEFILE rollback_cachefile;
131     rollback_log_node_cache rollback_cache;
132     TXN_MANAGER txn_manager;
133 };
134 
135 int toku_logger_find_next_unused_log_file(const char *directory, long long *result);
136 int toku_logger_find_logfiles (const char *directory, char ***resultp, int *n_logfiles);
137 void toku_logger_free_logfiles (char **logfiles, int n_logfiles);
138 
139 static inline int
txn_has_current_rollback_log(TOKUTXN txn)140 txn_has_current_rollback_log(TOKUTXN txn) {
141     return txn->roll_info.current_rollback.b != ROLLBACK_NONE.b;
142 }
143 
144 static inline int
txn_has_spilled_rollback_logs(TOKUTXN txn)145 txn_has_spilled_rollback_logs(TOKUTXN txn) {
146     return txn->roll_info.spilled_rollback_tail.b != ROLLBACK_NONE.b;
147 }
148 
149 struct txninfo {
150     uint64_t   rollentry_raw_count;  // the total count of every byte in the transaction and all its children.
151     uint32_t   num_fts;
152     FT *open_fts;
153     bool       force_fsync_on_commit;  //This transaction NEEDS an fsync once (if) it commits.  (commit means root txn)
154     uint64_t   num_rollback_nodes;
155     uint64_t   num_rollentries;
156     BLOCKNUM   spilled_rollback_head;
157     BLOCKNUM   spilled_rollback_tail;
158     BLOCKNUM   current_rollback;
159 };
160 
toku_logsizeof_uint8_t(uint32_t v)161 static inline int toku_logsizeof_uint8_t (uint32_t v __attribute__((__unused__))) {
162     return 1;
163 }
164 
toku_logsizeof_uint32_t(uint32_t v)165 static inline int toku_logsizeof_uint32_t (uint32_t v __attribute__((__unused__))) {
166     return 4;
167 }
168 
toku_logsizeof_uint64_t(uint32_t v)169 static inline int toku_logsizeof_uint64_t (uint32_t v __attribute__((__unused__))) {
170     return 8;
171 }
172 
toku_logsizeof_bool(uint32_t v)173 static inline int toku_logsizeof_bool (uint32_t v __attribute__((__unused__))) {
174     return 1;
175 }
176 
toku_logsizeof_FILENUM(FILENUM v)177 static inline int toku_logsizeof_FILENUM (FILENUM v __attribute__((__unused__))) {
178     return 4;
179 }
180 
toku_logsizeof_DISKOFF(DISKOFF v)181 static inline int toku_logsizeof_DISKOFF (DISKOFF v __attribute__((__unused__))) {
182     return 8;
183 }
toku_logsizeof_BLOCKNUM(BLOCKNUM v)184 static inline int toku_logsizeof_BLOCKNUM (BLOCKNUM v __attribute__((__unused__))) {
185     return 8;
186 }
187 
toku_logsizeof_LSN(LSN lsn)188 static inline int toku_logsizeof_LSN (LSN lsn __attribute__((__unused__))) {
189     return 8;
190 }
191 
toku_logsizeof_TXNID(TXNID txnid)192 static inline int toku_logsizeof_TXNID (TXNID txnid __attribute__((__unused__))) {
193     return 8;
194 }
195 
toku_logsizeof_TXNID_PAIR(TXNID_PAIR txnid)196 static inline int toku_logsizeof_TXNID_PAIR (TXNID_PAIR txnid __attribute__((__unused__))) {
197     return 16;
198 }
199 
toku_logsizeof_XIDP(XIDP xid)200 static inline int toku_logsizeof_XIDP (XIDP xid) {
201     assert(0<=xid->gtrid_length && xid->gtrid_length<=64);
202     assert(0<=xid->bqual_length && xid->bqual_length<=64);
203     return xid->gtrid_length
204 	+ xid->bqual_length
205 	+ 4  // formatID
206 	+ 1  // gtrid_length
207 	+ 1; // bqual_length
208 }
209 
toku_logsizeof_FILENUMS(FILENUMS fs)210 static inline int toku_logsizeof_FILENUMS (FILENUMS fs) {
211     static const FILENUM f = {0}; //fs could have .num==0 and then we cannot dereference
212     return 4 + fs.num * toku_logsizeof_FILENUM(f);
213 }
214 
toku_logsizeof_BYTESTRING(BYTESTRING bs)215 static inline int toku_logsizeof_BYTESTRING (BYTESTRING bs) {
216     return 4+bs.len;
217 }
218 
fixup_fname(BYTESTRING * f)219 static inline char *fixup_fname(BYTESTRING *f) {
220     assert(f->len>0);
221     char *fname = (char*)toku_xmalloc(f->len+1);
222     memcpy(fname, f->data, f->len);
223     fname[f->len]=0;
224     return fname;
225 }
226