Merge lp:~jaypipes/drizzle/split-xa-resource-manager into lp:~drizzle-trunk/drizzle/development
- split-xa-resource-manager
- Merge into development
Proposed by
Jay Pipes
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~jaypipes/drizzle/split-xa-resource-manager |
Merge into: | lp:~drizzle-trunk/drizzle/development |
Diff against target: |
1256 lines (+568/-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 (+28/-332) plugin/transaction_log/transaction_log.h (+23/-34) plugin/transaction_log/transaction_log_applier.cc (+146/-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/split-xa-resource-manager |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Drizzle Developers | Pending | ||
Review via email: mp+20600@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Jay Pipes (jaypipes) wrote : | # |
- 1304. By Jay Pipes <jpipes@serialcoder>
-
Merge trunk
- 1305. By Jay Pipes <jpipes@serialcoder>
-
Merge fixes for LP Bug 530870
- 1306. By Jay Pipes <jpipes@serialcoder>
-
Merge trunk and add in data dictionary fix for OSX/FreeBSD
- 1307. By Jay Pipes <jpipes@serialcoder>
-
Add errno.h to a few files. Apparently, this is necessary on OSX.
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 19:18:29 +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 19:18:29 +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 19:18:29 +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 19:18:29 +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 19:18:29 +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,93 +61,36 @@ |
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 | #include <unistd.h> |
392 | +#include <errno.h> |
393 | |
394 | #include <vector> |
395 | #include <string> |
396 | |
397 | -#include "drizzled/internal/my_sys.h" /* for internal::my_sync */ |
398 | - |
399 | -#include <drizzled/session.h> |
400 | -#include <drizzled/set_var.h> |
401 | +#include <drizzled/internal/my_sys.h> /* for internal::my_sync */ |
402 | +#include <drizzled/errmsg_print.h> |
403 | #include <drizzled/gettext.h> |
404 | -#include <drizzled/algorithm/crc32.h> |
405 | -#include <drizzled/message/transaction.pb.h> |
406 | -#include <google/protobuf/io/coded_stream.h> |
407 | |
408 | using namespace std; |
409 | using namespace drizzled; |
410 | -using namespace google; |
411 | - |
412 | -/** |
413 | - * Transaction Log plugin system variable - Is the log enabled? Only used on init(). |
414 | - * The enable() and disable() methods of the TransactionLog class control online |
415 | - * disabling. |
416 | - */ |
417 | -static bool sysvar_transaction_log_enabled= false; |
418 | -/** Transaction Log plugin system variable - The path to the log file used */ |
419 | -static char* sysvar_transaction_log_file= NULL; |
420 | -/** |
421 | - * Transaction Log plugin system variable - A debugging variable to assist |
422 | - * in truncating the log file. |
423 | - */ |
424 | -static bool sysvar_transaction_log_truncate_debug= false; |
425 | -static const char DEFAULT_LOG_FILE_PATH[]= "transaction.log"; /* In datadir... */ |
426 | -/** |
427 | - * Transaction Log plugin system variable - Should we write a CRC32 checksum for |
428 | - * each written Transaction message? |
429 | - */ |
430 | -static bool sysvar_transaction_log_checksum_enabled= false; |
431 | -/** |
432 | - * Numeric option controlling the sync/flush behaviour of the transaction |
433 | - * log. Options are: |
434 | - * |
435 | - * TransactionLog::SYNC_METHOD_OS == 0 ... let OS do sync'ing |
436 | - * TransactionLog::SYNC_METHOD_EVERY_WRITE == 1 ... sync on every write |
437 | - * TransactionLog::SYNC_METHOD_EVERY_SECOND == 2 ... sync at most once a second |
438 | - */ |
439 | -static uint32_t sysvar_transaction_log_sync_method= 0; |
440 | - |
441 | -/** DATA_DICTIONARY views */ |
442 | -static TransactionLogTool *transaction_log_tool; |
443 | -static TransactionLogEntriesTool *transaction_log_entries_tool; |
444 | -static TransactionLogTransactionsTool *transaction_log_transactions_tool; |
445 | - |
446 | -/** Index defined in transaction_log_index.cc */ |
447 | -extern TransactionLogIndex *transaction_log_index; |
448 | - |
449 | -/** Defined in print_transaction_message.cc */ |
450 | -extern plugin::Create_function<PrintTransactionMessageFunction> *print_transaction_message_func_factory; |
451 | -extern plugin::Create_function<HexdumpTransactionMessageFunction> *hexdump_transaction_message_func_factory; |
452 | - |
453 | -TransactionLog::TransactionLog(string name_arg, |
454 | - const string &in_log_file_path, |
455 | - bool in_do_checksum) |
456 | - : plugin::TransactionApplier(name_arg), |
457 | + |
458 | +TransactionLog *transaction_log= NULL; /* The singleton transaction log */ |
459 | + |
460 | +TransactionLog::TransactionLog(const string in_log_file_path, |
461 | + uint32_t in_sync_method) : |
462 | state(OFFLINE), |
463 | log_file_path(in_log_file_path), |
464 | has_error(false), |
465 | - error_message() |
466 | + error_message(), |
467 | + sync_method(in_sync_method) |
468 | { |
469 | - do_checksum= in_do_checksum; /* Have to do here, not in initialization list b/c atomic<> */ |
470 | - |
471 | /* Setup our log file and determine the next write offset... */ |
472 | log_file= open(log_file_path.c_str(), O_APPEND|O_CREAT|O_SYNC|O_WRONLY, S_IRWXU); |
473 | if (log_file == -1) |
474 | @@ -160,7 +101,6 @@ |
475 | error_message.append(strerror(errno)); |
476 | error_message.push_back('\n'); |
477 | has_error= true; |
478 | - deactivate(); |
479 | return; |
480 | } |
481 | |
482 | @@ -187,74 +127,26 @@ |
483 | TransactionLog::~TransactionLog() |
484 | { |
485 | /* Clear up any resources we've consumed */ |
486 | - if (isEnabled() && log_file != -1) |
487 | + if (log_file != -1) |
488 | { |
489 | (void) close(log_file); |
490 | } |
491 | } |
492 | |
493 | -void TransactionLog::apply(const message::Transaction &to_apply) |
494 | +off_t TransactionLog::writeEntry(const uint8_t *data, size_t data_length) |
495 | { |
496 | - uint8_t *buffer; /* Buffer we will write serialized header, |
497 | - message and trailing checksum to */ |
498 | - uint8_t *orig_buffer; |
499 | - |
500 | - size_t message_byte_length= to_apply.ByteSize(); |
501 | - ssize_t written; |
502 | - off_t cur_offset; |
503 | - size_t total_envelope_length= HEADER_TRAILER_BYTES + message_byte_length; |
504 | - |
505 | - /* |
506 | - * Attempt allocation of raw memory buffer for the header, |
507 | - * message and trailing checksum bytes. |
508 | - */ |
509 | - buffer= static_cast<uint8_t *>(malloc(total_envelope_length)); |
510 | - if (buffer == NULL) |
511 | - { |
512 | - errmsg_printf(ERRMSG_LVL_ERROR, |
513 | - _("Failed to allocate enough memory to buffer header, transaction message, and trailing checksum bytes. Tried to allocate %" PRId64 |
514 | - " bytes. Error: %s\n"), |
515 | - static_cast<int64_t>(total_envelope_length), |
516 | - strerror(errno)); |
517 | - state= CRASHED; |
518 | - deactivate(); |
519 | - return; |
520 | - } |
521 | - else |
522 | - orig_buffer= buffer; /* We will free() orig_buffer, as buffer is moved during write */ |
523 | + ssize_t written= 0; |
524 | |
525 | /* |
526 | * Do an atomic increment on the offset of the log file position |
527 | */ |
528 | - cur_offset= log_offset.fetch_and_add(static_cast<off_t>(total_envelope_length)); |
529 | + off_t cur_offset= log_offset.fetch_and_add(static_cast<off_t>(data_length)); |
530 | |
531 | /* |
532 | * We adjust cur_offset back to the original log_offset before |
533 | * the increment above... |
534 | */ |
535 | - cur_offset-= static_cast<off_t>((total_envelope_length)); |
536 | - |
537 | - /* |
538 | - * Write the header information, which is the message type and |
539 | - * the length of the transaction message into the buffer |
540 | - */ |
541 | - buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(static_cast<uint32_t>(ReplicationServices::TRANSACTION), buffer); |
542 | - buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(static_cast<uint32_t>(message_byte_length), buffer); |
543 | - |
544 | - /* |
545 | - * Now write the serialized transaction message, followed |
546 | - * by the optional checksum into the buffer. |
547 | - */ |
548 | - buffer= to_apply.SerializeWithCachedSizesToArray(buffer); |
549 | - |
550 | - uint32_t checksum= 0; |
551 | - if (do_checksum) |
552 | - { |
553 | - checksum= drizzled::algorithm::crc32(reinterpret_cast<char *>(buffer) - message_byte_length, message_byte_length); |
554 | - } |
555 | - |
556 | - /* We always write in network byte order */ |
557 | - buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(checksum, buffer); |
558 | + cur_offset-= static_cast<off_t>(data_length); |
559 | |
560 | /* |
561 | * Quick safety...if an error occurs above in another writer, the log |
562 | @@ -267,23 +159,22 @@ |
563 | * the original offset where an error occurred. |
564 | */ |
565 | log_offset= cur_offset; |
566 | - free(orig_buffer); |
567 | - return; |
568 | + return log_offset; |
569 | } |
570 | |
571 | /* Write the full buffer in one swoop */ |
572 | do |
573 | { |
574 | - written= pwrite(log_file, orig_buffer, total_envelope_length, cur_offset); |
575 | + written= pwrite(log_file, data, data_length, cur_offset); |
576 | } |
577 | while (written == -1 && errno == EINTR); /* Just retry the write when interrupted by a signal... */ |
578 | |
579 | - if (unlikely(written != static_cast<ssize_t>(total_envelope_length))) |
580 | + if (unlikely(written != static_cast<ssize_t>(data_length))) |
581 | { |
582 | errmsg_printf(ERRMSG_LVL_ERROR, |
583 | - _("Failed to write full size of transaction. Tried to write %" PRId64 |
584 | + _("Failed to write full size of log entry. Tried to write %" PRId64 |
585 | " bytes at offset %" PRId64 ", but only wrote %" PRId32 " bytes. Error: %s\n"), |
586 | - static_cast<int64_t>(total_envelope_length), |
587 | + static_cast<int64_t>(data_length), |
588 | static_cast<int64_t>(cur_offset), |
589 | static_cast<int64_t>(written), |
590 | strerror(errno)); |
591 | @@ -293,29 +184,22 @@ |
592 | * the original offset where an error occurred. |
593 | */ |
594 | log_offset= cur_offset; |
595 | - deactivate(); |
596 | } |
597 | - free(orig_buffer); |
598 | |
599 | int error_code= syncLogFile(); |
600 | |
601 | - transaction_log_index->addEntry(TransactionLogEntry(ReplicationServices::TRANSACTION, |
602 | - cur_offset, |
603 | - total_envelope_length), |
604 | - to_apply, |
605 | - checksum); |
606 | - |
607 | if (unlikely(error_code != 0)) |
608 | { |
609 | errmsg_printf(ERRMSG_LVL_ERROR, |
610 | _("Failed to sync log file. Got error: %s\n"), |
611 | strerror(errno)); |
612 | } |
613 | + return cur_offset; |
614 | } |
615 | |
616 | int TransactionLog::syncLogFile() |
617 | { |
618 | - switch (sysvar_transaction_log_sync_method) |
619 | + switch (sync_method) |
620 | { |
621 | case SYNC_METHOD_EVERY_WRITE: |
622 | return internal::my_sync(log_file, 0); |
623 | @@ -347,20 +231,11 @@ |
624 | |
625 | void TransactionLog::truncate() |
626 | { |
627 | - bool orig_is_enabled= isEnabled(); |
628 | - disable(); |
629 | - |
630 | /* |
631 | - * Wait a short amount of time before truncating. This just prevents error messages |
632 | - * from being produced during a call to apply(). Calling disable() above |
633 | - * means that once the current caller to apply() is done, no other calls are made to |
634 | - * apply() before enable is reset to its original state |
635 | - * |
636 | * @note |
637 | * |
638 | - * This is DEBUG code only! |
639 | + * This is NOT THREAD SAFE! DEBUG/TEST code only! |
640 | */ |
641 | - usleep(500); /* Sleep for half a second */ |
642 | log_offset= (off_t) 0; |
643 | int result; |
644 | do |
645 | @@ -368,12 +243,6 @@ |
646 | result= ftruncate(log_file, log_offset); |
647 | } |
648 | while (result == -1 && errno == EINTR); |
649 | - |
650 | - /* Clear the transaction log index data */ |
651 | - transaction_log_index->clear(); |
652 | - |
653 | - if (orig_is_enabled) |
654 | - enable(); |
655 | } |
656 | |
657 | bool TransactionLog::findLogFilenameContainingTransactionId(const ReplicationServices::GlobalTransactionId&, |
658 | @@ -399,180 +268,7 @@ |
659 | error_message.clear(); |
660 | } |
661 | |
662 | -const std::string &TransactionLog::getErrorMessage() const |
663 | +const string &TransactionLog::getErrorMessage() const |
664 | { |
665 | return error_message; |
666 | } |
667 | - |
668 | -TransactionLog *transaction_log= NULL; /* The singleton transaction log */ |
669 | - |
670 | -static int init(drizzled::plugin::Registry ®istry) |
671 | -{ |
672 | - /* Create and initialize the transaction log itself */ |
673 | - if (sysvar_transaction_log_enabled) |
674 | - { |
675 | - transaction_log= new (nothrow) TransactionLog("transaction_log_applier", |
676 | - string(sysvar_transaction_log_file), |
677 | - sysvar_transaction_log_checksum_enabled); |
678 | - |
679 | - if (transaction_log == NULL) |
680 | - { |
681 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLog instance. Got error: %s\n"), |
682 | - strerror(errno)); |
683 | - return 1; |
684 | - } |
685 | - else |
686 | - { |
687 | - /* Check to see if the log was not created properly */ |
688 | - if (transaction_log->hasError()) |
689 | - { |
690 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log. Got error: %s\n"), |
691 | - transaction_log->getErrorMessage().c_str()); |
692 | - return 1; |
693 | - } |
694 | - } |
695 | - registry.add(transaction_log); |
696 | - |
697 | - /* Setup DATA_DICTIONARY views */ |
698 | - |
699 | - transaction_log_tool= new(std::nothrow)TransactionLogTool; |
700 | - registry.add(transaction_log_tool); |
701 | - transaction_log_entries_tool= new(std::nothrow)TransactionLogEntriesTool; |
702 | - registry.add(transaction_log_entries_tool); |
703 | - transaction_log_transactions_tool= new(std::nothrow)TransactionLogTransactionsTool; |
704 | - registry.add(transaction_log_transactions_tool); |
705 | - |
706 | - /* Setup the module's UDFs */ |
707 | - print_transaction_message_func_factory= |
708 | - new plugin::Create_function<PrintTransactionMessageFunction>("print_transaction_message"); |
709 | - registry.add(print_transaction_message_func_factory); |
710 | - |
711 | - hexdump_transaction_message_func_factory= |
712 | - new plugin::Create_function<HexdumpTransactionMessageFunction>("hexdump_transaction_message"); |
713 | - registry.add(hexdump_transaction_message_func_factory); |
714 | - |
715 | - /* Create and initialize the transaction log index */ |
716 | - transaction_log_index= new (nothrow) TransactionLogIndex(*transaction_log); |
717 | - if (transaction_log_index == NULL) |
718 | - { |
719 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLogIndex instance. Got error: %s\n"), |
720 | - strerror(errno)); |
721 | - return 1; |
722 | - } |
723 | - else |
724 | - { |
725 | - /* Check to see if the index was not created properly */ |
726 | - if (transaction_log_index->hasError()) |
727 | - { |
728 | - errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log Index. Got error: %s\n"), |
729 | - transaction_log_index->getErrorMessage().c_str()); |
730 | - return 1; |
731 | - } |
732 | - } |
733 | - |
734 | - /* |
735 | - * Setup the background worker thread which maintains |
736 | - * summary information about the transaction log. |
737 | - */ |
738 | - if (initTransactionLogBackgroundWorker()) |
739 | - return 1; /* Error message output handled in function above */ |
740 | - } |
741 | - return 0; |
742 | -} |
743 | - |
744 | -static int deinit(drizzled::plugin::Registry ®istry) |
745 | -{ |
746 | - /* Cleanup the transaction log itself */ |
747 | - if (transaction_log) |
748 | - { |
749 | - registry.remove(transaction_log); |
750 | - delete transaction_log; |
751 | - delete transaction_log_index; |
752 | - |
753 | - /* Cleanup the DATA_DICTIONARY views */ |
754 | - registry.remove(transaction_log_tool); |
755 | - delete transaction_log_tool; |
756 | - registry.remove(transaction_log_entries_tool); |
757 | - delete transaction_log_entries_tool; |
758 | - registry.remove(transaction_log_transactions_tool); |
759 | - delete transaction_log_transactions_tool; |
760 | - |
761 | - /* Cleanup module UDFs */ |
762 | - registry.remove(print_transaction_message_func_factory); |
763 | - delete print_transaction_message_func_factory; |
764 | - registry.remove(hexdump_transaction_message_func_factory); |
765 | - delete hexdump_transaction_message_func_factory; |
766 | - } |
767 | - |
768 | - return 0; |
769 | -} |
770 | - |
771 | -static void set_truncate_debug(Session *, |
772 | - drizzle_sys_var *, |
773 | - void *, |
774 | - const void *save) |
775 | -{ |
776 | - /* |
777 | - * The const void * save comes directly from the check function, |
778 | - * which should simply return the result from the set statement. |
779 | - */ |
780 | - if (transaction_log) |
781 | - if (*(bool *)save != false) |
782 | - transaction_log->truncate(); |
783 | -} |
784 | - |
785 | -static DRIZZLE_SYSVAR_BOOL(enable, |
786 | - sysvar_transaction_log_enabled, |
787 | - PLUGIN_VAR_NOCMDARG, |
788 | - N_("Enable transaction log"), |
789 | - NULL, /* check func */ |
790 | - NULL, /* update func */ |
791 | - false /* default */); |
792 | - |
793 | -static DRIZZLE_SYSVAR_BOOL(truncate_debug, |
794 | - sysvar_transaction_log_truncate_debug, |
795 | - PLUGIN_VAR_NOCMDARG, |
796 | - N_("DEBUGGING - Truncate transaction log"), |
797 | - NULL, /* check func */ |
798 | - set_truncate_debug, /* update func */ |
799 | - false /* default */); |
800 | - |
801 | -static DRIZZLE_SYSVAR_STR(log_file, |
802 | - sysvar_transaction_log_file, |
803 | - PLUGIN_VAR_READONLY, |
804 | - N_("Path to the file to use for transaction log"), |
805 | - NULL, /* check func */ |
806 | - NULL, /* update func*/ |
807 | - DEFAULT_LOG_FILE_PATH /* default */); |
808 | - |
809 | -static DRIZZLE_SYSVAR_BOOL(enable_checksum, |
810 | - sysvar_transaction_log_checksum_enabled, |
811 | - PLUGIN_VAR_NOCMDARG, |
812 | - N_("Enable CRC32 Checksumming of each written transaction log entry"), |
813 | - NULL, /* check func */ |
814 | - NULL, /* update func */ |
815 | - false /* default */); |
816 | - |
817 | -static DRIZZLE_SYSVAR_UINT(sync_method, |
818 | - sysvar_transaction_log_sync_method, |
819 | - PLUGIN_VAR_OPCMDARG, |
820 | - N_("0 == rely on operating system to sync log file (default), " |
821 | - "1 == sync file at each transaction write, " |
822 | - "2 == sync log file once per second"), |
823 | - NULL, /* check func */ |
824 | - NULL, /* update func */ |
825 | - 0, /* default */ |
826 | - 0, |
827 | - 2, |
828 | - 0); |
829 | - |
830 | -static drizzle_sys_var* sys_variables[]= { |
831 | - DRIZZLE_SYSVAR(enable), |
832 | - DRIZZLE_SYSVAR(truncate_debug), |
833 | - DRIZZLE_SYSVAR(log_file), |
834 | - DRIZZLE_SYSVAR(enable_checksum), |
835 | - DRIZZLE_SYSVAR(sync_method), |
836 | - NULL |
837 | -}; |
838 | - |
839 | -DRIZZLE_PLUGIN(init, deinit, sys_variables); |
840 | |
841 | === modified file 'plugin/transaction_log/transaction_log.h' |
842 | --- plugin/transaction_log/transaction_log.h 2009-12-11 18:39:37 +0000 |
843 | +++ plugin/transaction_log/transaction_log.h 2010-03-05 19:18:29 +0000 |
844 | @@ -2,10 +2,11 @@ |
845 | * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
846 | * |
847 | * Copyright (C) 2008-2009 Sun Microsystems |
848 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
849 | * |
850 | * Authors: |
851 | * |
852 | - * Jay Pipes <joinfu@sun.com> |
853 | + * Jay Pipes <jaypipes@gmail.com.com> |
854 | * |
855 | * This program is free software; you can redistribute it and/or modify |
856 | * it under the terms of the GNU General Public License as published by |
857 | @@ -25,18 +26,13 @@ |
858 | /** |
859 | * @file |
860 | * |
861 | - * Defines the API of the default transaction log. |
862 | - * |
863 | - * @see drizzled/plugin/replicator.h |
864 | - * @see drizzled/plugin/applier.h |
865 | + * Defines the API of the transaction log file descriptor. |
866 | * |
867 | * @details |
868 | * |
869 | - * The TransactionLog applies events it receives from the ReplicationServices |
870 | - * server component to a simple log file on disk. |
871 | - * |
872 | - * Transactions are received in no guaranteed order and the command log |
873 | - * is in charge of writing these events to the log as they are received. |
874 | + * Basically, the TransactionLog is a descriptor for a log |
875 | + * file containing transaction messages that is written by |
876 | + * the TransactionLogApplier plugin(s). |
877 | */ |
878 | |
879 | #ifndef PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_H |
880 | @@ -44,15 +40,13 @@ |
881 | |
882 | #include <drizzled/atomics.h> |
883 | #include <drizzled/replication_services.h> |
884 | -#include <drizzled/plugin/transaction_replicator.h> |
885 | -#include <drizzled/plugin/transaction_applier.h> |
886 | |
887 | #include "transaction_log_entry.h" |
888 | |
889 | #include <vector> |
890 | #include <string> |
891 | |
892 | -class TransactionLog: public drizzled::plugin::TransactionApplier |
893 | +class TransactionLog |
894 | { |
895 | public: |
896 | static const uint32_t HEADER_TRAILER_BYTES= sizeof(uint32_t) + /* 4-byte msg type header */ |
897 | @@ -75,31 +69,13 @@ |
898 | static const uint32_t SYNC_METHOD_EVERY_WRITE= 1; //< Sync on every write to the log file |
899 | static const uint32_t SYNC_METHOD_EVERY_SECOND= 2; ///< Sync no more than once a second |
900 | public: |
901 | - TransactionLog(std::string name_arg, |
902 | - const std::string &in_log_file_path, |
903 | - bool in_do_checksum); |
904 | + TransactionLog(const std::string in_log_file_path, |
905 | + uint32_t in_sync_method); |
906 | |
907 | /** Destructor */ |
908 | ~TransactionLog(); |
909 | |
910 | /** |
911 | - * Applies a Transaction to the serial log |
912 | - * |
913 | - * @note |
914 | - * |
915 | - * It is important to note that memory allocation for the |
916 | - * supplied pointer is not guaranteed after the completion |
917 | - * of this function -- meaning the caller can dispose of the |
918 | - * supplied message. Therefore, appliers which are |
919 | - * implementing an asynchronous replication system must copy |
920 | - * the supplied message to their own controlled memory storage |
921 | - * area. |
922 | - * |
923 | - * @param Transaction message to be replicated |
924 | - */ |
925 | - void apply(const drizzled::message::Transaction &to_apply); |
926 | - |
927 | - /** |
928 | * Returns the current offset into the log |
929 | */ |
930 | inline off_t getLogOffset() |
931 | @@ -126,6 +102,19 @@ |
932 | } |
933 | |
934 | /** |
935 | + * Writes a chunk of data to the log file of a specified |
936 | + * length and returns the offset at which the chunk of |
937 | + * data was written. |
938 | + * |
939 | + * @param[in] Bytes to write |
940 | + * @param[in[ Length of bytes to write |
941 | + * |
942 | + * @retval |
943 | + * Returns the write offset if the write succeeded, OFF_T_MAX otherwise. |
944 | + */ |
945 | + off_t writeEntry(const uint8_t *data, size_t data_length); |
946 | + |
947 | + /** |
948 | * Truncates the existing log file |
949 | * |
950 | * @note |
951 | @@ -185,12 +174,12 @@ |
952 | |
953 | int log_file; ///< Handle for our log file |
954 | Status state; ///< The state the log is in |
955 | - drizzled::atomic<bool> do_checksum; ///< Do a CRC32 checksum when writing Transaction message to log? |
956 | const std::string log_file_path; ///< Full path to the log file |
957 | std::string log_file_name; ///< Name of the log file |
958 | drizzled::atomic<off_t> log_offset; ///< Offset in log file where log will write next command |
959 | bool has_error; ///< Is the log in error? |
960 | std::string error_message; ///< Current error message |
961 | + uint32_t sync_method; ///< Determines behaviour of syncing log file |
962 | time_t last_sync_time; ///< Last time the log file was synced (only set in SYNC_METHOD_EVERY_SECOND) |
963 | }; |
964 | |
965 | |
966 | === added file 'plugin/transaction_log/transaction_log_applier.cc' |
967 | --- plugin/transaction_log/transaction_log_applier.cc 1970-01-01 00:00:00 +0000 |
968 | +++ plugin/transaction_log/transaction_log_applier.cc 2010-03-05 19:18:29 +0000 |
969 | @@ -0,0 +1,146 @@ |
970 | +/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- |
971 | + * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
972 | + * |
973 | + * Copyright (C) 2008-2009 Sun Microsystems |
974 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
975 | + * |
976 | + * Authors: |
977 | + * |
978 | + * Jay Pipes <jaypipes@gmail.com.com> |
979 | + * |
980 | + * This program is free software; you can redistribute it and/or modify |
981 | + * it under the terms of the GNU General Public License as published by |
982 | + * the Free Software Foundation; either version 2 of the License, or |
983 | + * (at your option) any later version. |
984 | + * |
985 | + * This program is distributed in the hope that it will be useful, |
986 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
987 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
988 | + * GNU General Public License for more details. |
989 | + * |
990 | + * You should have received a copy of the GNU General Public License |
991 | + * along with this program; if not, write to the Free Software |
992 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
993 | + */ |
994 | + |
995 | +/** |
996 | + * @file |
997 | + * |
998 | + * Defines the implementation of the transaction applier plugin |
999 | + * for the transaction log. |
1000 | + * |
1001 | + * @see drizzled/plugin/transaction_replicator.h |
1002 | + * @see drizzled/plugin/transaction_applier.h |
1003 | + * |
1004 | + * @details |
1005 | + * |
1006 | + * The TransactionLogApplier::apply() method constructs the entry |
1007 | + * in the transaction log from the supplied Transaction message and |
1008 | + * asks its associated TransactionLog object to write this entry. |
1009 | + * |
1010 | + * Upon a successful write, the applier adds some information about |
1011 | + * the written transaction to the transaction log index. |
1012 | + */ |
1013 | + |
1014 | +#include "config.h" |
1015 | +#include "transaction_log.h" |
1016 | +#include "transaction_log_applier.h" |
1017 | +#include "transaction_log_index.h" |
1018 | + |
1019 | +#include <sys/stat.h> |
1020 | +#include <fcntl.h> |
1021 | +#include <unistd.h> |
1022 | +#include <errno.h> |
1023 | + |
1024 | +#include <drizzled/errmsg_print.h> |
1025 | +#include <drizzled/gettext.h> |
1026 | +#include <drizzled/algorithm/crc32.h> |
1027 | +#include <drizzled/message/transaction.pb.h> |
1028 | +#include <google/protobuf/io/coded_stream.h> |
1029 | + |
1030 | +using namespace std; |
1031 | +using namespace drizzled; |
1032 | +using namespace google; |
1033 | + |
1034 | +TransactionLogApplier *transaction_log_applier= NULL; /* The singleton transaction log applier */ |
1035 | + |
1036 | +extern TransactionLogIndex *transaction_log_index; |
1037 | + |
1038 | +TransactionLogApplier::TransactionLogApplier(const string name_arg, |
1039 | + TransactionLog &in_transaction_log, |
1040 | + bool in_do_checksum) : |
1041 | + plugin::TransactionApplier(name_arg), |
1042 | + transaction_log(in_transaction_log), |
1043 | + do_checksum(in_do_checksum) |
1044 | +{ |
1045 | +} |
1046 | + |
1047 | +TransactionLogApplier::~TransactionLogApplier() |
1048 | +{ |
1049 | +} |
1050 | + |
1051 | +void TransactionLogApplier::apply(const message::Transaction &to_apply) |
1052 | +{ |
1053 | + uint8_t *buffer; /* Buffer we will write serialized header, |
1054 | + message and trailing checksum to */ |
1055 | + uint8_t *orig_buffer; |
1056 | + |
1057 | + size_t message_byte_length= to_apply.ByteSize(); |
1058 | + size_t total_envelope_length= TransactionLog::HEADER_TRAILER_BYTES + message_byte_length; |
1059 | + |
1060 | + /* |
1061 | + * Attempt allocation of raw memory buffer for the header, |
1062 | + * message and trailing checksum bytes. |
1063 | + */ |
1064 | + buffer= static_cast<uint8_t *>(malloc(total_envelope_length)); |
1065 | + if (buffer == NULL) |
1066 | + { |
1067 | + errmsg_printf(ERRMSG_LVL_ERROR, |
1068 | + _("Failed to allocate enough memory to buffer header, " |
1069 | + "transaction message, and trailing checksum bytes. Tried to allocate %" PRId64 |
1070 | + " bytes. Error: %s\n"), |
1071 | + static_cast<int64_t>(total_envelope_length), |
1072 | + strerror(errno)); |
1073 | + return; |
1074 | + } |
1075 | + else |
1076 | + orig_buffer= buffer; /* We will free() orig_buffer, as buffer is moved during write */ |
1077 | + |
1078 | + /* |
1079 | + * Write the header information, which is the message type and |
1080 | + * the length of the transaction message into the buffer |
1081 | + */ |
1082 | + buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray( |
1083 | + static_cast<uint32_t>(ReplicationServices::TRANSACTION), buffer); |
1084 | + buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray( |
1085 | + static_cast<uint32_t>(message_byte_length), buffer); |
1086 | + |
1087 | + /* |
1088 | + * Now write the serialized transaction message, followed |
1089 | + * by the optional checksum into the buffer. |
1090 | + */ |
1091 | + buffer= to_apply.SerializeWithCachedSizesToArray(buffer); |
1092 | + |
1093 | + uint32_t checksum= 0; |
1094 | + if (do_checksum) |
1095 | + { |
1096 | + checksum= drizzled::algorithm::crc32( |
1097 | + reinterpret_cast<char *>(buffer) - message_byte_length, message_byte_length); |
1098 | + } |
1099 | + |
1100 | + /* We always write in network byte order */ |
1101 | + buffer= protobuf::io::CodedOutputStream::WriteLittleEndian32ToArray(checksum, buffer); |
1102 | + |
1103 | + /* Ask the transaction log to write the entry and return where it wrote it */ |
1104 | + off_t written_to= transaction_log.writeEntry(orig_buffer, total_envelope_length); |
1105 | + |
1106 | + free(orig_buffer); |
1107 | + |
1108 | + /* Add an entry to the index describing what was just applied */ |
1109 | + transaction_log_index->addEntry(TransactionLogEntry(ReplicationServices::TRANSACTION, |
1110 | + written_to, |
1111 | + total_envelope_length), |
1112 | + to_apply, |
1113 | + checksum); |
1114 | + |
1115 | +} |
1116 | |
1117 | === added file 'plugin/transaction_log/transaction_log_applier.h' |
1118 | --- plugin/transaction_log/transaction_log_applier.h 1970-01-01 00:00:00 +0000 |
1119 | +++ plugin/transaction_log/transaction_log_applier.h 2010-03-05 19:18:29 +0000 |
1120 | @@ -0,0 +1,83 @@ |
1121 | +/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- |
1122 | + * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
1123 | + * |
1124 | + * Copyright (C) 2008-2009 Sun Microsystems |
1125 | + * Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com> |
1126 | + * |
1127 | + * Authors: |
1128 | + * |
1129 | + * Jay Pipes <jaypipes@gmail.com.com> |
1130 | + * |
1131 | + * This program is free software; you can redistribute it and/or modify |
1132 | + * it under the terms of the GNU General Public License as published by |
1133 | + * the Free Software Foundation; either version 2 of the License, or |
1134 | + * (at your option) any later version. |
1135 | + * |
1136 | + * This program is distributed in the hope that it will be useful, |
1137 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1138 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1139 | + * GNU General Public License for more details. |
1140 | + * |
1141 | + * You should have received a copy of the GNU General Public License |
1142 | + * along with this program; if not, write to the Free Software |
1143 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1144 | + */ |
1145 | + |
1146 | +/** |
1147 | + * @file |
1148 | + * |
1149 | + * Defines the API of the transaction log applier. |
1150 | + * |
1151 | + * @see drizzled/plugin/replicator.h |
1152 | + * @see drizzled/plugin/applier.h |
1153 | + */ |
1154 | + |
1155 | +#ifndef PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_APPLIER_H |
1156 | +#define PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_APPLIER_H |
1157 | + |
1158 | +#include <drizzled/replication_services.h> |
1159 | +#include <drizzled/plugin/transaction_applier.h> |
1160 | + |
1161 | +#include "transaction_log_entry.h" |
1162 | + |
1163 | +#include <vector> |
1164 | +#include <string> |
1165 | + |
1166 | +class TransactionLog; |
1167 | + |
1168 | +class TransactionLogApplier: public drizzled::plugin::TransactionApplier |
1169 | +{ |
1170 | +public: |
1171 | + TransactionLogApplier(const std::string name_arg, |
1172 | + TransactionLog &in_transaction_log, |
1173 | + bool in_do_checksum); |
1174 | + |
1175 | + /** Destructor */ |
1176 | + ~TransactionLogApplier(); |
1177 | + |
1178 | + /** |
1179 | + * Applies a Transaction to the serial log |
1180 | + * |
1181 | + * @note |
1182 | + * |
1183 | + * It is important to note that memory allocation for the |
1184 | + * supplied pointer is not guaranteed after the completion |
1185 | + * of this function -- meaning the caller can dispose of the |
1186 | + * supplied message. Therefore, appliers which are |
1187 | + * implementing an asynchronous replication system must copy |
1188 | + * the supplied message to their own controlled memory storage |
1189 | + * area. |
1190 | + * |
1191 | + * @param Transaction message to be replicated |
1192 | + */ |
1193 | + void apply(const drizzled::message::Transaction &to_apply); |
1194 | +private: |
1195 | + /* Don't allows these */ |
1196 | + TransactionLogApplier(); |
1197 | + TransactionLogApplier(const TransactionLogApplier &other); |
1198 | + TransactionLogApplier &operator=(const TransactionLogApplier &other); |
1199 | + TransactionLog &transaction_log; |
1200 | + bool do_checksum; ///< Do a CRC32 checksum when writing Transaction message to log? |
1201 | +}; |
1202 | + |
1203 | +#endif /* PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_APPLIER_H */ |
1204 | |
1205 | === modified file 'plugin/transaction_log/transaction_log_index.cc' |
1206 | --- plugin/transaction_log/transaction_log_index.cc 2010-03-05 04:44:58 +0000 |
1207 | +++ plugin/transaction_log/transaction_log_index.cc 2010-03-05 19:18:29 +0000 |
1208 | @@ -42,7 +42,6 @@ |
1209 | |
1210 | TransactionLogIndex::TransactionLogIndex(TransactionLog &in_log) : |
1211 | log(in_log), |
1212 | - log_file(-1), |
1213 | index_file(-1), |
1214 | index_file_path(), |
1215 | has_error(false), |
1216 | |
1217 | === modified file 'plugin/transaction_log/transaction_log_index.h' |
1218 | --- plugin/transaction_log/transaction_log_index.h 2010-03-05 04:44:58 +0000 |
1219 | +++ plugin/transaction_log/transaction_log_index.h 2010-03-05 19:18:29 +0000 |
1220 | @@ -131,7 +131,6 @@ |
1221 | void clearError(); |
1222 | |
1223 | TransactionLog &log; ///< The transaction log instance |
1224 | - int log_file; ///< File descriptor for the transaction log file |
1225 | int index_file; ///< File descriptor for the transaction log on-disk index file |
1226 | const std::string index_file_path; ///< Filename of the on-disk transaction log index |
1227 | bool has_error; ///< Index is in error mode? |
1228 | |
1229 | === modified file 'plugin/transaction_log/transaction_log_reader.cc' |
1230 | --- plugin/transaction_log/transaction_log_reader.cc 2010-01-06 02:20:42 +0000 |
1231 | +++ plugin/transaction_log/transaction_log_reader.cc 2010-03-05 19:18:29 +0000 |
1232 | @@ -49,6 +49,7 @@ |
1233 | #include <cerrno> |
1234 | |
1235 | #include "transaction_log_reader.h" |
1236 | +#include "transaction_log.h" |
1237 | |
1238 | #include <drizzled/gettext.h> |
1239 | #include <drizzled/message/transaction.pb.h> |
1240 | |
1241 | === modified file 'plugin/transaction_log/transaction_log_reader.h' |
1242 | --- plugin/transaction_log/transaction_log_reader.h 2009-10-20 03:04:07 +0000 |
1243 | +++ plugin/transaction_log/transaction_log_reader.h 2010-03-05 19:18:29 +0000 |
1244 | @@ -38,10 +38,10 @@ |
1245 | #ifndef PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_READER_H |
1246 | #define PLUGIN_TRANSACTION_LOG_TRANSACTION_LOG_READER_H |
1247 | |
1248 | -#include "transaction_log.h" |
1249 | - |
1250 | #include <drizzled/plugin/transaction_reader.h> |
1251 | |
1252 | +class TransactionLog; |
1253 | + |
1254 | /** |
1255 | * A class which reads Transaction messages from the Transaction log file |
1256 | */ |
* Completes the blueprint for splitting the XA Resource Manager
API from the storage engine API:
We add a new plugin: :XaResourceMana ger abstract interface class
which exposes the X/Open XA distributed transaction protocol for
resource managers.
We add a new plugin: :MonitoredInTra nsaction base class from :TransactionSer vices component) derive.
which all plugins that need monitored by Drizzle's transaction
manager (drizzled:
All plugin: :StorageEngine' s now derive from plugin: :MonitoredInTra nsaction saction, as
since all storage engines a monitored by the transaction manager
and the Session keeps a "slot" available for keeping the engine's
per-session data state. In a future patch, the transaction log's
XaApplier plugin will also derive from MonitoredInTran
the transaction log, in XA mode, is also monitored by Drizzle's
transaction manager and automatically enlisted in XA transactions.
* Updates all documentation in /drizzled/ transaction_ services. cc
to accurately reflect Drizzle's new transaction management
process and explicit transaction and statement boundaries.
* Kills off dead code:
binlog_ format_ names gine::slot (now plugin: :MonitoredInTra nsaction: :getId( )) onalStorageEngi ne::two_ phase_commit (same as above)
ha_init()
total_ha, total_ha_2pc (no longer necessary, as the above-mentioned
abstract base classes provide all of this functionality)
StorageEn
Transacti