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