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 #include "logger/logcursor.h"
40 #include "test.h"
41
42 const int N = 2;
43
44 int
test_main(int argc,const char * argv[])45 test_main (int argc, const char *argv[]) {
46 default_parse_args(argc, argv);
47
48 int r;
49 toku_os_recursive_delete(TOKU_TEST_FILENAME);
50 r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU); assert(r==0);
51 TOKULOGGER logger;
52 LSN lsn = ZERO_LSN;
53
54 int helloseq = 0;
55
56 // create N log files with a hello message
57 for (int i=0; i<N; i++) {
58 r = toku_logger_create(&logger);
59 assert(r == 0);
60
61 r = toku_logger_open(TOKU_TEST_FILENAME, logger);
62 assert(r == 0);
63
64 char str[32];
65 sprintf(str, "hello%d", helloseq++);
66 BYTESTRING bs0 = { .len = (uint32_t) strlen(str), .data = str };
67 toku_log_comment(logger, &lsn, 0, 0, bs0);
68
69 r = toku_logger_close(&logger);
70 assert(r == 0);
71 }
72
73 // create N empty log files
74 for (int i=0; i<N; i++) {
75 r = toku_logger_create(&logger);
76 assert(r == 0);
77
78 r = toku_logger_open(TOKU_TEST_FILENAME, logger);
79 assert(r == 0);
80
81 r = toku_logger_close(&logger);
82 assert(r == 0);
83 }
84
85 // CREATE AN EMPTY FILE (tests [t:2384])
86 {
87 long long nexti;
88 r = toku_logger_find_next_unused_log_file(TOKU_TEST_FILENAME, &nexti);
89 assert(r == 0);
90 char mt_fname[TOKU_PATH_MAX+1];
91 snprintf(mt_fname, TOKU_PATH_MAX, "%s/log%012lld.tokulog%d", TOKU_TEST_FILENAME, nexti, TOKU_LOG_VERSION);
92 int mt_fd = open(mt_fname, O_CREAT+O_WRONLY+O_TRUNC+O_EXCL+O_BINARY, S_IRWXU);
93 assert(mt_fd != -1);
94 r = close(mt_fd);
95 }
96
97 // create N log files with a hello message
98 for (int i=0; i<N; i++) {
99 r = toku_logger_create(&logger);
100 assert(r == 0);
101
102 r = toku_logger_open(TOKU_TEST_FILENAME, logger);
103 assert(r == 0);
104
105 char str[32];
106 sprintf(str, "hello%d", helloseq++);
107 BYTESTRING bs0 = { .len = (uint32_t) strlen(str), .data = str };
108 toku_log_comment(logger, &lsn, 0, 0, bs0);
109
110 r = toku_logger_close(&logger);
111 assert(r == 0);
112 }
113
114 // CREATE AN EMPTY FILE (tests [t:2384])
115 {
116 long long nexti;
117 r = toku_logger_find_next_unused_log_file(TOKU_TEST_FILENAME, &nexti);
118 assert(r == 0);
119 char mt_fname[TOKU_PATH_MAX+1];
120 snprintf(mt_fname, TOKU_PATH_MAX, "%s/log%012lld.tokulog%d", TOKU_TEST_FILENAME, nexti, TOKU_LOG_VERSION);
121 int mt_fd = open(mt_fname, O_CREAT+O_WRONLY+O_TRUNC+O_EXCL+O_BINARY, S_IRWXU);
122 assert(mt_fd != -1);
123 r = close(mt_fd);
124 }
125
126 // verify the log forwards
127 TOKULOGCURSOR lc = NULL;
128 struct log_entry *le;
129
130 r = toku_logcursor_create(&lc, TOKU_TEST_FILENAME);
131 assert(r == 0 && lc != NULL);
132
133 helloseq = 0;
134 for (int i=0; i<2*N; i++) {
135
136 r = toku_logcursor_next(lc, &le);
137 assert(r == 0 && le->cmd == LT_comment);
138 char expect[32];
139 sprintf(expect, "hello%d", helloseq++);
140 assert(le->u.comment.comment.len == strlen(expect) && memcmp(le->u.comment.comment.data, expect, le->u.comment.comment.len) == 0);
141 }
142
143 r = toku_logcursor_next(lc, &le);
144 assert(r != 0);
145
146 r = toku_logcursor_destroy(&lc);
147 assert(r == 0 && lc == NULL);
148
149 // verify the log backwards
150 r = toku_logcursor_create(&lc, TOKU_TEST_FILENAME);
151 assert(r == 0 && lc != NULL);
152
153 helloseq = 2*N;
154 for (int i=0; i<2*N; i++) {
155
156 r = toku_logcursor_prev(lc, &le);
157 assert(r == 0 && le->cmd == LT_comment);
158 char expect[32];
159 sprintf(expect, "hello%d", --helloseq);
160 assert(le->u.comment.comment.len == strlen(expect) && memcmp(le->u.comment.comment.data, expect, le->u.comment.comment.len) == 0);
161 }
162
163 r = toku_logcursor_prev(lc, &le);
164 assert(r != 0);
165
166 r = toku_logcursor_destroy(&lc);
167 assert(r == 0 && lc == NULL);
168
169 // VERIFY TRIM WORKS WITH ZERO LENGTH FILE [t:2384]
170 {
171 LSN trim_lsn;
172 trim_lsn.lsn = (2*N)-1;
173 r = toku_logger_create(&logger); assert(r==0);
174 r = toku_logger_open(TOKU_TEST_FILENAME, logger); assert(r==0);
175
176 toku_logger_maybe_trim_log(logger, trim_lsn);
177 assert( toku_logfilemgr_num_logfiles(logger->logfilemgr) == 4 ); // untrimmed log, empty log, plus newly opened log
178
179 r = toku_logger_close(&logger);
180 }
181
182 toku_os_recursive_delete(TOKU_TEST_FILENAME);
183
184 return 0;
185 }
186