Hazelcast C++ Client
Hazelcast C++ Client Library
Loading...
Searching...
No Matches
transactions.cpp
1/*
2 * Copyright (c) 2008-2025, Hazelcast, Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <boost/uuid/uuid_io.hpp>
18
19#include <hazelcast/client/txn/client_transaction_util.h>
20#include "hazelcast/client/txn/TransactionProxy.h"
21#include "hazelcast/client/transaction_options.h"
22#include "hazelcast/util/Util.h"
23#include "hazelcast/client/spi/impl/ClientInvocation.h"
24#include "hazelcast/client/connection/ClientConnectionManagerImpl.h"
25#include "hazelcast/client/proxy/TransactionalMapImpl.h"
26#include "hazelcast/client/proxy/TransactionalMultiMapImpl.h"
27#include "hazelcast/client/proxy/TransactionalListImpl.h"
28#include "hazelcast/client/proxy/TransactionalQueueImpl.h"
29#include "hazelcast/client/proxy/TransactionalSetImpl.h"
30#include "hazelcast/client/imap.h"
31#include "hazelcast/client/multi_map.h"
32#include "hazelcast/client/ilist.h"
33#include "hazelcast/client/iqueue.h"
34#include "hazelcast/client/iset.h"
35#include "hazelcast/client/transaction_context.h"
36#include "hazelcast/client/spi/impl/ClientTransactionManagerServiceImpl.h"
37#include "hazelcast/client/protocol/codec/codecs.h"
38
39namespace hazelcast {
40namespace client {
41namespace txn {
42TransactionProxy::TransactionProxy(
43 transaction_options& txn_options,
44 spi::ClientContext& client_context,
45 std::shared_ptr<connection::Connection> connection)
46 : options_(txn_options)
47 , client_context_(client_context)
48 , connection_(connection)
49 , thread_id_(util::get_current_thread_id())
50 , state_(TxnState::NO_TXN)
51{}
52
53TransactionProxy::TransactionProxy(const TransactionProxy& rhs)
54 : options_(rhs.options_)
55 , client_context_(rhs.client_context_)
56 , connection_(rhs.connection_)
57 , thread_id_(rhs.thread_id_)
58 , txn_id_(rhs.txn_id_)
59 , state_(rhs.state_)
60 , start_time_(rhs.start_time_)
61{
62 transaction_exists_.store(rhs.transaction_exists_.load());
63}
64
65boost::uuids::uuid
66TransactionProxy::get_txn_id() const
67{
68 return txn_id_;
69}
70
71TxnState
72TransactionProxy::get_state() const
73{
74 return state_;
75}
76
77std::chrono::milliseconds
78TransactionProxy::get_timeout() const
79{
80 return options_.get_timeout();
81}
82
83boost::future<void>
84TransactionProxy::begin()
85{
86 try {
87 if (state_ == TxnState::ACTIVE) {
88 BOOST_THROW_EXCEPTION(exception::illegal_state(
89 "TransactionProxy::begin()", "Transaction is already active"));
90 }
91 check_thread();
92 if (transaction_exists_) {
93 BOOST_THROW_EXCEPTION(
94 exception::illegal_state("TransactionProxy::begin()",
95 "Nested transactions are not allowed!"));
96 }
97 transaction_exists_.store(true);
98 start_time_ = std::chrono::steady_clock::now();
99 auto request = protocol::codec::transaction_create_encode(
100 std::chrono::duration_cast<std::chrono::milliseconds>(get_timeout())
101 .count(),
102 options_.get_durability(),
103 static_cast<int32_t>(options_.get_transaction_type()),
104 thread_id_);
105 return invoke(request).then(
106 boost::launch::sync, [=](boost::future<protocol::ClientMessage> f) {
107 try {
108 auto msg = f.get();
109 // skip header
110 msg.rd_ptr(msg.RESPONSE_HEADER_LEN);
111 this->txn_id_ = msg.get<boost::uuids::uuid>();
112 this->state_ = TxnState::ACTIVE;
113 } catch (exception::iexception&) {
114 transaction_exists_.store(false);
115 throw;
116 }
117 });
118 } catch (exception::iexception&) {
119 transaction_exists_.store(false);
120 throw;
121 }
122}
123
124boost::future<void>
125TransactionProxy::commit()
126{
127 try {
128 if (state_ != TxnState::ACTIVE) {
129 BOOST_THROW_EXCEPTION(exception::illegal_state(
130 "TransactionProxy::commit()", "Transaction is not active"));
131 }
132 state_ = TxnState::COMMITTING;
133 check_thread();
134 check_timeout();
135
136 auto request =
137 protocol::codec::transaction_commit_encode(txn_id_, thread_id_);
138 return invoke(request).then(
139 boost::launch::sync, [=](boost::future<protocol::ClientMessage> f) {
140 try {
141 f.get();
142 state_ = TxnState::COMMITTED;
143 } catch (exception::iexception&) {
144 transaction_exists_.store(false);
145 client_transaction_util::transaction_exception_factory()
146 ->rethrow(std::current_exception(),
147 "TransactionProxy::commit() failed");
148 }
149 });
150 } catch (...) {
151 state_ = TxnState::COMMIT_FAILED;
152 transaction_exists_.store(false);
153 client_transaction_util::transaction_exception_factory()->rethrow(
154 std::current_exception(), "TransactionProxy::commit() failed");
155 return boost::make_ready_future();
156 }
157}
158
159boost::future<void>
160TransactionProxy::rollback()
161{
162 try {
163 if (state_ == TxnState::NO_TXN || state_ == TxnState::ROLLED_BACK) {
164 BOOST_THROW_EXCEPTION(exception::illegal_state(
165 "TransactionProxy::rollback()", "Transaction is not active"));
166 }
167 state_ = TxnState::ROLLING_BACK;
168 check_thread();
169 try {
170 auto request =
171 protocol::codec::transaction_rollback_encode(txn_id_, thread_id_);
172 return invoke(request).then(
173 boost::launch::sync,
174 [=](boost::future<protocol::ClientMessage> f) {
175 try {
176 state_ = TxnState::ROLLED_BACK;
177 transaction_exists_.store(false);
178 f.get();
179 } catch (exception::iexception& e) {
180 HZ_LOG(
181 client_context_.get_logger(),
182 warning,
183 boost::str(
184 boost::format(
185 "Exception while rolling back the transaction. "
186 "Exception: %1%") %
187 e));
188 }
189 });
190 } catch (exception::iexception& exception) {
191 HZ_LOG(client_context_.get_logger(),
192 warning,
193 boost::str(boost::format(
194 "Exception while rolling back the transaction. "
195 "Exception: %1%") %
196 exception));
197 }
198 state_ = TxnState::ROLLED_BACK;
199 transaction_exists_.store(false);
200 } catch (exception::iexception&) {
201 transaction_exists_.store(false);
202 client_transaction_util::transaction_exception_factory()->rethrow(
203 std::current_exception(), "TransactionProxy::rollback() failed");
204 }
205 return boost::make_ready_future();
206}
207
208serialization::pimpl::SerializationService&
209TransactionProxy::get_serialization_service()
210{
211 return client_context_.get_serialization_service();
212}
213
214std::shared_ptr<connection::Connection>
215TransactionProxy::get_connection()
216{
217 return connection_;
218}
219
220void
221TransactionProxy::check_thread()
222{
223 if (thread_id_ != util::get_current_thread_id()) {
224 BOOST_THROW_EXCEPTION(exception::illegal_state(
225 "TransactionProxy::checkThread()",
226 "Transaction cannot span multiple threads!"));
227 }
228}
229
230void
231TransactionProxy::check_timeout()
232{
233 if (start_time_ + options_.get_timeout() <
234 std::chrono::steady_clock::now()) {
235 BOOST_THROW_EXCEPTION(exception::transaction(
236 "TransactionProxy::checkTimeout()", "Transaction is timed-out!"));
237 }
238}
239
240TxnState::TxnState(state value)
241 : value(value)
242{
243 values.resize(9);
244 values[0] = NO_TXN;
245 values[1] = ACTIVE;
246 values[2] = PREPARING;
247 values[3] = PREPARED;
248 values[4] = COMMITTING;
249 values[5] = COMMITTED;
250 values[6] = COMMIT_FAILED;
251 values[7] = ROLLING_BACK;
252 values[8] = ROLLED_BACK;
253}
254
255TxnState::operator int() const
256{
257 return value;
258}
259
260void
261TxnState::operator=(int i)
262{
263 value = values[i];
264}
265
266boost::future<protocol::ClientMessage>
267TransactionProxy::invoke(protocol::ClientMessage& request)
268{
269 return client_transaction_util::invoke(
270 request,
271 boost::uuids::to_string(get_txn_id()),
272 client_context_,
273 connection_);
274}
275
276spi::ClientContext&
277TransactionProxy::get_client_context() const
278{
279 return client_context_;
280}
281
282const std::shared_ptr<util::exception_util::runtime_exception_factory>
283 client_transaction_util::exceptionFactory(
284 new class transaction_exception_factory());
285
286boost::future<protocol::ClientMessage>
287client_transaction_util::invoke(
288 protocol::ClientMessage& request,
289 const std::string& object_name,
290 spi::ClientContext& client,
291 const std::shared_ptr<connection::Connection>& connection)
292{
293 try {
294 std::shared_ptr<spi::impl::ClientInvocation> clientInvocation =
295 spi::impl::ClientInvocation::create(
296 client, request, object_name, connection);
297 return clientInvocation->invoke();
298 } catch (exception::iexception&) {
299 transaction_exception_factory()->rethrow(
300 std::current_exception(), "ClientTransactionUtil::invoke failed");
301 return boost::make_ready_future(protocol::ClientMessage(0));
302 }
303}
304
305const std::shared_ptr<util::exception_util::runtime_exception_factory>&
306client_transaction_util::transaction_exception_factory()
307{
308 return exceptionFactory;
309}
310
311void
312client_transaction_util::transaction_exception_factory::rethrow(
313 std::exception_ptr throwable,
314 const std::string& message)
315{
316 try {
317 std::rethrow_exception(throwable);
318 } catch (...) {
319 std::throw_with_nested(
320 boost::enable_current_exception(exception::transaction(
321 "transaction_exceptionFactory::create", message)));
322 }
323}
324} // namespace txn
325
326namespace proxy {
327TransactionalMapImpl::TransactionalMapImpl(
328 const std::string& name,
329 txn::TransactionProxy& transaction_proxy)
330 : TransactionalObject(imap::SERVICE_NAME, name, transaction_proxy)
331{}
332
333boost::future<bool>
334TransactionalMapImpl::contains_key_data(const serialization::pimpl::data& key)
335{
336 auto request = protocol::codec::transactionalmap_containskey_encode(
337 get_name(), get_transaction_id(), util::get_current_thread_id(), key);
338
339 return invoke_and_get_future<bool>(request);
340}
341
342boost::future<boost::optional<serialization::pimpl::data>>
343TransactionalMapImpl::get_data(const serialization::pimpl::data& key)
344{
345 auto request = protocol::codec::transactionalmap_get_encode(
346 get_name(), get_transaction_id(), util::get_current_thread_id(), key);
347
348 return invoke_and_get_future<boost::optional<serialization::pimpl::data>>(
349 request);
350}
351
352boost::future<int>
353TransactionalMapImpl::size()
354{
355 auto request = protocol::codec::transactionalmap_size_encode(
356 get_name(), get_transaction_id(), util::get_current_thread_id());
357
358 return invoke_and_get_future<int>(request);
359}
360
361boost::future<bool>
362TransactionalMapImpl::is_empty()
363{
364 auto request = protocol::codec::transactionalmap_isempty_encode(
365 get_name(), get_transaction_id(), util::get_current_thread_id());
366
367 return invoke_and_get_future<bool>(request);
368}
369
370boost::future<boost::optional<serialization::pimpl::data>>
371TransactionalMapImpl::put_data(const serialization::pimpl::data& key,
372 const serialization::pimpl::data& value)
373{
374
375 auto request = protocol::codec::transactionalmap_put_encode(
376 get_name(),
377 get_transaction_id(),
378 util::get_current_thread_id(),
379 key,
380 value,
381 std::chrono::duration_cast<std::chrono::milliseconds>(get_timeout())
382 .count());
383
384 return invoke_and_get_future<boost::optional<serialization::pimpl::data>>(
385 request);
386}
387
388boost::future<void>
389TransactionalMapImpl::set_data(const serialization::pimpl::data& key,
390 const serialization::pimpl::data& value)
391{
392 auto request = protocol::codec::transactionalmap_set_encode(
393 get_name(),
394 get_transaction_id(),
395 util::get_current_thread_id(),
396 key,
397 value);
398
399 return to_void_future(invoke(request));
400}
401
402boost::future<boost::optional<serialization::pimpl::data>>
403TransactionalMapImpl::put_if_absent_data(
404 const serialization::pimpl::data& key,
405 const serialization::pimpl::data& value)
406{
407 auto request = protocol::codec::transactionalmap_putifabsent_encode(
408 get_name(),
409 get_transaction_id(),
410 util::get_current_thread_id(),
411 key,
412 value);
413
414 return invoke_and_get_future<boost::optional<serialization::pimpl::data>>(
415 request);
416}
417
418boost::future<boost::optional<serialization::pimpl::data>>
419TransactionalMapImpl::replace_data(const serialization::pimpl::data& key,
420 const serialization::pimpl::data& value)
421{
422 auto request = protocol::codec::transactionalmap_replace_encode(
423 get_name(),
424 get_transaction_id(),
425 util::get_current_thread_id(),
426 key,
427 value);
428
429 return invoke_and_get_future<boost::optional<serialization::pimpl::data>>(
430 request);
431}
432
433boost::future<bool>
434TransactionalMapImpl::replace_data(const serialization::pimpl::data& key,
435 const serialization::pimpl::data& old_value,
436 const serialization::pimpl::data& new_value)
437{
438 auto request = protocol::codec::transactionalmap_replaceifsame_encode(
439 get_name(),
440 get_transaction_id(),
441 util::get_current_thread_id(),
442 key,
443 old_value,
444 new_value);
445
446 return invoke_and_get_future<bool>(request);
447}
448
449boost::future<boost::optional<serialization::pimpl::data>>
450TransactionalMapImpl::remove_data(const serialization::pimpl::data& key)
451{
452 auto request = protocol::codec::transactionalmap_remove_encode(
453 get_name(), get_transaction_id(), util::get_current_thread_id(), key);
454
455 return invoke_and_get_future<boost::optional<serialization::pimpl::data>>(
456 request);
457}
458
459boost::future<void>
460TransactionalMapImpl::delete_entry_data(const serialization::pimpl::data& key)
461{
462 auto request = protocol::codec::transactionalmap_delete_encode(
463 get_name(), get_transaction_id(), util::get_current_thread_id(), key);
464
465 return to_void_future(invoke(request));
466}
467
468boost::future<bool>
469TransactionalMapImpl::remove_data(const serialization::pimpl::data& key,
470 const serialization::pimpl::data& value)
471{
472 auto request = protocol::codec::transactionalmap_removeifsame_encode(
473 get_name(),
474 get_transaction_id(),
475 util::get_current_thread_id(),
476 key,
477 value);
478
479 return invoke_and_get_future<bool>(request);
480}
481
482boost::future<std::vector<serialization::pimpl::data>>
483TransactionalMapImpl::key_set_data()
484{
485 auto request = protocol::codec::transactionalmap_keyset_encode(
486 get_name(), get_transaction_id(), util::get_current_thread_id());
487
488 return invoke_and_get_future<std::vector<serialization::pimpl::data>>(
489 request);
490}
491
492boost::future<std::vector<serialization::pimpl::data>>
493TransactionalMapImpl::key_set_data(const serialization::pimpl::data& predicate)
494{
495 auto request = protocol::codec::transactionalmap_keysetwithpredicate_encode(
496 get_name(),
497 get_transaction_id(),
498 util::get_current_thread_id(),
499 predicate);
500
501 return invoke_and_get_future<std::vector<serialization::pimpl::data>>(
502 request);
503}
504
505boost::future<std::vector<serialization::pimpl::data>>
506TransactionalMapImpl::values_data()
507{
508 auto request = protocol::codec::transactionalmap_values_encode(
509 get_name(), get_transaction_id(), util::get_current_thread_id());
510
511 return invoke_and_get_future<std::vector<serialization::pimpl::data>>(
512 request);
513}
514
515boost::future<std::vector<serialization::pimpl::data>>
516TransactionalMapImpl::values_data(const serialization::pimpl::data& predicate)
517{
518 auto request = protocol::codec::transactionalmap_valueswithpredicate_encode(
519 get_name(),
520 get_transaction_id(),
521 util::get_current_thread_id(),
522 predicate);
523
524 return invoke_and_get_future<std::vector<serialization::pimpl::data>>(
525 request);
526}
527
528TransactionalMultiMapImpl::TransactionalMultiMapImpl(
529 const std::string& name,
530 txn::TransactionProxy& transaction_proxy)
531 : TransactionalObject(multi_map::SERVICE_NAME, name, transaction_proxy)
532{}
533
534boost::future<bool>
535TransactionalMultiMapImpl::put_data(const serialization::pimpl::data& key,
536 const serialization::pimpl::data& value)
537{
538 auto request = protocol::codec::transactionalmultimap_put_encode(
539 get_name(),
540 get_transaction_id(),
541 util::get_current_thread_id(),
542 key,
543 value);
544
545 return invoke_and_get_future<bool>(request);
546}
547
548boost::future<std::vector<serialization::pimpl::data>>
549TransactionalMultiMapImpl::get_data(const serialization::pimpl::data& key)
550{
551 auto request = protocol::codec::transactionalmultimap_get_encode(
552 get_name(), get_transaction_id(), util::get_current_thread_id(), key);
553
554 return invoke_and_get_future<std::vector<serialization::pimpl::data>>(
555 request);
556}
557
558boost::future<bool>
559TransactionalMultiMapImpl::remove(const serialization::pimpl::data& key,
560 const serialization::pimpl::data& value)
561{
562 auto request = protocol::codec::transactionalmultimap_removeentry_encode(
563 get_name(),
564 get_transaction_id(),
565 util::get_current_thread_id(),
566 key,
567 value);
568
569 return invoke_and_get_future<bool>(request);
570}
571
572boost::future<std::vector<serialization::pimpl::data>>
573TransactionalMultiMapImpl::remove_data(const serialization::pimpl::data& key)
574{
575 auto request = protocol::codec::transactionalmultimap_remove_encode(
576 get_name(), get_transaction_id(), util::get_current_thread_id(), key);
577
578 return invoke_and_get_future<std::vector<serialization::pimpl::data>>(
579 request);
580}
581
582boost::future<int>
583TransactionalMultiMapImpl::value_count(const serialization::pimpl::data& key)
584{
585 auto request = protocol::codec::transactionalmultimap_valuecount_encode(
586 get_name(), get_transaction_id(), util::get_current_thread_id(), key);
587
588 return invoke_and_get_future<int>(request);
589}
590
591boost::future<int>
592TransactionalMultiMapImpl::size()
593{
594 auto request = protocol::codec::transactionalmultimap_size_encode(
595 get_name(), get_transaction_id(), util::get_current_thread_id());
596
597 return invoke_and_get_future<int>(request);
598}
599
600TransactionalListImpl::TransactionalListImpl(const std::string& object_name,
601 txn::TransactionProxy& context)
602 : TransactionalObject(ilist::SERVICE_NAME, object_name, context)
603{}
604
605boost::future<bool>
606TransactionalListImpl::add(const serialization::pimpl::data& e)
607{
608 auto request = protocol::codec::transactionallist_add_encode(
609 get_name(), get_transaction_id(), util::get_current_thread_id(), e);
610
611 return invoke_and_get_future<bool>(request);
612}
613
614boost::future<bool>
615TransactionalListImpl::remove(const serialization::pimpl::data& e)
616{
617 auto request = protocol::codec::transactionallist_remove_encode(
618 get_name(), get_transaction_id(), util::get_current_thread_id(), e);
619
620 return invoke_and_get_future<bool>(request);
621}
622
623boost::future<int>
624TransactionalListImpl::size()
625{
626 auto request = protocol::codec::transactionallist_size_encode(
627 get_name(), get_transaction_id(), util::get_current_thread_id());
628
629 return invoke_and_get_future<int>(request);
630}
631
632TransactionalSetImpl::TransactionalSetImpl(
633 const std::string& name,
634 txn::TransactionProxy& transaction_proxy)
635 : TransactionalObject(iset::SERVICE_NAME, name, transaction_proxy)
636{}
637
638boost::future<bool>
639TransactionalSetImpl::add_data(const serialization::pimpl::data& e)
640{
641 auto request = protocol::codec::transactionalset_add_encode(
642 get_name(), get_transaction_id(), util::get_current_thread_id(), e);
643
644 return invoke_and_get_future<bool>(request);
645}
646
647boost::future<bool>
648TransactionalSetImpl::remove_data(const serialization::pimpl::data& e)
649{
650 auto request = protocol::codec::transactionalset_remove_encode(
651 get_name(), get_transaction_id(), util::get_current_thread_id(), e);
652
653 return invoke_and_get_future<bool>(request);
654}
655
656boost::future<int>
657TransactionalSetImpl::size()
658{
659 auto request = protocol::codec::transactionalset_size_encode(
660 get_name(), get_transaction_id(), util::get_current_thread_id());
661
662 return invoke_and_get_future<int>(request);
663}
664
665TransactionalObject::TransactionalObject(const std::string& service_name,
666 const std::string& object_name,
667 txn::TransactionProxy& context)
668 : proxy::SerializingProxy(context.get_client_context(), object_name)
669 , service_name_(service_name)
670 , name_(object_name)
671 , context_(context)
672{}
673
674TransactionalObject::~TransactionalObject() = default;
675
676const std::string&
677TransactionalObject::get_service_name()
678{
679 return service_name_;
680}
681
682const std::string&
683TransactionalObject::get_name()
684{
685 return name_;
686}
687
688boost::future<void>
689TransactionalObject::destroy()
690{
691 on_destroy();
692 auto request =
693 protocol::codec::client_destroyproxy_encode(name_, service_name_);
694 return to_void_future(
695 invoke_on_connection(request, context_.get_connection()));
696}
697
698void
699TransactionalObject::on_destroy()
700{}
701
702boost::uuids::uuid
703TransactionalObject::get_transaction_id() const
704{
705 return context_.get_txn_id();
706}
707
708std::chrono::milliseconds
709TransactionalObject::get_timeout() const
710{
711 return context_.get_timeout();
712}
713} // namespace proxy
714
716 spi::impl::ClientTransactionManagerServiceImpl& transaction_manager,
717 const transaction_options& txn_options)
718 : options_(txn_options)
719 , txn_connection_(transaction_manager.connect())
720 , transaction_(options_, transaction_manager.get_client(), txn_connection_)
721{}
722
723boost::uuids::uuid
725{
726 return transaction_.get_txn_id();
727}
728
729boost::future<void>
731{
732 return transaction_.begin();
733}
734
735boost::future<void>
737{
738 return transaction_.commit();
739}
740
741boost::future<void>
743{
744 return transaction_.rollback();
745}
746
748 : timeout_(std::chrono::minutes(2))
749 , durability_(1)
750 , transaction_type_(transaction_type::TWO_PHASE)
751{}
752
755{
756 return transaction_type_;
757}
758
761{
762 transaction_type_ = type;
763 return *this;
764}
765
766std::chrono::milliseconds
768{
769 return timeout_;
770}
771
773transaction_options::set_timeout(std::chrono::milliseconds duration)
774{
775 if (duration.count() <= 0) {
776 BOOST_THROW_EXCEPTION(exception::illegal_state(
777 "TransactionOptions::setTimeout", "Timeout must be positive!"));
778 }
779 timeout_ = duration;
780 return *this;
781}
782
783int
785{
786 return durability_;
787}
788
791{
792 if (num_machines < 0) {
793 BOOST_THROW_EXCEPTION(
794 exception::illegal_state("TransactionOptions::setDurability",
795 "Durability cannot be negative!"));
796 }
797 this->durability_ = num_machines;
798 return *this;
799}
800} // namespace client
801} // namespace hazelcast
802
803namespace std {
804std::size_t
805hash<std::pair<std::string, std::string>>::operator()(
806 const std::pair<std::string, std::string>& val) const noexcept
807{
808 return std::hash<std::string>{}(val.first + val.second);
809}
810} // namespace std
boost::future< void > begin_transaction()
Begins a transaction.
boost::future< void > commit_transaction()
Commits a transaction.
boost::future< void > rollback_transaction()
Begins a transaction.
boost::uuids::uuid get_txn_id() const
transaction_context(spi::impl::ClientTransactionManagerServiceImpl &transaction_manager, const transaction_options &)
Constructor to be used internally.
Contains the configuration for a Hazelcast transaction.
transaction_options & set_timeout(std::chrono::milliseconds duration)
The timeout determines the maximum lifespan of a transaction.
transaction_options & set_transaction_type(transaction_type transaction_type)
Sets the TransactionType.
transaction_type get_transaction_type() const
std::chrono::milliseconds get_timeout() const
transaction_options & set_durability(int num_machines)
Sets the transaction durability.
transaction_options()
Creates a new default configured TransactionsOptions.
STL namespace.