libpqxx: transactor.hxx Source File

libpqxx 4.0.1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes

transactor.hxx
1 /*-------------------------------------------------------------------------
2 *
3 * FILE
4 * pqxx/transactor.hxx
5 *
6 * DESCRIPTION
7 * definition of the pqxx::transactor class.
8 * pqxx::transactor is a framework-style wrapper for safe transactions
9 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead.
10 *
11 * Copyright (c) 2001-2008, Jeroen T. Vermeulen <jtv@xs4all.nl>
12 *
13 * See COPYING for copyright license. If you did not receive a file called
14 * COPYING with this source code, please notify the distributor of this mistake,
15 * or contact the author.
16 *
17 *-------------------------------------------------------------------------
18 */
19 #ifndef PQXX_H_TRANSACTOR
20 #define PQXX_H_TRANSACTOR
21
22 #include "pqxx/compiler-public.hxx"
23 #include "pqxx/compiler-internal-pre.hxx"
24
25 #include "pqxx/connection_base"
26 #include "pqxx/transaction"
27
28
29 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
30 */
31
32 namespace pqxx
33 {
34
36
65 template<typename TRANSACTION=transaction<read_committed> >
66 class transactor :
67 public PGSTD::unary_function<TRANSACTION, void>
68 {
69 public:
70 explicit transactor(const PGSTD::string &TName="transactor") : //[t4]
71 m_Name(TName) { }
72
74
85 void operator()(TRANSACTION &T); //[t4]
86
87 // Overridable member functions, called by connection_base::perform() if an
88 // attempt to run transaction fails/succeeds, respectively, or if the
89 // connection is lost at just the wrong moment, goes into an indeterminate
90 // state. Use these to patch up runtime state to match events, if needed, or
91 // to report failure conditions.
92
94
102 void on_abort(const char[]) throw () {} //[t13]
103
105
109 void on_commit() {} //[t7]
110
112
123 void on_doubt() throw () {} //[t13]
124
125 // TODO: Rename Name()--is there a compatible way?
127 PGSTD::string Name() const { return m_Name; } //[t13]
128
129 private:
130 PGSTD::string m_Name;
131 };
132
133
134 }
135
136
137 template<typename TRANSACTOR>
138 inline void pqxx::connection_base::perform(const TRANSACTOR &T,
139 int Attempts)
140 {
141 if (Attempts <= 0) return;
142
143 bool Done = false;
144
145 // Make attempts to perform T
146 // TODO: Differentiate between db-related exceptions and other exceptions?
147 do
148 {
149 --Attempts;
150
151 // Work on a copy of T2 so we can restore the starting situation if need be
152 TRANSACTOR T2(T);
153 try
154 {
155 typename TRANSACTOR::argument_type X(*this, T2.Name());
156 T2(X);
157 X.commit();
158 Done = true;
159 }
160 catch (const in_doubt_error &)
161 {
162 // Not sure whether transaction went through or not. The last thing in
163 // the world that we should do now is retry.
164 T2.on_doubt();
165 throw;
166 }
167 catch (const PGSTD::exception &e)
168 {
169 // Could be any kind of error.
170 T2.on_abort(e.what());
171 if (Attempts <= 0) throw;
172 continue;
173 }
174 catch (...)
175 {
176 // Don't try to forge ahead if we don't even know what happened
177 T2.on_abort("Unknown exception");
178 throw;
179 }
180
181 T2.on_commit();
182 } while (!Done);
183 }
184
185
186 #include "pqxx/compiler-internal-post.hxx"
187
188 #endif
189