]> git.ipfire.org Git - thirdparty/pdns.git/blob - modules/opendbxbackend/odbxbackend.cc
make DomainInfo not carry IP addresses as strings. And some subsequent cleanups..
[thirdparty/pdns.git] / modules / opendbxbackend / odbxbackend.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 * originally authored by Norbert Sendetzky
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * In addition, for the avoidance of any doubt, permission is granted to
11 * link this program with OpenSSL and to (re)distribute the binaries
12 * produced as the result of such linking.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include "odbxbackend.hh"
27
28
29
30 inline string& strbind( const string& search, const string& replace, string& subject )
31 {
32 size_t pos = 0;
33
34 while( ( pos = subject.find( search, pos ) ) != string::npos )
35 {
36 subject.replace( pos, search.size(), replace );
37 pos += replace.size();
38 }
39
40 return subject;
41 }
42
43
44
45 OdbxBackend::OdbxBackend( const string& suffix )
46 {
47 vector<string> hosts;
48
49
50 try
51 {
52 m_result = NULL;
53 m_handle[READ] = NULL;
54 m_handle[WRITE] = NULL;
55 m_myname = "[OpendbxBackend]";
56 m_default_ttl = arg().asNum( "default-ttl" );
57 m_qlog = arg().mustDo( "query-logging" );
58
59 setArgPrefix( "opendbx" + suffix );
60
61 if( getArg( "host" ).size() > 0 )
62 {
63 g_log.log( m_myname + " WARNING: Using deprecated opendbx-host parameter", Logger::Warning );
64 stringtok( m_hosts[READ], getArg( "host" ), ", " );
65 m_hosts[WRITE] = m_hosts[READ];
66 }
67 else
68 {
69 stringtok( m_hosts[READ], getArg( "host-read" ), ", " );
70 stringtok( m_hosts[WRITE], getArg( "host-write" ), ", " );
71 }
72
73 if( !connectTo( m_hosts[READ], READ ) ) { throw( PDNSException( "Fatal: Connecting to server for reading failed" ) ); }
74 if( !connectTo( m_hosts[WRITE], WRITE ) ) { throw( PDNSException( "Fatal: Connecting to server for writing failed" ) ); }
75 }
76 catch( std::exception& e )
77 {
78 g_log.log( m_myname + " OdbxBackend(): Caught STL exception - " + e.what(), Logger::Error );
79 throw( PDNSException( "Fatal: STL exception" ) );
80 }
81 }
82
83
84
85 OdbxBackend::~OdbxBackend()
86 {
87 odbx_unbind( m_handle[WRITE] );
88 odbx_unbind( m_handle[READ] );
89
90 odbx_finish( m_handle[WRITE] );
91 odbx_finish( m_handle[READ] );
92 }
93
94
95
96 bool OdbxBackend::getDomainInfo( const DNSName& domain, DomainInfo& di, bool getSerial )
97 {
98 const char* tmp;
99
100
101 try
102 {
103 DLOG( g_log.log( m_myname + " getDomainInfo()", Logger::Debug ) );
104
105 string stmt = getArg( "sql-zoneinfo" );
106 string& stmtref = strbind( ":name", escape( domain.makeLowerCase().toStringRootDot(), READ ), stmt );
107
108 if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
109 if( !getRecord( READ ) ) { return false; }
110
111 do
112 {
113 di.id = 0;
114 di.zone.clear();
115 di.masters.clear();
116 di.last_check = 0;
117 di.notified_serial = 0;
118 di.kind = DomainInfo::Native;
119 di.backend = this;
120 di.serial = 0;
121
122 if( getSerial && ( tmp = odbx_field_value( m_result, 6 ) ) != NULL )
123 {
124 SOAData sd;
125
126 sd.serial = 0;
127 fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd );
128
129 if( sd.serial == 0 && ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
130 {
131 sd.serial = strtol( tmp, NULL, 10 );
132 }
133
134 di.serial = sd.serial;
135 }
136
137 if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL )
138 {
139 di.last_check = strtol( tmp, NULL, 10 );
140 }
141
142 if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
143 {
144 vector<string> masters;
145 stringtok(masters, string( tmp, odbx_field_length( m_result, 3 ) ), ", \t");
146 for(const auto& m : masters)
147 {
148 di.masters.emplace_back(m, 53);
149 }
150 }
151
152 if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
153 {
154 if( !strncmp( tmp, "SLAVE", 5 ) )
155 {
156 di.kind = DomainInfo::Slave;
157 }
158 else if( !strncmp( tmp, "MASTER", 6 ) )
159 {
160 di.kind = DomainInfo::Master;
161 }
162 }
163
164 if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
165 {
166 di.zone = DNSName(string( tmp, odbx_field_length( m_result, 1 ) ));
167 }
168
169 if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL )
170 {
171 di.id = strtol( tmp, NULL, 10 );
172 }
173 }
174 while( getRecord( READ ) );
175 }
176 catch( std::exception& e )
177 {
178 g_log.log( m_myname + " getDomainInfo: Caught STL std::exception - " + e.what(), Logger::Error );
179 return false;
180 }
181
182 return true;
183 }
184
185
186
187 bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd, bool unmodifiedSerial)
188 {
189 const char* tmp;
190
191
192 try
193 {
194 DLOG( g_log.log( m_myname + " getSOA()", Logger::Debug ) );
195
196 string stmt = getArg( "sql-lookupsoa" );
197 string& stmtref = strbind( ":name", escape( domain.makeLowerCase().toStringRootDot(), READ ), stmt );
198
199 if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
200 if( !getRecord( READ ) ) { return false; }
201
202 do
203 {
204 sd.qname = domain;
205 sd.serial = 0;
206 sd.ttl = m_default_ttl;
207
208 if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
209 {
210 fillSOAData( string( tmp, odbx_field_length( m_result, 3 ) ), sd );
211 }
212
213 if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
214 {
215 sd.ttl = strtoul( tmp, NULL, 10 );
216 }
217
218 if( !unmodifiedSerial && sd.serial == 0 && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
219 {
220 sd.serial = strtol( tmp, NULL, 10 );
221 }
222
223 if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL )
224 {
225 sd.domain_id = strtol( tmp, NULL, 10 );
226 }
227
228 if( sd.nameserver.empty() )
229 {
230 sd.nameserver = DNSName(arg()["default-soa-name"]);
231 }
232
233 if( sd.hostmaster.empty() )
234 {
235 sd.hostmaster = DNSName("hostmaster") + DNSName(domain);
236 }
237
238 sd.db = this;
239 }
240 while( getRecord( READ ) );
241 }
242 catch( std::exception& e )
243 {
244 g_log.log( m_myname + " getSOA: Caught STL exception - " + e.what(), Logger::Error );
245 return false;
246 }
247
248 return true;
249 }
250
251
252
253 bool OdbxBackend::list( const DNSName& target, int zoneid, bool include_disabled )
254 {
255 try
256 {
257 DLOG( g_log.log( m_myname + " list()", Logger::Debug ) );
258
259 m_qname.clear();
260 m_result = NULL;
261
262 int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
263
264 if( len < 0 )
265 {
266 g_log.log( m_myname + " list: Unable to convert zone id to string - format error", Logger::Error );
267 return false;
268 }
269
270 if( len > static_cast<int>(sizeof( m_buffer )) - 1 )
271 {
272 g_log.log( m_myname + " list: Unable to convert zone id to string - insufficient buffer space", Logger::Error );
273 return false;
274 }
275
276 string stmt = getArg( "sql-list" );
277 string& stmtref = strbind( ":id", string( m_buffer, len ), stmt );
278
279 if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
280 }
281 catch( std::exception& e )
282 {
283 g_log.log( m_myname + " list: Caught STL exception - " + e.what(), Logger::Error );
284 return false;
285 }
286
287 return true;
288 }
289
290
291
292 void OdbxBackend::lookup( const QType& qtype, const DNSName& qname, DNSPacket* dnspkt, int zoneid )
293 {
294 try
295 {
296 DLOG( g_log.log( m_myname + " lookup()", Logger::Debug ) );
297
298 string stmt;
299 string& stmtref = stmt;
300
301 m_result = NULL;
302 m_qname = qname;
303
304 if( zoneid < 0 )
305 {
306 if( qtype.getCode() == QType::ANY )
307 {
308 stmt = getArg( "sql-lookup" );
309 } else {
310 stmt = getArg( "sql-lookuptype" );
311 stmtref = strbind( ":type", qtype.getName(), stmt );
312 }
313 }
314 else
315 {
316 if( qtype.getCode() == QType::ANY )
317 {
318 stmt = getArg( "sql-lookupid" );
319 } else {
320 stmt = getArg( "sql-lookuptypeid" );
321 stmtref = strbind( ":type", qtype.getName(), stmt );
322 }
323
324 int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
325
326 if( len < 0 )
327 {
328 g_log.log( m_myname + " lookup: Unable to convert zone id to string - format error", Logger::Error );
329 throw( DBException( "Error: Libc error" ) );
330 }
331
332 if( len > static_cast<int>(sizeof( m_buffer )) - 1 )
333 {
334 g_log.log( m_myname + " lookup: Unable to convert zone id to string - insufficient buffer space", Logger::Error );
335 throw( DBException( "Error: Libc error" ) );
336 }
337
338 stmtref = strbind( ":id", string( m_buffer, len ), stmtref );
339 }
340
341 stmtref = strbind( ":name", escape( qname.makeLowerCase().toStringRootDot(), READ ), stmtref );
342
343 if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) )
344 {
345 throw( DBException( "Error: DB statement failed" ) );
346 }
347 }
348 catch( std::exception& e )
349 {
350 g_log.log( m_myname + " lookup: Caught STL exception - " + e.what(), Logger::Error );
351 throw( DBException( "Error: STL exception" ) );
352 }
353 }
354
355
356
357 bool OdbxBackend::get( DNSResourceRecord& rr )
358 {
359 const char* tmp;
360 string priority;
361
362 try
363 {
364 DLOG( g_log.log( m_myname + " get()", Logger::Debug ) );
365
366 if( getRecord( READ ) )
367 {
368
369 rr.content = "";
370 rr.domain_id = 0;
371 rr.last_modified = 0;
372 rr.ttl = m_default_ttl;
373 rr.qname = m_qname;
374
375 if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL )
376 {
377 rr.domain_id = strtol( tmp, NULL, 10 );
378 }
379
380 if( m_qname.empty() && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
381 {
382 rr.qname = DNSName( string(tmp, odbx_field_length( m_result, 1 ) ));
383 }
384
385 if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
386 {
387 rr.qtype = tmp;
388 }
389
390 if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
391 {
392 rr.ttl = strtoul( tmp, NULL, 10 );
393 }
394
395 if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL )
396 {
397 priority = string( tmp, odbx_field_length( m_result, 4 ) );
398 }
399
400 if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
401 {
402 rr.content = string( tmp, odbx_field_length( m_result, 5 ) );
403 }
404
405 if (rr.qtype==QType::MX || rr.qtype==QType::SRV)
406 rr.content = priority + " " + rr.content;
407
408 return true;
409 }
410 }
411 catch( std::exception& e )
412 {
413 g_log.log( m_myname + " get: Caught STL exception - " + e.what(), Logger::Error );
414 return false;
415 }
416
417 return false;
418 }
419
420
421 void OdbxBackend::setFresh( uint32_t domain_id )
422 {
423 int len;
424
425
426 try
427 {
428 DLOG( g_log.log( m_myname + " setFresh()", Logger::Debug ) );
429
430 if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
431 {
432 g_log.log( m_myname + " setFresh: Master server is unreachable", Logger::Error );
433 throw( DBException( "Error: Server unreachable" ) );
434 }
435
436 len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-lastcheck" ).c_str(), time( 0 ), domain_id );
437
438 if( len < 0 )
439 {
440 g_log.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - format error", Logger::Error );
441 throw( DBException( "Error: Libc error" ) );
442 }
443
444 if( len > static_cast<int>(sizeof( m_buffer )) - 1 )
445 {
446 g_log.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - insufficient buffer space", Logger::Error );
447 throw( DBException( "Error: Libc error" ) );
448 }
449
450 if( !execStmt( m_buffer, len, WRITE ) )
451 {
452 throw( DBException( "Error: DB statement failed" ) );
453 }
454 }
455 catch ( std::exception& e )
456 {
457 g_log.log( m_myname + " setFresh: Caught STL exception - " + e.what(), Logger::Error );
458 throw( DBException( "Error: STL exception" ) );
459 }
460 }
461
462
463
464 void OdbxBackend::setNotified( uint32_t domain_id, uint32_t serial )
465 {
466 try
467 {
468 DLOG( g_log.log( m_myname + " setNotified()", Logger::Debug ) );
469
470 if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
471 {
472 g_log.log( m_myname + " setFresh: Master server is unreachable", Logger::Error );
473 throw( DBException( "Error: Server unreachable" ) );
474 }
475
476 int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-serial" ).c_str(), serial, domain_id );
477
478 if( len < 0 )
479 {
480 g_log.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - format error", Logger::Error );
481 throw( DBException( "Error: Libc error" ) );
482 }
483
484 if( len > static_cast<int>(sizeof( m_buffer )) - 1 )
485 {
486 g_log.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - insufficient buffer space", Logger::Error );
487 throw( DBException( "Error: Libc error" ) );
488 }
489
490 if( !execStmt( m_buffer, len, WRITE ) )
491 {
492 throw( DBException( "Error: DB statement failed" ) );
493 }
494 }
495 catch ( std::exception& e )
496 {
497 g_log.log( m_myname + " setNotified: Caught STL exception - " + e.what(), Logger::Error );
498 throw( DBException( "Error: STL exception" ) );
499 }
500 }
501
502
503
504 void OdbxBackend::getUnfreshSlaveInfos( vector<DomainInfo>* unfresh )
505 {
506 try
507 {
508 DLOG( g_log.log( m_myname + " getUnfreshSlaveInfos()", Logger::Debug ) );
509
510 if( unfresh == NULL )
511 {
512 g_log.log( m_myname + " getUnfreshSlaveInfos: invalid parameter - NULL pointer", Logger::Error );
513 return;
514 }
515
516 getDomainList( getArg( "sql-infoslaves" ), unfresh, &checkSlave );
517 }
518 catch ( std::exception& e )
519 {
520 g_log.log( m_myname + " getUnfreshSlaveInfo: Caught STL exception - " + e.what(), Logger::Error );
521 }
522 }
523
524
525
526 void OdbxBackend::getUpdatedMasters( vector<DomainInfo>* updated )
527 {
528 try
529 {
530 DLOG( g_log.log( m_myname + " getUpdatedMasters()", Logger::Debug ) );
531
532 if( updated == NULL )
533 {
534 g_log.log( m_myname + " getUpdatedMasters: invalid parameter - NULL pointer", Logger::Error );
535 return;
536 }
537
538 getDomainList( getArg( "sql-infomasters" ), updated, &checkMaster );
539 }
540 catch ( std::exception& e )
541 {
542 g_log.log( m_myname + " getUpdatedMasters: Caught STL exception - " + e.what(), Logger::Error );
543 }
544 }
545
546
547
548 bool OdbxBackend::superMasterBackend( const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& set, string *nameserver, string* account, DNSBackend** ddb )
549 {
550 try
551 {
552 DLOG( g_log.log( m_myname + " superMasterBackend()", Logger::Debug ) );
553
554 if( account != NULL && ddb != NULL )
555 {
556 vector<DNSResourceRecord>::const_iterator i;
557
558 for( i = set.begin(); i != set.end(); i++ )
559 {
560 string stmt = getArg( "sql-supermaster" );
561 string& stmtref = strbind( ":ip", escape( ip, READ ), stmt );
562 stmtref = strbind( ":ns", escape( i->content, READ ), stmtref );
563
564 if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
565
566 if( getRecord( READ ) )
567 {
568 if( odbx_field_value( m_result, 0 ) != NULL )
569 {
570 *account = string( odbx_field_value( m_result, 0 ), odbx_field_length( m_result, 0 ) );
571 }
572
573 while( getRecord( READ ) );
574
575 *ddb=this;
576 return true;
577 }
578 }
579 }
580 }
581 catch ( std::exception& e )
582 {
583 g_log.log( m_myname + " superMasterBackend: Caught STL exception - " + e.what(), Logger::Error );
584 return false;
585 }
586
587 return false;
588 }
589
590
591
592 bool OdbxBackend::createSlaveDomain( const string& ip, const DNSName& domain, const string &nameserver, const string& account )
593 {
594 try
595 {
596 DLOG( g_log.log( m_myname + " createSlaveDomain()", Logger::Debug ) );
597
598 if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
599 {
600 g_log.log( m_myname + " createSlaveDomain: Master server is unreachable", Logger::Error );
601 return false;
602 }
603
604 int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-slave" ).c_str(), escape( domain.makeLowerCase().toStringRootDot(), WRITE ).c_str(),
605 escape( ip, WRITE ).c_str(), escape( account, WRITE ).c_str() );
606
607 if( len < 0 )
608 {
609 g_log.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - format error", Logger::Error );
610 return false;
611 }
612
613 if( len > static_cast<int>(sizeof( m_buffer )) - 1 )
614 {
615 g_log.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - insufficient buffer space", Logger::Error );
616 return false;
617 }
618
619 if( !execStmt( m_buffer, len, WRITE ) ) { return false; }
620 }
621 catch ( std::exception& e )
622 {
623 g_log.log( m_myname + " createSlaveDomain: Caught STL exception - " + e.what(), Logger::Error );
624 return false;
625 }
626
627 return true;
628 }
629
630
631
632 bool OdbxBackend::feedRecord( const DNSResourceRecord& rr, const DNSName& ordername )
633 {
634 try
635 {
636 DLOG( g_log.log( m_myname + " feedRecord()", Logger::Debug ) );
637
638 if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
639 {
640 g_log.log( m_myname + " feedRecord: Master server is unreachable", Logger::Error );
641 return false;
642 }
643
644 unsigned int priority=0;
645 string content(rr.content);
646
647 if(rr.qtype == QType::MX || rr.qtype == QType::SRV) {
648 priority=pdns_stou(content);
649 string::size_type pos = content.find_first_not_of("0123456789");
650 if(pos != string::npos)
651 boost::erase_head(content, pos);
652 trim_left(content);
653 }
654
655 int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-record" ).c_str(), rr.domain_id,
656 escape( rr.qname.makeLowerCase().toStringRootDot(), WRITE ).c_str(), rr.qtype.getName().c_str(), rr.ttl, priority,
657 escape( content, WRITE ).c_str() );
658
659 if( len < 0 )
660 {
661 g_log.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - format error", Logger::Error );
662 return false;
663 }
664
665 if( len > static_cast<int>(sizeof( m_buffer )) - 1 )
666 {
667 g_log.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - insufficient buffer space", Logger::Error );
668 return false;
669 }
670
671 if( !execStmt( m_buffer, len, WRITE ) ) { return false; }
672 }
673 catch ( std::exception& e )
674 {
675 g_log.log( m_myname + " feedRecord: Caught STL exception - " + e.what(), Logger::Error );
676 return false;
677 }
678
679 return true;
680 }
681
682
683
684 bool OdbxBackend::startTransaction( const DNSName& domain, int zoneid )
685 {
686 try
687 {
688 DLOG( g_log.log( m_myname + " startTransaction()", Logger::Debug ) );
689
690 if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
691 {
692 g_log.log( m_myname + " startTransaction: Master server is unreachable", Logger::Error );
693 return false;
694 }
695
696 string stmtref = getArg( "sql-transactbegin" );
697 if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; }
698 int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
699
700 if( len < 0 )
701 {
702 g_log.log( m_myname + " startTransaction: Unable to convert zone id to string - format error", Logger::Error );
703 return false;
704 }
705
706 if( len > static_cast<int>(sizeof( m_buffer )) - 1 )
707 {
708 g_log.log( m_myname + " startTransaction: Unable to convert zone id to string - insufficient buffer space", Logger::Error );
709 return false;
710 }
711
712 if(zoneid >= 0) {
713 string stmt = getArg( "sql-zonedelete" );
714 stmtref = strbind( ":id", string( m_buffer, len ), stmt );
715 if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; }
716 }
717 }
718 catch ( std::exception& e )
719 {
720 g_log.log( m_myname + " startTransaction: Caught STL exception - " + e.what(), Logger::Error );
721 return false;
722 }
723
724 return true;
725 }
726
727
728
729 bool OdbxBackend::commitTransaction()
730 {
731 try
732 {
733 DLOG( g_log.log( m_myname + " commitTransaction()", Logger::Debug ) );
734
735 if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
736 {
737 g_log.log( m_myname + " commitTransaction: Master server is unreachable", Logger::Error );
738 return false;
739 }
740
741 const string& stmt = getArg( "sql-transactend" );
742 if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; }
743 }
744 catch ( std::exception& e )
745 {
746 g_log.log( m_myname + " commitTransaction: Caught STL exception - " + e.what(), Logger::Error );
747 return false;
748 }
749
750 return true;
751 }
752
753
754
755 bool OdbxBackend::abortTransaction()
756 {
757 try
758 {
759 DLOG( g_log.log( m_myname + " abortTransaction()", Logger::Debug ) );
760
761 if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
762 {
763 g_log.log( m_myname + " abortTransaction: Master server is unreachable", Logger::Error );
764 return false;
765 }
766
767 const string& stmt = getArg( "sql-transactabort" );
768 if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; }
769 }
770 catch ( std::exception& e )
771 {
772 g_log.log( m_myname + " abortTransaction: Caught STL exception - " + e.what(), Logger::Error );
773 return false;
774 }
775
776 return true;
777 }