Merge lp:~jaypipes/drizzle/refactor-trx-log-applier into lp:~drizzle-trunk/drizzle/development
- refactor-trx-log-applier
- Merge into development
Proposed by
Jay Pipes
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~jaypipes/drizzle/refactor-trx-log-applier |
Merge into: | lp:~drizzle-trunk/drizzle/development |
Diff against target: |
1253 lines (+566/-375) 12 files modified
drizzled/plugin/transaction_reader.h (+2/-1) plugin/transaction_log/data_dictionary_schema.cc (+1/-1) plugin/transaction_log/module.cc (+279/-0) plugin/transaction_log/plugin.ini (+3/-3) plugin/transaction_log/transaction_log.cc (+27/-332) plugin/transaction_log/transaction_log.h (+23/-34) plugin/transaction_log/transaction_log_applier.cc (+145/-0) plugin/transaction_log/transaction_log_applier.h (+83/-0) plugin/transaction_log/transaction_log_index.cc (+0/-1) plugin/transaction_log/transaction_log_index.h (+0/-1) plugin/transaction_log/transaction_log_reader.cc (+1/-0) plugin/transaction_log/transaction_log_reader.h (+2/-2) |
To merge this branch: | bzr merge lp:~jaypipes/drizzle/refactor-trx-log-applier |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brian Aker | Pending | ||
Drizzle Developers | Pending | ||
Review via email: mp+20770@code.launchpad.net |
Commit message
Description of the change
Completes the blueprint for refactoring applier out of log descriptor.
1) Makes the TransactionLog class a simple descriptor for the actual transaction log file
2) Splits out the TransactionLogA
3) Splits the module initialization stuff out into a file, /plugin/
To post a comment you must log in.
- 1307. By Jay Pipes <jpipes@serialcoder>
-
Make OSX/FreeBSD happy about size_t != uint64_t != int64_t...
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'drizzled/plugin/transaction_reader.h' |
2 | --- drizzled/plugin/transaction_reader.h 2010-02-04 08:14:46 +0000 |
3 | +++ drizzled/plugin/transaction_reader.h 2010-03-05 18:39:28 +0000 |
4 | @@ -24,7 +24,8 @@ |
5 | #ifndef DRIZZLED_PLUGIN_TRANSACTION_READER_H |
6 | #define DRIZZLED_PLUGIN_TRANSACTION_READER_H |
7 | |
8 | -#include <drizzled/replication_services.h> /* For global transaction ID typedef */ |
9 | +#include "drizzled/plugin/plugin.h" |
10 | +#include "drizzled/replication_services.h" /* For global transaction ID typedef */ |
11 | |
12 | /** |
13 | * @file Defines the API for a TransactionReader |
14 | |
15 | === modified file 'plugin/transaction_log/data_dictionary_schema.cc' |
16 | --- plugin/transaction_log/data_dictionary_schema.cc 2010-03-05 04:44:58 +0000 |
17 | +++ plugin/transaction_log/data_dictionary_schema.cc 2010-03-05 18:39:28 +0000 |
18 | @@ -121,7 +121,7 @@ |
19 | push(transaction_log_index->getMaxTransactionId()); |
20 | push(transaction_log_index->getMinEndTimestamp()); |
21 | push(transaction_log_index->getMaxEndTimestamp()); |
22 | - push(transaction_log_index->getSizeInBytes()); |
23 | + push(static_cast<uint64_t>(transaction_log_index->getSizeInBytes())); |
24 | |
25 | is_done= true; |
26 | return true; |
27 | |
28 | === added file 'plugin/transaction_log/module.cc' |
29 | --- plugin/transaction_log/module.cc 1970-01-01 00:00:00 +0000 |
30 | +++ plugin/transaction_log/module.cc 2010-03-05 18:39:28 +0000 |
31 | @@ -0,0 +1,279 @@ |
32 | +/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- |
33 | + * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
34 | + * |
35 | + * Copyright (C) 2008-2009 Sun Microsystems |
36 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
37 | + * |
38 | + * Authors: |
39 | + * |
40 | + * Jay Pipes <jaypipes@gmail.com.com> |
41 | + * |
42 | + * This program is free software; you can redistribute it and/or modify |
43 | + * it under the terms of the GNU General Public License as published by |
44 | + * the Free Software Foundation; either version 2 of the License, or |
45 | + * (at your option) any later version. |
46 | + * |
47 | + * This program is distributed in the hope that it will be useful, |
48 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
49 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
50 | + * GNU General Public License for more details. |
51 | + * |
52 | + * You should have received a copy of the GNU General Public License |
53 | + * along with this program; if not, write to the Free Software |
54 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
55 | + */ |
56 | + |
57 | +/** |
58 | + * @file |
59 | + * |
60 | + * Transaction log module initialization and plugin |
61 | + * registration. |
62 | + */ |
63 | + |
64 | +#include "config.h" |
65 | + |
66 | +#include "transaction_log.h" |
67 | +#include "transaction_log_applier.h" |
68 | +#include "transaction_log_index.h" |
69 | +#include "data_dictionary_schema.h" |
70 | +#include "print_transaction_message.h" |
71 | +#include "hexdump_transaction_message.h" |
72 | +#include "background_worker.h" |
73 | + |
74 | +#include <drizzled/plugin/plugin.h> |
75 | +#include <drizzled/session.h> |
76 | +#include <drizzled/set_var.h> |
77 | +#include <drizzled/gettext.h> |
78 | + |
79 | +using namespace std; |
80 | +using namespace drizzled; |
81 | + |
82 | +/** |
83 | + * Transaction Log plugin system variable - Is the log enabled? Only used on init(). |
84 | + * The enable() and disable() methods of the TransactionLog class control online |
85 | + * disabling. |
86 | + */ |
87 | +static bool sysvar_transaction_log_enabled= false; |
88 | +/** Transaction Log plugin system variable - The path to the log file used */ |
89 | +static char* sysvar_transaction_log_file= NULL; |
90 | +/** |
91 | + * Transaction Log plugin system variable - A debugging variable to assist |
92 | + * in truncating the log file. |
93 | + */ |
94 | +static bool sysvar_transaction_log_truncate_debug= false; |
95 | +static const char DEFAULT_LOG_FILE_PATH[]= "transaction.log"; /* In datadir... */ |
96 | +/** |
97 | + * Transaction Log plugin system variable - Should we write a CRC32 checksum for |
98 | + * each written Transaction message? |
99 | + */ |
100 | +static bool sysvar_transaction_log_checksum_enabled= false; |
101 | +/** |
102 | + * Numeric option controlling the sync/flush behaviour of the transaction |
103 | + * log. Options are: |
104 | + * |
105 | + * TransactionLog::SYNC_METHOD_OS == 0 ... let OS do sync'ing |
106 | + * TransactionLog::SYNC_METHOD_EVERY_WRITE == 1 ... sync on every write |
107 | + * TransactionLog::SYNC_METHOD_EVERY_SECOND == 2 ... sync at most once a second |
108 | + */ |
109 | +static uint32_t sysvar_transaction_log_sync_method= 0; |
110 | + |
111 | +/** DATA_DICTIONARY views */ |
112 | +static TransactionLogTool *transaction_log_tool; |
113 | +static TransactionLogEntriesTool *transaction_log_entries_tool; |
114 | +static TransactionLogTransactionsTool *transaction_log_transactions_tool; |
115 | + |
116 | +/** Index defined in transaction_log_index.cc */ |
117 | +extern TransactionLogIndex *transaction_log_index; |
118 | +/** Transaction Log descriptor defined in transaction_log.cc */ |
119 | +extern TransactionLog *transaction_log; |
120 | +/** Transaction Log descriptor defined in transaction_log.cc */ |
121 | +extern TransactionLogApplier *transaction_log_applier; |
122 | + |
123 | +/** Defined in print_transaction_message.cc */ |
124 | +extern plugin::Create_function<PrintTransactionMessageFunction> *print_transaction_message_func_factory; |
125 | +extern plugin::Create_function<HexdumpTransactionMessageFunction> *hexdump_transaction_message_func_factory; |
126 | + |
127 | +static int init(drizzled::plugin::Registry ®istry) |
128 | +{ |
129 | + /* Create and initialize the transaction log itself */ |
130 | + if (sysvar_transaction_log_enabled) |
131 | + { |
132 | + transaction_log= new (nothrow) TransactionLog(string(sysvar_transaction_log_file), |
133 | + sysvar_transaction_log_sync_method); |
134 | + |
135 | + if (transaction_log == NULL) |
136 | + { |
137 | + errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLog instance. Got error: %s\n"), |
138 | + strerror(errno)); |
139 | + return 1; |
140 | + } |
141 | + else |
142 | + { |
143 | + /* Check to see if the log was not created properly */ |
144 | + if (transaction_log->hasError()) |
145 | + { |
146 | + errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log. Got error: %s\n"), |
147 | + transaction_log->getErrorMessage().c_str()); |
148 | + return 1; |
149 | + } |
150 | + } |
151 | + /* Create the applier plugin and register it */ |
152 | + transaction_log_applier= new (nothrow) TransactionLogApplier("transaction_log_applier", |
153 | + *transaction_log, |
154 | + sysvar_transaction_log_checksum_enabled); |
155 | + if (transaction_log_applier == NULL) |
156 | + { |
157 | + errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLogApplier instance. Got error: %s\n"), |
158 | + strerror(errno)); |
159 | + return 1; |
160 | + } |
161 | + registry.add(transaction_log_applier); |
162 | + |
163 | + /* Setup DATA_DICTIONARY views */ |
164 | + |
165 | + transaction_log_tool= new (nothrow) TransactionLogTool; |
166 | + registry.add(transaction_log_tool); |
167 | + transaction_log_entries_tool= new (nothrow) TransactionLogEntriesTool; |
168 | + registry.add(transaction_log_entries_tool); |
169 | + transaction_log_transactions_tool= new (nothrow) TransactionLogTransactionsTool; |
170 | + registry.add(transaction_log_transactions_tool); |
171 | + |
172 | + /* Setup the module's UDFs */ |
173 | + print_transaction_message_func_factory= |
174 | + new plugin::Create_function<PrintTransactionMessageFunction>("print_transaction_message"); |
175 | + registry.add(print_transaction_message_func_factory); |
176 | + |
177 | + hexdump_transaction_message_func_factory= |
178 | + new plugin::Create_function<HexdumpTransactionMessageFunction>("hexdump_transaction_message"); |
179 | + registry.add(hexdump_transaction_message_func_factory); |
180 | + |
181 | + /* Create and initialize the transaction log index */ |
182 | + transaction_log_index= new (nothrow) TransactionLogIndex(*transaction_log); |
183 | + if (transaction_log_index == NULL) |
184 | + { |
185 | + errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLogIndex instance. Got error: %s\n"), |
186 | + strerror(errno)); |
187 | + return 1; |
188 | + } |
189 | + else |
190 | + { |
191 | + /* Check to see if the index was not created properly */ |
192 | + if (transaction_log_index->hasError()) |
193 | + { |
194 | + errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log Index. Got error: %s\n"), |
195 | + transaction_log_index->getErrorMessage().c_str()); |
196 | + return 1; |
197 | + } |
198 | + } |
199 | + |
200 | + /* |
201 | + * Setup the background worker thread which maintains |
202 | + * summary information about the transaction log. |
203 | + */ |
204 | + if (initTransactionLogBackgroundWorker()) |
205 | + return 1; /* Error message output handled in function above */ |
206 | + } |
207 | + return 0; |
208 | +} |
209 | + |
210 | +static int deinit(drizzled::plugin::Registry ®istry) |
211 | +{ |
212 | + /* Cleanup the transaction log itself */ |
213 | + if (transaction_log) |
214 | + { |
215 | + registry.remove(transaction_log_applier); |
216 | + delete transaction_log; |
217 | + delete transaction_log_index; |
218 | + |
219 | + /* Cleanup the DATA_DICTIONARY views */ |
220 | + registry.remove(transaction_log_tool); |
221 | + delete transaction_log_tool; |
222 | + registry.remove(transaction_log_entries_tool); |
223 | + delete transaction_log_entries_tool; |
224 | + registry.remove(transaction_log_transactions_tool); |
225 | + delete transaction_log_transactions_tool; |
226 | + |
227 | + /* Cleanup module UDFs */ |
228 | + registry.remove(print_transaction_message_func_factory); |
229 | + delete print_transaction_message_func_factory; |
230 | + registry.remove(hexdump_transaction_message_func_factory); |
231 | + delete hexdump_transaction_message_func_factory; |
232 | + } |
233 | + |
234 | + return 0; |
235 | +} |
236 | + |
237 | +static void set_truncate_debug(Session *, |
238 | + drizzle_sys_var *, |
239 | + void *, |
240 | + const void *save) |
241 | +{ |
242 | + /* |
243 | + * The const void * save comes directly from the check function, |
244 | + * which should simply return the result from the set statement. |
245 | + */ |
246 | + if (transaction_log) |
247 | + { |
248 | + if (*(bool *)save != false) |
249 | + { |
250 | + transaction_log->truncate(); |
251 | + transaction_log_index->clear(); |
252 | + } |
253 | + } |
254 | +} |
255 | + |
256 | +static DRIZZLE_SYSVAR_BOOL(enable, |
257 | + sysvar_transaction_log_enabled, |
258 | + PLUGIN_VAR_NOCMDARG, |
259 | + N_("Enable transaction log"), |
260 | + NULL, /* check func */ |
261 | + NULL, /* update func */ |
262 | + false /* default */); |
263 | + |
264 | +static DRIZZLE_SYSVAR_BOOL(truncate_debug, |
265 | + sysvar_transaction_log_truncate_debug, |
266 | + PLUGIN_VAR_NOCMDARG, |
267 | + N_("DEBUGGING - Truncate transaction log"), |
268 | + NULL, /* check func */ |
269 | + set_truncate_debug, /* update func */ |
270 | + false /* default */); |
271 | + |
272 | +static DRIZZLE_SYSVAR_STR(log_file, |
273 | + sysvar_transaction_log_file, |
274 | + PLUGIN_VAR_READONLY, |
275 | + N_("Path to the file to use for transaction log"), |
276 | + NULL, /* check func */ |
277 | + NULL, /* update func*/ |
278 | + DEFAULT_LOG_FILE_PATH /* default */); |
279 | + |
280 | +static DRIZZLE_SYSVAR_BOOL(enable_checksum, |
281 | + sysvar_transaction_log_checksum_enabled, |
282 | + PLUGIN_VAR_NOCMDARG, |
283 | + N_("Enable CRC32 Checksumming of each written transaction log entry"), |
284 | + NULL, /* check func */ |
285 | + NULL, /* update func */ |
286 | + false /* default */); |
287 | + |
288 | +static DRIZZLE_SYSVAR_UINT(sync_method, |
289 | + sysvar_transaction_log_sync_method, |
290 | + PLUGIN_VAR_OPCMDARG, |
291 | + N_("0 == rely on operating system to sync log file (default), " |
292 | + "1 == sync file at each transaction write, " |
293 | + "2 == sync log file once per second"), |
294 | + NULL, /* check func */ |
295 | + NULL, /* update func */ |
296 | + 0, /* default */ |
297 | + 0, |
298 | + 2, |
299 | + 0); |
300 | + |
301 | +static drizzle_sys_var* sys_variables[]= { |
302 | + DRIZZLE_SYSVAR(enable), |
303 | + DRIZZLE_SYSVAR(truncate_debug), |
304 | + DRIZZLE_SYSVAR(log_file), |
305 | + DRIZZLE_SYSVAR(enable_checksum), |
306 | + DRIZZLE_SYSVAR(sync_method), |
307 | + NULL |
308 | +}; |
309 | + |
310 | +DRIZZLE_PLUGIN(init, deinit, sys_variables); |
311 | |
312 | === modified file 'plugin/transaction_log/plugin.ini' |
313 | --- plugin/transaction_log/plugin.ini 2010-02-11 04:18:03 +0000 |
314 | +++ plugin/transaction_log/plugin.ini 2010-03-05 18:39:28 +0000 |
315 | @@ -1,13 +1,13 @@ |
316 | [plugin] |
317 | name=transaction_log |
318 | -version=0.1 |
319 | +version=0.1.1 |
320 | author=Jay Pipes |
321 | license=PLUGIN_LICENSE_GPL |
322 | title=Transaction Log |
323 | description=Log of Transaction Messages |
324 | load_by_default=yes |
325 | -sources= background_worker.cc hexdump_transaction_message.cc print_transaction_message.cc transaction_log.cc transaction_log_entry.cc transaction_log_index.cc transaction_log_reader.cc data_dictionary_schema.cc |
326 | -headers= background_worker.h hexdump_transaction_message.h print_transaction_message.h transaction_log.h transaction_log_entry.h transaction_log_index.h transaction_log_reader.h data_dictionary_schema.h |
327 | +sources= background_worker.cc hexdump_transaction_message.cc module.cc print_transaction_message.cc transaction_log.cc transaction_log_applier.cc transaction_log_entry.cc transaction_log_index.cc transaction_log_reader.cc data_dictionary_schema.cc |
328 | +headers= background_worker.h hexdump_transaction_message.h print_transaction_message.h transaction_log.h transaction_log_applier.h transaction_log_entry.h transaction_log_index.h transaction_log_reader.h data_dictionary_schema.h |
329 | libs=${top_builddir}/drizzled/algorithm/libhash.la |
330 | libadd=$(LIBZ) |
331 | cxxflags=${PROTOSKIP_WARNINGS} |
332 | |
333 | === modified file 'plugin/transaction_log/transaction_log.cc' |
334 | --- plugin/transaction_log/transaction_log.cc 2010-03-05 04:44:58 +0000 |
335 | +++ plugin/transaction_log/transaction_log.cc 2010-03-05 18:39:28 +0000 |
336 | @@ -2,10 +2,11 @@ |
337 | * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
338 | * |
339 | * Copyright (C) 2008-2009 Sun Microsystems |
340 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
341 | * |
342 | * Authors: |
343 | * |
344 | - * Jay Pipes <joinfu@sun.com> |
345 | + * Jay Pipes <jaypipes@gmail.com.com> |
346 | * |
347 | * This program is free software; you can redistribute it and/or modify |
348 | * it under the terms of the GNU General Public License as published by |
349 | @@ -25,10 +26,7 @@ |
350 | /** |
351 | * @file |
352 | * |
353 | - * Defines the implementation of the default transaction log. |
354 | - * |
355 | - * @see drizzled/plugin/transaction_replicator.h |
356 | - * @see drizzled/plugin/transaction_applier.h |
357 | + * Defines the implementation of the transaction log file descriptor. |
358 | * |
359 | * @details |
360 | * |
361 | @@ -37,7 +35,7 @@ |
362 | * We have an atomic off_t called log_offset which keeps track of the |
363 | * offset into the log file for writing the next Transaction. |
364 | * |
365 | - * We write Transaction message encapsulated in an 8-byte length header and a |
366 | + * We write Transaction message encapsulated in an 8-byte length/type header and a |
367 | * 4-byte checksum trailer. |
368 | * |
369 | * When writing a Transaction to the log, we calculate the length of the |
370 | @@ -63,20 +61,10 @@ |
371 | * Possibly look at a scoreboard approach with multiple file segments. For |
372 | * right now, though, this is just a quick simple implementation to serve |
373 | * as a skeleton and a springboard. |
374 | - * |
375 | - * @todo |
376 | - * |
377 | - * Move the Applier piece of this code out into its own source file and leave |
378 | - * this for all the glue code of the module. |
379 | */ |
380 | |
381 | #include "config.h" |
382 | #include "transaction_log.h" |
383 | -#include "transaction_log_index.h" |
384 | -#include "data_dictionary_schema.h" |
385 | -#include "print_transaction_message.h" |
386 | -#include "hexdump_transaction_message.h" |
387 | -#include "background_worker.h" |
388 | |
389 | #include <sys/stat.h> |
390 | #include <fcntl.h> |
391 | @@ -85,71 +73,23 @@ |
392 | #include <vector> |
393 | #include <string> |
394 | |
395 | -#include "drizzled/internal/my_sys.h" /* for internal::my_sync */ |
396 | - |
397 | -#include <drizzled/session.h> |
398 | -#include <drizzled/set_var.h> |
399 | +#include <drizzled/internal/my_sys.h> /* for internal::my_sync */ |
400 | +#include <drizzled/errmsg_print.h> |
401 | #include <drizzled/gettext.h> |
402 | -#include <drizzled/algorithm/crc32.h> |
403 | -#include <drizzled/message/transaction.pb.h> |
404 | -#include <google/protobuf/io/coded_stream.h> |
405 | |
406 | using namespace std; |
407 | using namespace drizzled; |
408 | -using namespace google; |
409 | - |
410 | -/** |
411 | - * Transaction Log plugin system variable - Is the log enabled? Only used on init(). |
412 | - * The enable() and disable() methods of the TransactionLog class control online |
413 | - * disabling. |
414 | - */ |
415 | -static bool sysvar_transaction_log_enabled= false; |
416 | -/** Transaction Log plugin system variable - The path to the log file used */ |
417 | -static char* sysvar_transaction_log_file= NULL; |
418 | -/** |
419 | - * Transaction Log plugin system variable - A debugging variable to assist |
420 | - * in truncating the log file. |
421 | - */ |
422 | -static bool sysvar_transaction_log_truncate_debug= false; |
423 | -static const char DEFAULT_LOG_FILE_PATH[]= "transaction.log"; /* In datadir... */ |
424 | -/** |
425 | - * Transaction Log plugin system variable - Should we write a CRC32 checksum for |
426 | - * each written Transaction message? |
427 | - */ |
428 | -static bool sysvar_transaction_log_checksum_enabled= false; |
429 | -/** |
430 | - * Numeric option controlling the sync/flush behaviour of the transaction |
431 | - * log. Options are: |
432 | - * |
433 | - * TransactionLog::SYNC_METHOD_OS == 0 ... let OS do sync'ing |
434 | - * TransactionLog::SYNC_METHOD_EVERY_WRITE == 1 ... sync on every write |
435 | - * TransactionLog::SYNC_METHOD_EVERY_SECOND == 2 ... sync at most once a second |
436 | - */ |
437 | -static uint32_t sysvar_transaction_log_sync_method= 0; |
438 | - |
439 | -/** DATA_DICTIONARY views */ |
440 | -static TransactionLogTool *transaction_log_tool; |
441 | -static TransactionLogEntriesTool *transaction_log_entries_tool; |
442 | -static TransactionLogTransactionsTool *transaction_log_transactions_tool; |
443 | - |
444 | -/** Index defined in transaction_log_index.cc */ |
445 | -extern TransactionLogIndex *transaction_log_index; |
446 | - |
447 | -/** Defined in print_transaction_message.cc */ |
448 | -extern plugin::Create_function<PrintTransactionMessageFunction> *print_transaction_message_func_factory; |
449 | -extern plugin::Create_function<HexdumpTransactionMessageFunction> *hexdump_transaction_message_func_factory; |
450 | - |
451 | -TransactionLog::TransactionLog(string name_arg, |
452 | - const string &in_log_file_path, |
453 | - bool in_do_checksum) |
454 | - : plugin::TransactionApplier(name_arg), |
455 | + |
456 | +TransactionLog *transaction_log= NULL; /* The singleton transaction log */ |
457 | + |
458 | +TransactionLog::TransactionLog(const string in_log_file_path, |
459 | + uint32_t in_sync_method) : |
460 | state(OFFLINE), |
461 | log_file_path(in_log_file_path), |
462 | has_error(false), |
463 | - error_message() |
464 | + error_message(), |
465 | + sync_method(in_sync_method) |
466 | { |
467 | - do_checksum= in_do_checksum; /* Have to do here, not in initialization list b/c atomic<> */ |
468 | - |
469 | /* Setup our log file and determine the next write offset... */ |
470 | log_file= open(log_file_path.c_str(), O_APPEND|O_CREAT|O_SYNC|O_WRONLY, S_IRWXU); |
471 | if (log_file == -1) |
472 | @@ -160,7 +100,6 @@ |
473 | error_message.append(strerror(errno)); |
474 | error_message.push_back('\n'); |
475 | has_error= true; |
476 | - deactivate(); |
477 | return; |
478 | } |
479 | |
480 | @@ -187,74 +126,26 @@ |
481 | TransactionLog::~TransactionLog() |
482 | { |
483 | /* Clear up any resources we've consumed */ |
484 | - if (isEnabled() && log_file != -1) |
485 | + if (log_file != -1) |
486 | { |
487 | (void) close(log_file); |
488 | } |
489 | } |
490 | |
491 | -void TransactionLog::apply(const message::Transaction &to_apply) |
492 | +off_t TransactionLog::writeEntry(const uint8_t *data, size_t data_length) |
493 | { |
494 | - uint8_t *buffer; /* Buffer we will write serialized header, |
495 | - message and trailing checksum to */ |
496 | - uint8_t *orig_buffer; |
497 | - |
498 | - size_t message_byte_length= to_apply.ByteSize(); |
499 | - ssize_t written; |
500 | - off_t cur_offset; |
501 | - size_t total_envelope_length= HEADER_TRAILER_BYTES + message_byte_length; |
502 | - |
503 | - /* |
504 | - * Attempt allocation of raw memory buffer for the header, |
505 | - * message and trailing checksum bytes. |
506 | - */ |
507 | - buffer= static_cast<uint8_t *>(malloc(total_envelope_length)); |
508 | - if (buffer == NULL) |
509 | - { |
510 | - errmsg_printf(ERRMSG_LVL_ERROR, |
511 | - _("Failed to allocate enough memory to buffer header, transaction message, and trailing checksum bytes. Tried to allocate %" PRId64 |
512 | - " bytes. Error: %s\n"), |
513 | - static_cast<int64_t>(total_envelope_length), |
514 | - strerror(errno)); |
515 | - state= CRASHED; |
516 | - deactivate(); |
517 | - return; |
518 | - } |
519 | - else |
520 | - orig_buffer= buffer; /* We will free() orig_buffer, as buffer is moved during write */ |
521 | + ssize_t written= 0; |
522 | |
523 | /* |
524 | * Do an atomic increment on the offset of the log file position |
525 | */ |
526 | - cur_offset= log_offset.fetch_and_add(static_cast<off_t>(total_envelope_length)); |
527 | + off_t cur_offset= log_offset.fetch_and_add(static_cast<off_t>(data_length)); |
528 | |
529 | /* |
530 | * We adjust cur_offset back to the original log_offset before |
531 | * the increment above... |
532 | */ |
533 | - cur_offset-= static_cast<off_t>((total_envelope_length)); |
534 | - |
535 | - /* |
536 | - * Write the header information, which is the message type and |
537 | - * the length of the transaction message into the buffer |
538 | - */ |
539 | - buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(static_cast<uint32_t>(ReplicationServices::TRANSACTION), buffer); |
540 | - buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(static_cast<uint32_t>(message_byte_length), buffer); |
541 | - |
542 | - /* |
543 | - * Now write the serialized transaction message, followed |
544 | - * by the optional checksum into the buffer. |
545 | - */ |
546 | - buffer= to_apply.SerializeWithCachedSizesToArray(buffer); |
547 | - |
548 | - uint32_t checksum= 0; |
549 | - if (do_checksum) |
550 | - { |
551 | - checksum= drizzled::algorithm::crc32(reinterpret_cast<char *>(buffer) - message_byte_length, message_byte_length); |
552 | - } |
553 | - |
554 | - /* We always write in network byte order */ |
555 | - buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(checksum, buffer); |
556 | + cur_offset-= static_cast<off_t>(data_length); |
557 | |
558 | /* |
559 | * Quick safety...if an error occurs above in another writer, the log |
560 | @@ -267,23 +158,22 @@ |
561 | * the original offset where an error occurred. |
562 | */ |
563 | log_offset= cur_offset; |
564 | - free(orig_buffer); |
565 | - return; |
566 | + return log_offset; |
567 | } |
568 | |
569 | /* Write the full buffer in one swoop */ |
570 | do |
571 | { |
572 | - written= pwrite(log_file, orig_buffer, total_envelope_length, cur_offset); |
573 | + written= pwrite(log_file, data, data_length, cur_offset); |
574 | } |
575 | while (written == -1 && errno == EINTR); /* Just retry the write when interrupted by a signal... */ |
576 | |
577 | - if (unlikely(written != static_cast<ssize_t>(total_envelope_length))) |
578 | + if (unlikely(written != static_cast<ssize_t>(data_length))) |
579 | { |
580 | errmsg_printf(ERRMSG_LVL_ERROR, |
581 | - _("Failed to write full size of transaction. Tried to write %" PRId64 |
582 | + _("Failed to write full size of log entry. Tried to write %" PRId64 |
583 | " bytes at offset %" PRId64 ", but only wrote %" PRId32 " bytes. Error: %s\n"), |
584 | - static_cast<int64_t>(total_envelope_length), |
585 | + static_cast<int64_t>(data_length), |
586 | static_cast<int64_t>(cur_offset), |
587 | static_cast<int64_t>(written), |
588 | strerror(errno)); |
589 | @@ -293,29 +183,22 @@ |
590 | * the original offset where an error occurred. |
591 | */ |
592 | log_offset= cur_offset; |
593 | - deactivate(); |
594 | } |
595 | - free(orig_buffer); |
596 | |
597 | int error_code= syncLogFile(); |
598 | |
599 | - transaction_log_index->addEntry(TransactionLogEntry(ReplicationServices::TRANSACTION, |
600 | - cur_offset, |
601 | - total_envelope_length), |
602 | - to_apply, |
603 | - checksum); |
604 | - |
605 | if (unlikely(error_code != 0)) |
606 | { |
607 | errmsg_printf(ERRMSG_LVL_ERROR, |
608 | _("Failed to sync log file. Got error: %s\n"), |
609 | strerror(errno)); |
610 | } |
611 | + return cur_offset; |
612 | } |
613 | |
614 | int TransactionLog::syncLogFile() |
615 | { |
616 | - switch (sysvar_transaction_log_sync_method) |
617 | + switch (sync_method) |
618 | { |
619 | case SYNC_METHOD_EVERY_WRITE: |
620 | return internal::my_sync(log_file, 0); |
621 | @@ -347,20 +230,11 @@ |
622 | |
623 | void TransactionLog::truncate() |
624 | { |
625 | - bool orig_is_enabled= isEnabled(); |
626 | - disable(); |
627 | - |
628 | /* |
629 | - * Wait a short amount of time before truncating. This just prevents error messages |
630 | - * from being produced during a call to apply(). Calling disable() above |
631 | - * means that once the current caller to apply() is done, no other calls are made to |
632 | - * apply() before enable is reset to its original state |
633 | - * |
634 | * @note |
635 | * |
636 | - * This is DEBUG code only! |
637 | + * This is NOT THREAD SAFE! DEBUG/TEST code only! |
638 | */ |
639 | - usleep(500); /* Sleep for half a second */ |
640 | log_offset= (off_t) 0; |
641 | int result; |
642 | do |
643 | @@ -368,12 +242,6 @@ |
644 | result= ftruncate(log_file, log_offset); |
645 | } |
646 | while (result == -1 && errno == EINTR); |
647 | - |
648 | - /* Clear the transaction log index data */ |
649 | - transaction_log_index->clear(); |
650 | - |
651 | - if (orig_is_enabled) |
652 | - enable(); |
653 | } |
654 | |
655 | bool TransactionLog::findLogFilenameContainingTransactionId(const ReplicationServices::GlobalTransactionId&, |
656 | @@ -399,180 +267,7 @@ |
657 | error_message.clear(); |
658 | } |
659 | |
660 | -const std::string &TransactionLog::getErrorMessage() const |
661 | +const string &TransactionLog::getErrorMessage() const |
662 | { |
663 | return error_message; |
664 | } |
665 | - |
666 | -TransactionLog *transaction_log= NULL; /* The singleton transaction log */ |
667 | - |
668 | -static int init(drizzled::plugin::Registry ®istry) |
669 | -{ |
670 | - /* Create and initialize the transaction log itself */ |
671 | - if (sysvar_transaction_log_enabled) |
672 | - { |
673 | - transaction_log= new (nothrow) TransactionLog("transaction_log_applier", |
674 | - string(sysvar_transaction_log_file), |
675 | - sysvar_transaction_log_checksum_enabled); |
676 | - |
677 | - if (transaction_log == NULL) |
678 | - { |
679 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLog instance. Got error: %s\n"), |
680 | - strerror(errno)); |
681 | - return 1; |
682 | - } |
683 | - else |
684 | - { |
685 | - /* Check to see if the log was not created properly */ |
686 | - if (transaction_log->hasError()) |
687 | - { |
688 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log. Got error: %s\n"), |
689 | - transaction_log->getErrorMessage().c_str()); |
690 | - return 1; |
691 | - } |
692 | - } |
693 | - registry.add(transaction_log); |
694 | - |
695 | - /* Setup DATA_DICTIONARY views */ |
696 | - |
697 | - transaction_log_tool= new(std::nothrow)TransactionLogTool; |
698 | - registry.add(transaction_log_tool); |
699 | - transaction_log_entries_tool= new(std::nothrow)TransactionLogEntriesTool; |
700 | - registry.add(transaction_log_entries_tool); |
701 | - transaction_log_transactions_tool= new(std::nothrow)TransactionLogTransactionsTool; |
702 | - registry.add(transaction_log_transactions_tool); |
703 | - |
704 | - /* Setup the module's UDFs */ |
705 | - print_transaction_message_func_factory= |
706 | - new plugin::Create_function<PrintTransactionMessageFunction>("print_transaction_message"); |
707 | - registry.add(print_transaction_message_func_factory); |
708 | - |
709 | - hexdump_transaction_message_func_factory= |
710 | - new plugin::Create_function<HexdumpTransactionMessageFunction>("hexdump_transaction_message"); |
711 | - registry.add(hexdump_transaction_message_func_factory); |
712 | - |
713 | - /* Create and initialize the transaction log index */ |
714 | - transaction_log_index= new (nothrow) TransactionLogIndex(*transaction_log); |
715 | - if (transaction_log_index == NULL) |
716 | - { |
717 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLogIndex instance. Got error: %s\n"), |
718 | - strerror(errno)); |
719 | - return 1; |
720 | - } |
721 | - else |
722 | - { |
723 | - /* Check to see if the index was not created properly */ |
724 | - if (transaction_log_index->hasError()) |
725 | - { |
726 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log Index. Got error: %s\n"), |
727 | - transaction_log_index->getErrorMessage().c_str()); |
728 | - return 1; |
729 | - } |
730 | - } |
731 | - |
732 | - /* |
733 | - * Setup the background worker thread which maintains |
734 | - * summary information about the transaction log. |
735 | - */ |
736 | - if (initTransactionLogBackgroundWorker()) |
737 | - return 1; /* Error message output handled in function above */ |
738 | - } |
739 | - return 0; |
740 | -} |
741 | - |
742 | -static int deinit(drizzled::plugin::Registry ®istry) |
743 | -{ |
744 | - /* Cleanup the transaction log itself */ |
745 | - if (transaction_log) |
746 | - { |
747 | - registry.remove(transaction_log); |
748 | - delete transaction_log; |
749 | - delete transaction_log_index; |
750 | - |
751 | - /* Cleanup the DATA_DICTIONARY views */ |
752 | - registry.remove(transaction_log_tool); |
753 | - delete transaction_log_tool; |
754 | - registry.remove(transaction_log_entries_tool); |
755 | - delete transaction_log_entries_tool; |
756 | - registry.remove(transaction_log_transactions_tool); |
757 | - delete transaction_log_transactions_tool; |
758 | - |
759 | - /* Cleanup module UDFs */ |
760 | - registry.remove(print_transaction_message_func_factory); |
761 | - delete print_transaction_message_func_factory; |
762 | - registry.remove(hexdump_transaction_message_func_factory); |
763 | - delete hexdump_transaction_message_func_factory; |
764 | - } |
765 | - |
766 | - return 0; |
767 | -} |
768 | - |
769 | -static void set_truncate_debug(Session *, |
770 | - drizzle_sys_var *, |
771 | - void *, |
772 | - const void *save) |
773 | -{ |
774 | - /* |
775 | - * The const void * save comes directly from the check function, |
776 | - * which should simply return the result from the set statement. |
777 | - */ |
778 | - if (transaction_log) |
779 | - if (*(bool *)save != false) |
780 | - transaction_log->truncate(); |
781 | -} |
782 | - |
783 | -static DRIZZLE_SYSVAR_BOOL(enable, |
784 | - sysvar_transaction_log_enabled, |
785 | - PLUGIN_VAR_NOCMDARG, |
786 | - N_("Enable transaction log"), |
787 | - NULL, /* check func */ |
788 | - NULL, /* update func */ |
789 | - false /* default */); |
790 | - |
791 | -static DRIZZLE_SYSVAR_BOOL(truncate_debug, |
792 | - sysvar_transaction_log_truncate_debug, |
793 | - PLUGIN_VAR_NOCMDARG, |
794 | - N_("DEBUGGING - Truncate transaction log"), |
795 | - NULL, /* check func */ |
796 | - set_truncate_debug, /* update func */ |
797 | - false /* default */); |
798 | - |
799 | -static DRIZZLE_SYSVAR_STR(log_file, |
800 | - sysvar_transaction_log_file, |
801 | - PLUGIN_VAR_READONLY, |
802 | - N_("Path to the file to use for transaction log"), |
803 | - NULL, /* check func */ |
804 | - NULL, /* update func*/ |
805 | - DEFAULT_LOG_FILE_PATH /* default */); |
806 | - |
807 | -static DRIZZLE_SYSVAR_BOOL(enable_checksum, |
808 | - sysvar_transaction_log_checksum_enabled, |
809 | - PLUGIN_VAR_NOCMDARG, |
810 | - N_("Enable CRC32 Checksumming of each written transaction log entry"), |
811 | - NULL, /* check func */ |
812 | - NULL, /* update func */ |
813 | - false /* default */); |
814 | - |
815 | -static DRIZZLE_SYSVAR_UINT(sync_method, |
816 | - sysvar_transaction_log_sync_method, |
817 | - PLUGIN_VAR_OPCMDARG, |
818 | - N_("0 == rely on operating system to sync log file (default), " |
819 | - "1 == sync file at each transaction write, " |
820 | - "2 == sync log file once per second"), |
821 | - NULL, /* check func */ |
822 | - NULL, /* update func */ |
823 | - 0, /* default */ |
824 | - 0, |
825 | - 2, |
826 | - 0); |
827 | - |
828 | -static drizzle_sys_var* sys_variables[]= { |
829 | - DRIZZLE_SYSVAR(enable), |
830 | - DRIZZLE_SYSVAR(truncate_debug), |
831 | - DRIZZLE_SYSVAR(log_file), |
832 | - DRIZZLE_SYSVAR(enable_checksum), |
833 | - DRIZZLE_SYSVAR(sync_method), |
834 | - NULL |
835 | -}; |
836 | - |
837 | -DRIZZLE_PLUGIN(init, deinit, sys_variables); |
838 | |
839 | === modified file 'plugin/transaction_log/transaction_log.h' |
840 | --- plugin/transaction_log/transaction_log.h 2009-12-11 18:39:37 +0000 |
841 | +++ plugin/transaction_log/transaction_log.h 2010-03-05 18:39:28 +0000 |
842 | @@ -2,10 +2,11 @@ |
843 | * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
844 | * |
845 | * Copyright (C) 2008-2009 Sun Microsystems |
846 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
847 | * |
848 | * Authors: |
849 | * |
850 | - * Jay Pipes <joinfu@sun.com> |
851 | + * Jay Pipes <jaypipes@gmail.com.com> |
852 | * |
853 | * This program is free software; you can redistribute it and/or modify |
854 | * it under the terms of the GNU General Public License as published by |
855 | @@ -25,18 +26,13 @@ |
856 | /** |
857 | * @file |
858 | * |
859 | - * Defines the API of the default transaction log. |
860 | - * |
861 | - * @see drizzled/plugin/replicator.h |
862 | - * @see drizzled/plugin/applier.h |
863 | + * Defines the API of the transaction log file descriptor. |
864 | * |
865 | * @details |
866 | * |
867 | - * The TransactionLog applies events it receives from the ReplicationServices |
868 | - * server component to a simple log file on disk. |
869 | - * |
870 | - * Transactions are received in no guaranteed order and the command log |
871 | - * is in charge of writing these events to the log as they are received. |
872 | + * Basically, the TransactionLog is a descriptor for a log |
873 | + * file containing transaction messages that is written by |
874 | + * the TransactionLogApplier plugin(s). |
875 | */ |
876 | |
877 | #ifndef PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_H |
878 | @@ -44,15 +40,13 @@ |
879 | |
880 | #include <drizzled/atomics.h> |
881 | #include <drizzled/replication_services.h> |
882 | -#include <drizzled/plugin/transaction_replicator.h> |
883 | -#include <drizzled/plugin/transaction_applier.h> |
884 | |
885 | #include "transaction_log_entry.h" |
886 | |
887 | #include <vector> |
888 | #include <string> |
889 | |
890 | -class TransactionLog: public drizzled::plugin::TransactionApplier |
891 | +class TransactionLog |
892 | { |
893 | public: |
894 | static const uint32_t HEADER_TRAILER_BYTES= sizeof(uint32_t) + /* 4-byte msg type header */ |
895 | @@ -75,31 +69,13 @@ |
896 | static const uint32_t SYNC_METHOD_EVERY_WRITE= 1; //< Sync on every write to the log file |
897 | static const uint32_t SYNC_METHOD_EVERY_SECOND= 2; ///< Sync no more than once a second |
898 | public: |
899 | - TransactionLog(std::string name_arg, |
900 | - const std::string &in_log_file_path, |
901 | - bool in_do_checksum); |
902 | + TransactionLog(const std::string in_log_file_path, |
903 | + uint32_t in_sync_method); |
904 | |
905 | /** Destructor */ |
906 | ~TransactionLog(); |
907 | |
908 | /** |
909 | - * Applies a Transaction to the serial log |
910 | - * |
911 | - * @note |
912 | - * |
913 | - * It is important to note that memory allocation for the |
914 | - * supplied pointer is not guaranteed after the completion |
915 | - * of this function -- meaning the caller can dispose of the |
916 | - * supplied message. Therefore, appliers which are |
917 | - * implementing an asynchronous replication system must copy |
918 | - * the supplied message to their own controlled memory storage |
919 | - * area. |
920 | - * |
921 | - * @param Transaction message to be replicated |
922 | - */ |
923 | - void apply(const drizzled::message::Transaction &to_apply); |
924 | - |
925 | - /** |
926 | * Returns the current offset into the log |
927 | */ |
928 | inline off_t getLogOffset() |
929 | @@ -126,6 +102,19 @@ |
930 | } |
931 | |
932 | /** |
933 | + * Writes a chunk of data to the log file of a specified |
934 | + * length and returns the offset at which the chunk of |
935 | + * data was written. |
936 | + * |
937 | + * @param[in] Bytes to write |
938 | + * @param[in[ Length of bytes to write |
939 | + * |
940 | + * @retval |
941 | + * Returns the write offset if the write succeeded, OFF_T_MAX otherwise. |
942 | + */ |
943 | + off_t writeEntry(const uint8_t *data, size_t data_length); |
944 | + |
945 | + /** |
946 | * Truncates the existing log file |
947 | * |
948 | * @note |
949 | @@ -185,12 +174,12 @@ |
950 | |
951 | int log_file; ///< Handle for our log file |
952 | Status state; ///< The state the log is in |
953 | - drizzled::atomic<bool> do_checksum; ///< Do a CRC32 checksum when writing Transaction message to log? |
954 | const std::string log_file_path; ///< Full path to the log file |
955 | std::string log_file_name; ///< Name of the log file |
956 | drizzled::atomic<off_t> log_offset; ///< Offset in log file where log will write next command |
957 | bool has_error; ///< Is the log in error? |
958 | std::string error_message; ///< Current error message |
959 | + uint32_t sync_method; ///< Determines behaviour of syncing log file |
960 | time_t last_sync_time; ///< Last time the log file was synced (only set in SYNC_METHOD_EVERY_SECOND) |
961 | }; |
962 | |
963 | |
964 | === added file 'plugin/transaction_log/transaction_log_applier.cc' |
965 | --- plugin/transaction_log/transaction_log_applier.cc 1970-01-01 00:00:00 +0000 |
966 | +++ plugin/transaction_log/transaction_log_applier.cc 2010-03-05 18:39:28 +0000 |
967 | @@ -0,0 +1,145 @@ |
968 | +/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- |
969 | + * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
970 | + * |
971 | + * Copyright (C) 2008-2009 Sun Microsystems |
972 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
973 | + * |
974 | + * Authors: |
975 | + * |
976 | + * Jay Pipes <jaypipes@gmail.com.com> |
977 | + * |
978 | + * This program is free software; you can redistribute it and/or modify |
979 | + * it under the terms of the GNU General Public License as published by |
980 | + * the Free Software Foundation; either version 2 of the License, or |
981 | + * (at your option) any later version. |
982 | + * |
983 | + * This program is distributed in the hope that it will be useful, |
984 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
985 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
986 | + * GNU General Public License for more details. |
987 | + * |
988 | + * You should have received a copy of the GNU General Public License |
989 | + * along with this program; if not, write to the Free Software |
990 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
991 | + */ |
992 | + |
993 | +/** |
994 | + * @file |
995 | + * |
996 | + * Defines the implementation of the transaction applier plugin |
997 | + * for the transaction log. |
998 | + * |
999 | + * @see drizzled/plugin/transaction_replicator.h |
1000 | + * @see drizzled/plugin/transaction_applier.h |
1001 | + * |
1002 | + * @details |
1003 | + * |
1004 | + * The TransactionLogApplier::apply() method constructs the entry |
1005 | + * in the transaction log from the supplied Transaction message and |
1006 | + * asks its associated TransactionLog object to write this entry. |
1007 | + * |
1008 | + * Upon a successful write, the applier adds some information about |
1009 | + * the written transaction to the transaction log index. |
1010 | + */ |
1011 | + |
1012 | +#include "config.h" |
1013 | +#include "transaction_log.h" |
1014 | +#include "transaction_log_applier.h" |
1015 | +#include "transaction_log_index.h" |
1016 | + |
1017 | +#include <sys/stat.h> |
1018 | +#include <fcntl.h> |
1019 | +#include <unistd.h> |
1020 | + |
1021 | +#include <drizzled/errmsg_print.h> |
1022 | +#include <drizzled/gettext.h> |
1023 | +#include <drizzled/algorithm/crc32.h> |
1024 | +#include <drizzled/message/transaction.pb.h> |
1025 | +#include <google/protobuf/io/coded_stream.h> |
1026 | + |
1027 | +using namespace std; |
1028 | +using namespace drizzled; |
1029 | +using namespace google; |
1030 | + |
1031 | +TransactionLogApplier *transaction_log_applier= NULL; /* The singleton transaction log applier */ |
1032 | + |
1033 | +extern TransactionLogIndex *transaction_log_index; |
1034 | + |
1035 | +TransactionLogApplier::TransactionLogApplier(const string name_arg, |
1036 | + TransactionLog &in_transaction_log, |
1037 | + bool in_do_checksum) : |
1038 | + plugin::TransactionApplier(name_arg), |
1039 | + transaction_log(in_transaction_log), |
1040 | + do_checksum(in_do_checksum) |
1041 | +{ |
1042 | +} |
1043 | + |
1044 | +TransactionLogApplier::~TransactionLogApplier() |
1045 | +{ |
1046 | +} |
1047 | + |
1048 | +void TransactionLogApplier::apply(const message::Transaction &to_apply) |
1049 | +{ |
1050 | + uint8_t *buffer; /* Buffer we will write serialized header, |
1051 | + message and trailing checksum to */ |
1052 | + uint8_t *orig_buffer; |
1053 | + |
1054 | + size_t message_byte_length= to_apply.ByteSize(); |
1055 | + size_t total_envelope_length= TransactionLog::HEADER_TRAILER_BYTES + message_byte_length; |
1056 | + |
1057 | + /* |
1058 | + * Attempt allocation of raw memory buffer for the header, |
1059 | + * message and trailing checksum bytes. |
1060 | + */ |
1061 | + buffer= static_cast<uint8_t *>(malloc(total_envelope_length)); |
1062 | + if (buffer == NULL) |
1063 | + { |
1064 | + errmsg_printf(ERRMSG_LVL_ERROR, |
1065 | + _("Failed to allocate enough memory to buffer header, " |
1066 | + "transaction message, and trailing checksum bytes. Tried to allocate %" PRId64 |
1067 | + " bytes. Error: %s\n"), |
1068 | + static_cast<int64_t>(total_envelope_length), |
1069 | + strerror(errno)); |
1070 | + return; |
1071 | + } |
1072 | + else |
1073 | + orig_buffer= buffer; /* We will free() orig_buffer, as buffer is moved during write */ |
1074 | + |
1075 | + /* |
1076 | + * Write the header information, which is the message type and |
1077 | + * the length of the transaction message into the buffer |
1078 | + */ |
1079 | + buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray( |
1080 | + static_cast<uint32_t>(ReplicationServices::TRANSACTION), buffer); |
1081 | + buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray( |
1082 | + static_cast<uint32_t>(message_byte_length), buffer); |
1083 | + |
1084 | + /* |
1085 | + * Now write the serialized transaction message, followed |
1086 | + * by the optional checksum into the buffer. |
1087 | + */ |
1088 | + buffer= to_apply.SerializeWithCachedSizesToArray(buffer); |
1089 | + |
1090 | + uint32_t checksum= 0; |
1091 | + if (do_checksum) |
1092 | + { |
1093 | + checksum= drizzled::algorithm::crc32( |
1094 | + reinterpret_cast<char *>(buffer) - message_byte_length, message_byte_length); |
1095 | + } |
1096 | + |
1097 | + /* We always write in network byte order */ |
1098 | + buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(checksum, buffer); |
1099 | + |
1100 | + /* Ask the transaction log to write the entry and return where it wrote it */ |
1101 | + off_t written_to= transaction_log.writeEntry(orig_buffer, total_envelope_length); |
1102 | + |
1103 | + free(orig_buffer); |
1104 | + |
1105 | + /* Add an entry to the index describing what was just applied */ |
1106 | + transaction_log_index->addEntry(TransactionLogEntry(ReplicationServices::TRANSACTION, |
1107 | + written_to, |
1108 | + total_envelope_length), |
1109 | + to_apply, |
1110 | + checksum); |
1111 | + |
1112 | +} |
1113 | |
1114 | === added file 'plugin/transaction_log/transaction_log_applier.h' |
1115 | --- plugin/transaction_log/transaction_log_applier.h 1970-01-01 00:00:00 +0000 |
1116 | +++ plugin/transaction_log/transaction_log_applier.h 2010-03-05 18:39:28 +0000 |
1117 | @@ -0,0 +1,83 @@ |
1118 | +/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- |
1119 | + * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
1120 | + * |
1121 | + * Copyright (C) 2008-2009 Sun Microsystems |
1122 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
1123 | + * |
1124 | + * Authors: |
1125 | + * |
1126 | + * Jay Pipes <jaypipes@gmail.com.com> |
1127 | + * |
1128 | + * This program is free software; you can redistribute it and/or modify |
1129 | + * it under the terms of the GNU General Public License as published by |
1130 | + * the Free Software Foundation; either version 2 of the License, or |
1131 | + * (at your option) any later version. |
1132 | + * |
1133 | + * This program is distributed in the hope that it will be useful, |
1134 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1135 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1136 | + * GNU General Public License for more details. |
1137 | + * |
1138 | + * You should have received a copy of the GNU General Public License |
1139 | + * along with this program; if not, write to the Free Software |
1140 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1141 | + */ |
1142 | + |
1143 | +/** |
1144 | + * @file |
1145 | + * |
1146 | + * Defines the API of the transaction log applier. |
1147 | + * |
1148 | + * @see drizzled/plugin/replicator.h |
1149 | + * @see drizzled/plugin/applier.h |
1150 | + */ |
1151 | + |
1152 | +#ifndef PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_APPLIER_H |
1153 | +#define PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_APPLIER_H |
1154 | + |
1155 | +#include <drizzled/replication_services.h> |
1156 | +#include <drizzled/plugin/transaction_applier.h> |
1157 | + |
1158 | +#include "transaction_log_entry.h" |
1159 | + |
1160 | +#include <vector> |
1161 | +#include <string> |
1162 | + |
1163 | +class TransactionLog; |
1164 | + |
1165 | +class TransactionLogApplier: public drizzled::plugin::TransactionApplier |
1166 | +{ |
1167 | +public: |
1168 | + TransactionLogApplier(const std::string name_arg, |
1169 | + TransactionLog &in_transaction_log, |
1170 | + bool in_do_checksum); |
1171 | + |
1172 | + /** Destructor */ |
1173 | + ~TransactionLogApplier(); |
1174 | + |
1175 | + /** |
1176 | + * Applies a Transaction to the serial log |
1177 | + * |
1178 | + * @note |
1179 | + * |
1180 | + * It is important to note that memory allocation for the |
1181 | + * supplied pointer is not guaranteed after the completion |
1182 | + * of this function -- meaning the caller can dispose of the |
1183 | + * supplied message. Therefore, appliers which are |
1184 | + * implementing an asynchronous replication system must copy |
1185 | + * the supplied message to their own controlled memory storage |
1186 | + * area. |
1187 | + * |
1188 | + * @param Transaction message to be replicated |
1189 | + */ |
1190 | + void apply(const drizzled::message::Transaction &to_apply); |
1191 | +private: |
1192 | + /* Don't allows these */ |
1193 | + TransactionLogApplier(); |
1194 | + TransactionLogApplier(const TransactionLogApplier &other); |
1195 | + TransactionLogApplier &operator=(const TransactionLogApplier &other); |
1196 | + TransactionLog &transaction_log; |
1197 | + bool do_checksum; ///< Do a CRC32 checksum when writing Transaction message to log? |
1198 | +}; |
1199 | + |
1200 | +#endif /* PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_APPLIER_H */ |
1201 | |
1202 | === modified file 'plugin/transaction_log/transaction_log_index.cc' |
1203 | --- plugin/transaction_log/transaction_log_index.cc 2010-03-05 04:44:58 +0000 |
1204 | +++ plugin/transaction_log/transaction_log_index.cc 2010-03-05 18:39:28 +0000 |
1205 | @@ -42,7 +42,6 @@ |
1206 | |
1207 | TransactionLogIndex::TransactionLogIndex(TransactionLog &in_log) : |
1208 | log(in_log), |
1209 | - log_file(-1), |
1210 | index_file(-1), |
1211 | index_file_path(), |
1212 | has_error(false), |
1213 | |
1214 | === modified file 'plugin/transaction_log/transaction_log_index.h' |
1215 | --- plugin/transaction_log/transaction_log_index.h 2010-03-05 04:44:58 +0000 |
1216 | +++ plugin/transaction_log/transaction_log_index.h 2010-03-05 18:39:28 +0000 |
1217 | @@ -131,7 +131,6 @@ |
1218 | void clearError(); |
1219 | |
1220 | TransactionLog &log; ///< The transaction log instance |
1221 | - int log_file; ///< File descriptor for the transaction log file |
1222 | int index_file; ///< File descriptor for the transaction log on-disk index file |
1223 | const std::string index_file_path; ///< Filename of the on-disk transaction log index |
1224 | bool has_error; ///< Index is in error mode? |
1225 | |
1226 | === modified file 'plugin/transaction_log/transaction_log_reader.cc' |
1227 | --- plugin/transaction_log/transaction_log_reader.cc 2010-01-06 02:20:42 +0000 |
1228 | +++ plugin/transaction_log/transaction_log_reader.cc 2010-03-05 18:39:28 +0000 |
1229 | @@ -49,6 +49,7 @@ |
1230 | #include <cerrno> |
1231 | |
1232 | #include "transaction_log_reader.h" |
1233 | +#include "transaction_log.h" |
1234 | |
1235 | #include <drizzled/gettext.h> |
1236 | #include <drizzled/message/transaction.pb.h> |
1237 | |
1238 | === modified file 'plugin/transaction_log/transaction_log_reader.h' |
1239 | --- plugin/transaction_log/transaction_log_reader.h 2009-10-20 03:04:07 +0000 |
1240 | +++ plugin/transaction_log/transaction_log_reader.h 2010-03-05 18:39:28 +0000 |
1241 | @@ -38,10 +38,10 @@ |
1242 | #ifndef PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_READER_H |
1243 | #define PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_READER_H |
1244 | |
1245 | -#include "transaction_log.h" |
1246 | - |
1247 | #include <drizzled/plugin/transaction_reader.h> |
1248 | |
1249 | +class TransactionLog; |
1250 | + |
1251 | /** |
1252 | * A class which reads Transaction messages from the Transaction log file |
1253 | */ |