transactd 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/BUILD_UNIX-JA +6 -6
  3. data/README +20 -18
  4. data/README-JA +19 -17
  5. data/RELEASE_NOTE +144 -0
  6. data/RELEASE_NOTE-JA +153 -0
  7. data/bin/common/tdclc_32_2_3.dll +0 -0
  8. data/bin/common/tdclc_64_2_3.dll +0 -0
  9. data/build/common/get_ruby_path.cmake +1 -1
  10. data/build/swig/ruby/ruby.swg +10 -9
  11. data/build/swig/ruby/tdclrb_wrap.cpp +1416 -561
  12. data/build/swig/tdcl.i +30 -3
  13. data/build/tdclc/tdclc.cbproj +1 -1
  14. data/build/tdclc/tdclc.rc +4 -4
  15. data/build/tdclcpp/BUILDNUMBER.txt +1 -0
  16. data/build/tdclcpp/tdclcpp.rc +4 -4
  17. data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
  18. data/build/tdclrb/BUILDNUMBER.txt +1 -0
  19. data/build/tdclrb/tdclrb.rc +4 -4
  20. data/source/bzs/db/engine/mysql/database.cpp +85 -41
  21. data/source/bzs/db/engine/mysql/database.h +35 -5
  22. data/source/bzs/db/engine/mysql/mysqlInternal.h +189 -37
  23. data/source/bzs/db/engine/mysql/mysqlThd.cpp +21 -21
  24. data/source/bzs/db/protocol/tdap/client/activeTable.cpp +11 -0
  25. data/source/bzs/db/protocol/tdap/client/activeTable.h +1 -1
  26. data/source/bzs/db/protocol/tdap/client/activeTableImple.h +11 -4
  27. data/source/bzs/db/protocol/tdap/client/client.h +30 -1
  28. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +2 -1
  29. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +35 -5
  30. data/source/bzs/db/protocol/tdap/client/field.cpp +100 -51
  31. data/source/bzs/db/protocol/tdap/client/field.h +7 -7
  32. data/source/bzs/db/protocol/tdap/client/filter.h +20 -6
  33. data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +337 -58
  34. data/source/bzs/db/protocol/tdap/client/groupQuery.h +56 -13
  35. data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +83 -5
  36. data/source/bzs/db/protocol/tdap/client/nsDatabase.h +4 -1
  37. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +2 -2
  38. data/source/bzs/db/protocol/tdap/client/nsTable.h +2 -1
  39. data/source/bzs/db/protocol/tdap/client/pooledDatabaseManager.h +20 -6
  40. data/source/bzs/db/protocol/tdap/client/recordset.cpp +7 -0
  41. data/source/bzs/db/protocol/tdap/client/recordsetImple.h +8 -4
  42. data/source/bzs/db/protocol/tdap/client/request.h +11 -1
  43. data/source/bzs/db/protocol/tdap/client/serializer.cpp +40 -2
  44. data/source/bzs/db/protocol/tdap/client/serializer.h +4 -2
  45. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +1 -0
  46. data/source/bzs/db/protocol/tdap/client/stringConverter.h +4 -4
  47. data/source/bzs/db/protocol/tdap/client/table.cpp +124 -71
  48. data/source/bzs/db/protocol/tdap/client/table.h +8 -7
  49. data/source/bzs/db/protocol/tdap/client/trdormapi.h +33 -1
  50. data/source/bzs/db/protocol/tdap/fieldComp.h +1 -1
  51. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +3 -1
  52. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +20 -4
  53. data/source/bzs/db/protocol/tdap/mysql/request.h +14 -0
  54. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +132 -69
  55. data/source/bzs/db/protocol/tdap/tdapRequest.h +18 -4
  56. data/source/bzs/db/protocol/tdap/tdapSchema.cpp +32 -22
  57. data/source/bzs/db/protocol/tdap/tdapSchema.h +69 -4
  58. data/source/bzs/db/protocol/tdap/tdapcapi.h +13 -5
  59. data/source/bzs/db/protocol/tdap/uri.h +4 -4
  60. data/source/bzs/db/transactd/transactd.cpp +6 -5
  61. data/source/bzs/env/crosscompile.cpp +17 -0
  62. data/source/bzs/env/crosscompile.h +4 -1
  63. data/source/bzs/env/mbcswchrLinux.cpp +3 -0
  64. data/source/bzs/example/deleteRecords.cpp +13 -0
  65. data/source/bzs/example/deleteRecords_c.cpp +8 -1
  66. data/source/bzs/example/insertRecords.cpp +14 -0
  67. data/source/bzs/example/insertRecords_c.cpp +8 -1
  68. data/source/bzs/example/ormap_c.cpp +8 -1
  69. data/source/bzs/example/queryData.cpp +92 -2
  70. data/source/bzs/example/queryData.h +3 -1
  71. data/source/bzs/example/readRecords.cpp +13 -0
  72. data/source/bzs/example/readRecords_c.cpp +8 -1
  73. data/source/bzs/example/updateRecords.cpp +13 -0
  74. data/source/bzs/example/updateRecords_c.cpp +8 -1
  75. data/source/bzs/example/update_with_transaction.cpp +13 -0
  76. data/source/bzs/example/update_with_transaction_c.cpp +8 -1
  77. data/source/bzs/example/useORMRecord.cpp +9 -3
  78. data/source/bzs/netsvc/client/iconnection.h +8 -0
  79. data/source/bzs/netsvc/client/tcpClient.cpp +61 -16
  80. data/source/bzs/netsvc/client/tcpClient.h +430 -214
  81. data/source/bzs/netsvc/server/serverPipe.cpp +2 -2
  82. data/source/bzs/test/tdclphp/transactd_Test.php +115 -19
  83. data/source/bzs/test/tdclphp/transactd_blob_Test.php +33 -5
  84. data/source/bzs/test/tdclphp/transactd_kanjischema_Test.php +21 -3
  85. data/source/bzs/test/tdclphp/transactd_pool_Test.php +17 -3
  86. data/source/bzs/test/tdclrb/transactd_blob_spec.rb +26 -8
  87. data/source/bzs/test/tdclrb/transactd_kanjischema_spec.rb +13 -6
  88. data/source/bzs/test/tdclrb/transactd_pool_spec.rb +14 -8
  89. data/source/bzs/test/tdclrb/transactd_spec.rb +117 -27
  90. data/source/bzs/test/transactdBench/scaling_bench.cpp +5 -5
  91. data/source/bzs/test/transactdBench/workerBase.h +2 -2
  92. data/source/bzs/test/trdclengn/test_trdclengn.cpp +898 -51
  93. data/source/global/tdclatl/Database.cpp +12 -0
  94. data/source/global/tdclatl/Database.h +4 -0
  95. data/source/global/tdclatl/FieldDef.cpp +19 -0
  96. data/source/global/tdclatl/FieldDef.h +4 -0
  97. data/source/global/tdclatl/FieldDefs.cpp +14 -16
  98. data/source/global/tdclatl/GroupQuery.cpp +21 -16
  99. data/source/global/tdclatl/GroupQuery.h +1 -1
  100. data/source/global/tdclatl/QueryBase.cpp +14 -0
  101. data/source/global/tdclatl/QueryBase.h +2 -0
  102. data/source/global/tdclatl/Record.cpp +41 -10
  103. data/source/global/tdclatl/Record.h +1 -1
  104. data/source/global/tdclatl/Recordset.cpp +117 -31
  105. data/source/global/tdclatl/Recordset.h +6 -5
  106. data/source/global/tdclatl/Table.cpp +24 -28
  107. data/source/global/tdclatl/Table.h +3 -4
  108. data/source/global/tdclatl/activeTable.cpp +149 -103
  109. data/source/global/tdclatl/activeTable.h +1 -1
  110. data/source/global/tdclatl/tdclatl.idl +38 -18
  111. data/transactd.gemspec +1 -1
  112. metadata +8 -4
  113. data/bin/common/tdclc_32_2_2.dll +0 -0
  114. data/bin/common/tdclc_64_2_2.dll +0 -0
@@ -20,15 +20,20 @@
20
20
  ================================================================= */
21
21
 
22
22
  #include <bzs/netsvc/client/iconnection.h>
23
+
23
24
  #include <boost/asio/write.hpp>
24
25
  #include <boost/asio/read.hpp>
25
26
  #include <boost/system/system_error.hpp>
27
+ #include <boost/bind.hpp>
26
28
  #include <boost/thread/mutex.hpp>
29
+ #if (BOOST_VERSION > 104900)
30
+ #include <boost/asio/deadline_timer.hpp>
31
+ #endif
27
32
  #include <stdio.h>
28
33
  #include <vector>
29
34
  #ifdef LINUX
30
35
  #include <pthread.h>
31
- #include <signal.h>
36
+ #include <signal.h>
32
37
  #endif
33
38
 
34
39
 
@@ -39,9 +44,10 @@ using namespace boost::system;
39
44
  #define WRITEBUF_SIZE 66000
40
45
 
41
46
  #define PORTNUMBUF_SIZE 10
42
- #define CLIENT_ERROR_CANT_CREATEPIPE 3106
43
- #define CLIENT_ERROR_SHAREMEM_DENIED 3104
47
+ #define CLIENT_ERROR_CANT_CREATEPIPE 3106
48
+ #define CLIENT_ERROR_SHAREMEM_DENIED 3104
44
49
  #define CLIENT_ERROR_CONNECTION_FAILURE 3106
50
+ #define ERROR_TD_NET_TOO_BIGDATA 3802
45
51
  #define MAX_DATA_SIZE 10485760 // 10MB
46
52
 
47
53
  namespace bzs
@@ -51,13 +57,52 @@ namespace netsvc
51
57
  namespace client
52
58
  {
53
59
 
60
+ #ifndef _WIN32
61
+
62
+ class signalmask
63
+ {
64
+ sigset_t m_signmask, m_sigomask;
65
+ public:
66
+ signalmask()
67
+ {
68
+ sigfillset(&m_signmask);
69
+ sigdelset(&m_signmask, SIGQUIT | SIGKILL | SIGHUP | SIGINT |SIGTERM);
70
+ pthread_sigmask(SIG_SETMASK, &m_signmask , &m_sigomask);
71
+ }
72
+
73
+ ~signalmask()
74
+ {
75
+ pthread_sigmask(SIG_SETMASK, &m_sigomask, NULL);
76
+ }
77
+ };
78
+ #endif
79
+
80
+ class exception : public std::exception
81
+ {
82
+ int m_error;
83
+ std::string m_msg;
84
+
85
+ public:
86
+ exception(int errorCode, const char* const& message)
87
+ : std::exception(), m_error(errorCode), m_msg(message)
88
+ {
89
+ }
90
+
91
+ ~exception() throw() {}
92
+
93
+ const char* what() const throw() { return m_msg.c_str(); }
94
+
95
+ int error() { return m_error; }
96
+ };
97
+
54
98
  typedef bool (*handshake)(connection* c, void* data);
55
99
  class connections
56
100
  {
57
101
  std::vector<connection*> m_conns;
102
+ std::string m_pipeName;
58
103
  boost::asio::io_service m_ios;
104
+ boost::asio::ip::tcp::resolver m_resolver;
59
105
  mutex m_mutex;
60
- std::string m_pipeName;
61
106
  static bool m_usePipedLocal;
62
107
 
63
108
  connection* getConnection(asio::ip::tcp::endpoint& ep);
@@ -75,11 +120,15 @@ public:
75
120
  ~connections();
76
121
  connection* connect(const std::string& host, handshake f,
77
122
  void* data, bool newConnection = false);
123
+ bool reconnect(connection* c, const std::string& host,
124
+ handshake f, void* data);
125
+
78
126
  connection* getConnection(const std::string& host);
79
127
  bool disconnect(connection* c);
80
128
  int connectionCount();
81
129
  static char port[PORTNUMBUF_SIZE];
82
- static short timeout;
130
+ static int connectTimeout;
131
+ static int netTimeout;
83
132
  };
84
133
 
85
134
  /** Implementation of Part of the connection interface
@@ -91,8 +140,6 @@ protected:
91
140
 
92
141
  asio::io_service m_ios;
93
142
  asio::ip::tcp::endpoint m_ep;
94
- std::vector<char> m_readbuf;
95
- std::vector<char> m_sendbuf;
96
143
  idirectReadHandler* m_reader;
97
144
  size_t m_readLen;
98
145
  int m_refCount;
@@ -113,78 +160,267 @@ protected:
113
160
  int charsetServer() const { return m_charsetServer; };
114
161
 
115
162
  void setCharsetServer(int v) { m_charsetServer = v; }
116
-
163
+
117
164
  public:
118
165
  connectionBase(asio::ip::tcp::endpoint& ep)
119
166
  : m_ep(ep), m_reader(NULL), m_refCount(0),
120
167
  m_charsetServer(-1), m_connected(false), m_isHandShakable(true)
121
168
  {
122
169
  }
123
-
124
170
  void setDirectReadHandler(idirectReadHandler* p){ m_reader = p; }
171
+ bool isHandShakable() const {return m_isHandShakable;};
172
+ };
125
173
 
126
- char* sendBuffer(size_t size)
174
+
175
+ template <class T>
176
+ class asio_tcp_io
177
+ {
178
+ T& m_socket;
179
+ public:
180
+ asio_tcp_io(T& socket):m_socket(socket){}
181
+
182
+ size_t readAll(char* buf, size_t size)
127
183
  {
128
- if (size > m_sendbuf.size())
129
- m_sendbuf.resize(size);
130
- return &m_sendbuf[0];
184
+ return asio::read(m_socket, asio::buffer(buf, size),
185
+ asio::transfer_all());
131
186
  }
132
187
 
133
- unsigned int sendBufferSize() { return (unsigned int)m_sendbuf.size(); };
188
+ size_t readSome(char* buf, size_t size, size_t minimum)
189
+ {
190
+ return asio::read(m_socket, asio::buffer(buf, size),
191
+ asio::transfer_at_least(minimum));
192
+ }
134
193
 
135
- void setReadBufferSizeIf(size_t size)
194
+ void write(const char* buf, size_t size, int /*flag*/)
136
195
  {
137
- if (m_readbuf.size() < size)
138
- m_readbuf.resize(size);
196
+ asio::write(m_socket, asio::buffer(buf, size),
197
+ asio::transfer_all());
139
198
  }
140
199
 
141
- bool isHandShakable() const {return m_isHandShakable;};
142
- };
200
+ template <typename MutableBufferSequence>
201
+ void writeMultibuffer(const MutableBufferSequence& buffer)
202
+ {
203
+ asio::write(m_socket, buffer, asio::transfer_all());
204
+ }
143
205
 
144
- /** Implementation of the connection template
145
- */
206
+ void on_connected() {}
207
+
208
+ };
209
+
210
+ #if (defined(_WIN32))
211
+ #define MSG_WAITALL 0x8
212
+ #define MSG_EOR 0
213
+ #define MSG_MORE 0
214
+ #endif
215
+
216
+ #ifdef LINUX
217
+ #define SOCKET_ERROR -1
218
+ #endif
219
+
220
+ #if (BOOST_VERSION > 104900)
221
+ #define SYSTEM_CATEGORY system_category()
222
+ #else
223
+ #define SYSTEM_CATEGORY system_category
224
+ #endif
225
+
226
+ #ifndef __APPLE__
227
+ template <class T>
228
+ class native_tcp_io
229
+ {
230
+ T& m_socket;
231
+ int getErrorCode()
232
+ {
233
+ #ifndef _WIN32
234
+ return errno;
235
+ #else
236
+ return WSAGetLastError();
237
+ #endif
238
+ }
239
+
240
+ public:
241
+ native_tcp_io(T& socket):m_socket(socket){}
242
+
243
+ #ifdef _WIN32
244
+ size_t readAll2(char* buf, size_t size)
245
+ {
246
+ int n = 0;
247
+ do
248
+ {
249
+ int nn = recv(m_socket.native(), buf + n, (int)size - n, 0);
250
+ if (n == SOCKET_ERROR)
251
+ throw system_error(error_code(getErrorCode(), SYSTEM_CATEGORY));
252
+ n += nn;
253
+ }while (n != size);
254
+ return (size_t)n;
255
+ }
256
+ #endif
257
+
258
+ size_t readAll(char* buf, size_t size)
259
+ {
260
+ errno = 0;
261
+ int n = recv(m_socket.native(), buf, (int)size, MSG_WAITALL);
262
+ if (n == SOCKET_ERROR)
263
+ {
264
+ #ifdef _WIN32
265
+ if (WSAEOPNOTSUPP == getErrorCode())
266
+ return readAll2(buf, size);
267
+ else
268
+ #endif
269
+ throw system_error(error_code(getErrorCode(), SYSTEM_CATEGORY));
270
+ }
271
+ return (size_t)n;
272
+ }
273
+
274
+ size_t readSome(char* buf, size_t size, size_t minimum)
275
+ {
276
+ errno = 0;
277
+ int n = recv(m_socket.native(), buf, (int)size, 0);
278
+ if (n == SOCKET_ERROR)
279
+ throw system_error(error_code(getErrorCode(), SYSTEM_CATEGORY));
280
+ return (size_t)n;
281
+ }
282
+
283
+ void write(const char* buf, size_t size, int flag)
284
+ {
285
+ errno = 0;
286
+ int n = send(m_socket.native(), buf, (int)size, flag);
287
+ if (n == SOCKET_ERROR)
288
+ throw system_error(error_code(getErrorCode(), SYSTEM_CATEGORY));
289
+ }
290
+
291
+ template <typename MutableBufferSequence>
292
+ void writeMultibuffer(const MutableBufferSequence& buffer)
293
+ {
294
+ buffers::const_iterator it = buffer.begin();
295
+ buffers::const_iterator ite = buffer.end();
296
+ while (it != ite)
297
+ {
298
+ std::size_t s = asio::buffer_size(*it);
299
+ const char* p = asio::buffer_cast<const char*>(*it);
300
+ write(p, s, (it == (ite - 1)) ? MSG_EOR : MSG_MORE);
301
+ ++it;
302
+ }
303
+ }
304
+
305
+ void on_connected()
306
+ {
307
+ #ifndef _WIN32
308
+ int val = 0;
309
+ ioctl(m_socket.native(), FIONBIO, &val);
310
+ #else
311
+ u_long val = 0;
312
+ ioctlsocket(m_socket.native(), FIONBIO, &val);
313
+ #endif
314
+ }
315
+ };
316
+ #endif
317
+
146
318
  template <class T> class connectionImple : public connectionBase
147
319
  {
148
- #ifdef LINUX
149
- sigset_t m_signmask, m_sigomask;
150
- #endif
151
320
  protected:
152
- //unsigned int m_datalen;
153
- //unsigned short m_rows;
154
321
  T m_socket;
155
322
  buffers m_optionalBuffes;
156
323
 
157
- //unsigned int datalen() const { return m_datalen; }
158
-
159
- //unsigned short rows() const { return m_rows; }
324
+ void checkError(const system::error_code& e)
325
+ {
326
+ if (e)
327
+ {
328
+ if (e == asio::error::operation_aborted)
329
+ throw system_error(asio::error::timed_out);
330
+ throw system_error(e);
331
+ }
332
+ }
160
333
 
161
- // server send any segment of lower than 0xFFFF data by asyncWrite
162
- // last 4byte is 0xFFFFFFFF, that is specify end of data
163
- /*void segmentRead()
334
+ void cleanup()
164
335
  {
165
- bool end = false;
166
- unsigned short n;
167
- while (!end)
336
+ if (m_connected)
168
337
  {
169
- boost::asio::read(m_socket, boost::asio::buffer(&n, 2),
170
- boost::asio::transfer_all());
338
+ try
339
+ {
340
+ m_ios.stop();
341
+ m_socket.close();
342
+ m_ios.reset();
343
+ }
344
+ catch (...)
345
+ {
346
+ }
347
+ m_connected = false;
348
+ }
349
+ }
171
350
 
172
- if (m_readLen + n > m_readbuf.size())
173
- m_readbuf.resize(m_readLen + n);
351
+ ~connectionImple()
352
+ {
353
+ cleanup();
354
+ }
174
355
 
175
- m_readLen += boost::asio::read(
176
- m_socket, boost::asio::buffer(&m_readbuf[m_readLen], n),
177
- boost::asio::transfer_all());
356
+ char* asyncWriteRead(unsigned int writeSize)
357
+ {
358
+ #ifndef _WIN32
359
+ signalmask smask;
360
+ #endif
361
+ write(writeSize);
362
+ return read();
363
+ }
364
+
365
+ buffers* optionalBuffers() { return &m_optionalBuffes; }
366
+
367
+ void reconnect(asio::ip::tcp::endpoint& ep)
368
+ {
369
+ cleanup();
370
+ m_ios.reset();
371
+ m_ep = ep;
372
+ connect();
373
+ }
374
+
375
+ public:
376
+ connectionImple(asio::ip::tcp::endpoint& ep)
377
+ : connectionBase(ep)/*, m_datalen(0)*/, m_socket(m_ios)
378
+ {
379
+ }
380
+ };
381
+
382
+ #define _size_holder asio::placeholders::bytes_transferred
383
+ #define _error_holder asio::placeholders::error
384
+
385
+ /** Implementation of The TCP connection.
386
+ */
387
+ #if (defined(LINUX) && (BOOST_VERSION > 104900))
388
+ #define USE_CONNECT_TIMER
389
+ #endif
390
+
391
+ template <class T>
392
+ class tcpConnection : public connectionImple<asio::ip::tcp::socket>
393
+ {
394
+ T s_io;
395
+ #ifdef USE_CONNECT_TIMER
396
+ asio::deadline_timer m_timer;
397
+ #endif
398
+ std::vector<char> m_readbuf;
399
+ std::vector<char> m_sendbuf;
400
+
401
+ void resizeReadBuffer(unsigned int n)
402
+ {
403
+ if (n > MAX_DATA_SIZE)
404
+ throw exception(ERROR_TD_NET_TOO_BIGDATA, "read");
405
+ if (n > m_readbuf.size())
406
+ m_readbuf.resize(n);
407
+ }
408
+
409
+ char* sendBuffer(size_t size)
410
+ {
411
+ if (size > m_sendbuf.size())
412
+ m_sendbuf.resize(size);
413
+ return &m_sendbuf[0];
414
+ }
415
+
416
+ unsigned int sendBufferSize() { return (unsigned int)m_sendbuf.size(); };
417
+
418
+ void setReadBufferSizeIf(size_t size)
419
+ {
420
+ if (m_readbuf.size() < size)
421
+ m_readbuf.resize(size);
422
+ }
178
423
 
179
- end = (*((unsigned int*)(&m_readbuf[m_readLen - 4])) == 0xFFFFFFFF);
180
- }
181
- m_readLen -= 4;
182
- // additinal data length info
183
- boost::asio::read(m_socket, boost::asio::buffer(&m_datalen, 4),
184
- boost::asio::transfer_all());
185
- boost::asio::read(m_socket, boost::asio::buffer(&m_rows, 2),
186
- boost::asio::transfer_all());
187
- }*/
188
424
  bool queryFunction(unsigned int v)
189
425
  {
190
426
  if (v == CONNECTION_FUNCTION_DIRECT_READ)
@@ -192,78 +428,112 @@ protected:
192
428
  return false;
193
429
  }
194
430
 
431
+ void cleanup()
432
+ {
433
+ #ifdef USE_CONNECT_TIMER
434
+ m_timer.cancel();
435
+ #endif
436
+ connectionImple<asio::ip::tcp::socket>::cleanup();
437
+ }
438
+ #ifdef USE_CONNECT_TIMER
439
+ void setTimer(int time)
440
+ {
441
+ #ifdef _WIN32
442
+ time /= 1000;
443
+ #endif
444
+ m_timer.cancel();
445
+ m_timer.expires_from_now(boost::posix_time::seconds(time));
446
+ m_timer.async_wait(boost::bind(&tcpConnection::on_timer, this, _1));
447
+ }
448
+ #endif
449
+
450
+ void on_connect(const boost::system::error_code& e)
451
+ {
452
+ #ifdef USE_CONNECT_TIMER
453
+ m_timer.cancel();
454
+ #endif
455
+ checkError(e);
456
+ s_io.on_connected();
457
+ m_socket.set_option(boost::asio::ip::tcp::no_delay(true));
458
+ m_connected = true;
459
+ setTimeouts(connections::netTimeout);
460
+ }
461
+
462
+ void on_timer(const boost::system::error_code& e)
463
+ {
464
+ if (e) return;
465
+ #pragma warning(disable : 4996)
466
+ try{ m_socket.cancel(); } catch (...) {}
467
+ #pragma warning(default : 4996)
468
+ }
469
+
470
+ void setTimeouts(int time)
471
+ {
472
+ struct timeval timeout;
473
+ timeout.tv_usec = 0;
474
+ timeout.tv_sec = time;
475
+ int ret = setsockopt(m_socket.native(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout,
476
+ sizeof(timeout));
477
+ ret = setsockopt(m_socket.native(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout,
478
+ sizeof(timeout));
479
+ }
480
+ #ifdef USE_CONNECT_TIMER
481
+ void connect()
482
+ {
483
+ m_socket.async_connect(m_ep,
484
+ bind(&tcpConnection::on_connect, this, _error_holder));
485
+ setTimer(connections::connectTimeout);
486
+ m_ios.run();
487
+ m_ios.reset();
488
+ }
489
+
490
+ void connect()
491
+ {
492
+ setTimeouts(connections::connectTimeout);
493
+ m_socket.connect(m_ep);
494
+ boost::system::error_code e;
495
+ on_connect(e);
496
+ m_ios.reset();
497
+ }
498
+ #endif
499
+
195
500
  unsigned int directRead(void* buf, unsigned int size)
196
501
  {
197
- return (unsigned int)boost::asio::read(m_socket,
198
- boost::asio::buffer(buf, size),
199
- boost::asio::transfer_all());
502
+ return (unsigned int)s_io.readAll((char*)buf, size);
200
503
  }
201
504
 
202
505
  void* directReadRemain(unsigned int size)
203
506
  {
204
507
  if (size > m_readbuf.size())
205
508
  m_readbuf.resize(size);
206
-
207
- m_readLen += boost::asio::read(
208
- m_socket,
209
- boost::asio::buffer(&m_readbuf[0], size),
210
- boost::asio::transfer_all());
509
+ m_readLen += s_io.readAll(&m_readbuf[0], size);
211
510
  return &m_readbuf[0];
212
- }
213
-
214
- template <typename CompletionCondition, typename MutableBufferSequence>
215
- size_t doRead(const MutableBufferSequence& buf, CompletionCondition cnd)
216
- {
217
- boost::system::error_code e;
218
- #ifdef LINUX
219
- pthread_sigmask(SIG_SETMASK, &m_signmask , &m_sigomask);
220
- #endif
221
- size_t n = boost::asio::read(m_socket, buf, cnd, e);
222
- #ifdef LINUX
223
- pthread_sigmask(SIG_SETMASK, &m_sigomask, NULL);
224
- #endif
225
- if (e) throw e;
226
- return n;
227
- }
228
-
511
+ }
512
+
229
513
  char* read()
230
514
  {
231
515
  if (!m_connected)
232
516
  throw system_error(asio::error::not_connected);
233
517
  m_readLen = 0;
234
- //m_datalen = 0;
235
- //m_rows = 0;
236
- unsigned int n;
237
-
238
- //m_readLen += boost::asio::read(m_socket, boost::asio::buffer(&n, 4),
239
- // boost::asio::transfer_all());
240
- /*if (n == 0xFFFFFFFF)
241
- {
242
- segmentRead();
243
- m_readLen += boost::asio::read(m_socket, boost::asio::buffer(&n, 4),
244
- boost::asio::transfer_all());
245
- }*/
518
+ unsigned int n;
246
519
  if (m_reader)
247
520
  {
248
- m_readLen = doRead(boost::asio::buffer(&n, 4), boost::asio::transfer_all());
249
-
521
+ m_readLen = s_io.readAll((char*)&n, 4);
250
522
  m_readLen += m_reader->onRead(n - 4, this);
251
523
  }else
252
524
  {
253
- m_readLen = doRead(boost::asio::buffer(&m_readbuf[0],m_readbuf.size()),
254
- boost::asio::transfer_at_least(4));
525
+ m_readLen = s_io.readSome(&m_readbuf[0], m_readbuf.size(), 4);
255
526
  n = *((unsigned int*)(&m_readbuf[0]));
256
527
  }
257
- if ((n > m_readLen) && (n < MAX_DATA_SIZE))
528
+
529
+ if (n > m_readLen)
258
530
  {
259
- if (n > m_readbuf.size())
260
- m_readbuf.resize(n);
261
- m_readLen += doRead(boost::asio::buffer(&m_readbuf[m_readLen], n - m_readLen),
262
- boost::asio::transfer_all());
531
+ resizeReadBuffer(n);
532
+ m_readLen += s_io.readAll(&m_readbuf[m_readLen], n - m_readLen);
263
533
  }
264
534
  return &m_readbuf[0];
265
- }
266
-
535
+ }
536
+
267
537
  void write(unsigned int writeSize)
268
538
  {
269
539
  if (!m_connected)
@@ -272,105 +542,28 @@ protected:
272
542
  {
273
543
  m_optionalBuffes.insert(m_optionalBuffes.begin(),
274
544
  asio::buffer(sendBuffer(0), writeSize));
275
- boost::asio::write(m_socket, m_optionalBuffes,
276
- boost::asio::transfer_all());
545
+ s_io.writeMultibuffer(m_optionalBuffes);
277
546
  m_optionalBuffes.clear();
278
547
  }
279
548
  else
280
- boost::asio::write(m_socket, asio::buffer(sendBuffer(0), writeSize),
281
- boost::asio::transfer_all());
282
- }
283
-
284
- public:
285
- connectionImple(asio::ip::tcp::endpoint& ep)
286
- : connectionBase(ep)/*, m_datalen(0)*/, m_socket(m_ios)
287
- {
288
- #ifdef LINUX
289
- sigfillset(&m_signmask);
290
- #endif
291
- }
292
-
293
- ~connectionImple()
294
- {
295
- try
296
- {
297
- m_ios.stop();
298
- m_socket.close();
299
- }
300
- catch (...)
301
- {
302
- }
303
- }
304
-
305
- char* asyncWriteRead(unsigned int writeSize)
306
- {
307
- write(writeSize);
308
- return read();
309
- }
310
-
311
- buffers* optionalBuffers() { return &m_optionalBuffes; }
312
- };
313
-
314
-
315
- /** Implementation of The TCP connection.
316
- */
317
- class tcpConnection : public connectionImple<asio::ip::tcp::socket>
318
- {
319
-
549
+ s_io.write(sendBuffer(0), writeSize, MSG_EOR);
550
+ }
320
551
  public:
321
552
  tcpConnection(asio::ip::tcp::endpoint& ep)
322
- : connectionImple<asio::ip::tcp::socket>(ep)
553
+ : connectionImple<asio::ip::tcp::socket>(ep),s_io(m_socket)
554
+ #ifdef USE_CONNECT_TIMER
555
+ , m_timer(m_ios)
556
+ #endif
323
557
  {
324
558
  m_readbuf.resize(READBUF_SIZE);
325
559
  m_sendbuf.resize(WRITEBUF_SIZE);
326
- }
327
-
328
- void setupTimeouts()
329
- {
330
- #if defined _WIN32
331
- int32_t timeout = connections::timeout;
332
- setsockopt(m_socket.native(), SOL_SOCKET, SO_RCVTIMEO,
333
- (const char*)&timeout, sizeof(timeout));
334
- setsockopt(m_socket.native(), SOL_SOCKET, SO_SNDTIMEO,
335
- (const char*)&timeout, sizeof(timeout));
336
- #else
337
- struct timeval timeout;
338
- timeout.tv_usec = 0;
339
- timeout.tv_sec = connections::timeout;
340
- setsockopt(m_socket.native(), SOL_SOCKET, SO_RCVTIMEO, &timeout,
341
- sizeof(timeout));
342
- setsockopt(m_socket.native(), SOL_SOCKET, SO_SNDTIMEO, &timeout,
343
- sizeof(timeout));
344
- #endif
345
- }
346
-
347
- void connect()
348
- {
349
- setupTimeouts();
350
- m_socket.connect(m_ep);
351
- m_socket.set_option(boost::asio::ip::tcp::no_delay(true));
352
- m_connected = true;
353
- }
354
- };
355
-
356
- class exception : public std::exception
357
- {
358
- int m_error;
359
-
360
- std::string m_msg;
361
-
362
- public:
363
- exception(int errorCode, const char* const& message)
364
- : std::exception(), m_error(errorCode), m_msg(message)
365
- {
366
- }
367
-
368
- ~exception() throw() {}
369
-
370
- const char* what() const throw() { return m_msg.c_str(); }
371
-
372
- int error() { return m_error; }
373
- };
560
+ }
561
+ };
562
+ #ifdef __APPLE__
563
+ typedef tcpConnection<asio_tcp_io<asio::ip::tcp::socket> > asio_tcpConnection;
564
+ #else
565
+ typedef tcpConnection<native_tcp_io<asio::ip::tcp::socket> > native_tcpConnection;
566
+ #endif
374
567
 
375
568
  #ifdef USE_PIPE_CLIENT
376
569
 
@@ -388,6 +581,18 @@ class pipeConnection : public connectionImple<platform_stream>
388
581
  HANDLE m_sendEvent;
389
582
  HANDLE m_mapFile;
390
583
 
584
+ unsigned int directRead(void* buf, unsigned int size)
585
+ {
586
+ assert(0);
587
+ return 0;
588
+ }
589
+
590
+ void* directReadRemain(unsigned int size)
591
+ {
592
+ assert(0);
593
+ return NULL;
594
+ }
595
+
391
596
  bool queryFunction(unsigned int v)
392
597
  {
393
598
  if (v == CONNECTION_FUNCTION_DIRECT_READ)
@@ -418,10 +623,9 @@ class pipeConnection : public connectionImple<platform_stream>
418
623
  throw exception(errorCode, buf);
419
624
  }
420
625
 
421
- char* getUniqName(const char* name)
626
+ char* getUniqName(const char* name, char* buf)
422
627
  {
423
- connectionBase::m_readbuf.resize(120);
424
- char* p = &connectionBase::m_readbuf[0];
628
+ char* p = buf;
425
629
  DWORD processId = GetCurrentProcessId();
426
630
  __int64 clientid = (__int64) this;
427
631
  sprintf_s(p, 120, "%s_%u_%Lu", name, processId, clientid);
@@ -431,6 +635,7 @@ class pipeConnection : public connectionImple<platform_stream>
431
635
  void createKernelObjects(unsigned int shareMemSize)
432
636
  {
433
637
  char tmp[50];
638
+ char buf[120];
434
639
  SYSTEM_INFO SystemInfo;
435
640
  GetSystemInfo(&SystemInfo);
436
641
  int size = shareMemSize / SystemInfo.dwAllocationGranularity + 1;
@@ -439,7 +644,7 @@ class pipeConnection : public connectionImple<platform_stream>
439
644
  sprintf_s(tmp, 50, "Global\\%s", m_pipeName.c_str());
440
645
  m_mapFile =
441
646
  CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
442
- m_sendBufferSize * 2, getUniqName(tmp));
647
+ m_sendBufferSize * 2, getUniqName(tmp, buf));
443
648
  if (m_mapFile == NULL)
444
649
  throwException("CreateFileMapping", CLIENT_ERROR_SHAREMEM_DENIED);
445
650
 
@@ -454,12 +659,12 @@ class pipeConnection : public connectionImple<platform_stream>
454
659
  throwException("MapViewOfFile W", CLIENT_ERROR_SHAREMEM_DENIED);
455
660
 
456
661
  sprintf_s(tmp, 50, "Global\\%sToClnt", m_pipeName.c_str());
457
- m_recvEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, getUniqName(tmp));
662
+ m_recvEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, getUniqName(tmp, buf));
458
663
  if (m_recvEvent == NULL)
459
664
  throwException("OpenEvent Client", CLIENT_ERROR_SHAREMEM_DENIED);
460
665
 
461
666
  sprintf_s(tmp, 50, "Global\\%sToSrv", m_pipeName.c_str());
462
- m_sendEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, getUniqName(tmp));
667
+ m_sendEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, getUniqName(tmp, buf));
463
668
  if (m_sendEvent == NULL)
464
669
  throwException("OpenEvent Server", CLIENT_ERROR_SHAREMEM_DENIED);
465
670
  }
@@ -475,7 +680,7 @@ class pipeConnection : public connectionImple<platform_stream>
475
680
 
476
681
  char* read()
477
682
  {
478
- while (WAIT_TIMEOUT == WaitForSingleObject(m_recvEvent, connections::timeout))
683
+ while (WAIT_TIMEOUT == WaitForSingleObject(m_recvEvent, connections::netTimeout))
479
684
  {
480
685
  DWORD n = 0;
481
686
  BOOL ret = GetNamedPipeHandleState(m_socket.native(), NULL, &n,
@@ -486,33 +691,29 @@ class pipeConnection : public connectionImple<platform_stream>
486
691
  return m_readbuf_p;
487
692
  }
488
693
 
489
- public:
490
- pipeConnection(asio::ip::tcp::endpoint& ep, const std::string& pipeName)
491
- : connectionImple<platform_stream>(ep), m_pipeName(pipeName),
492
- m_mapFile(NULL), m_recvEvent(NULL), m_sendEvent(NULL),
493
- m_writebuf_p(NULL), m_readbuf_p(NULL), m_sendBufferSize(0)
494
-
694
+ ~pipeConnection()
495
695
  {
696
+ cleanup();
496
697
  }
497
698
 
498
- ~pipeConnection()
699
+ void cleanup()
499
700
  {
500
701
  if (m_connected)
501
- {
502
- if (m_writebuf_p)
503
- memset(m_writebuf_p, 0, sizeof(unsigned int));
504
- DWORD n = 0;
505
- BOOL ret = GetNamedPipeHandleState(m_socket.native(), NULL, &n,
702
+ {
703
+ if (m_writebuf_p)
704
+ memset(m_writebuf_p, 0, sizeof(unsigned int));
705
+ DWORD n = 0;
706
+ BOOL ret = GetNamedPipeHandleState(m_socket.native(), NULL, &n,
506
707
  NULL, NULL, NULL, 0);
507
708
  if(m_sendEvent && ret && n)
508
709
  {
509
- SetEvent(m_sendEvent);
710
+ SetEvent(m_sendEvent);
510
711
  //Wait for server side close connection
511
712
  while (WAIT_TIMEOUT ==
512
- WaitForSingleObject(m_recvEvent, connections::timeout))
713
+ WaitForSingleObject(m_recvEvent, connections::connectTimeout))
513
714
  ;
514
715
  }
515
- }
716
+ }
516
717
  if (m_recvEvent)
517
718
  CloseHandle(m_recvEvent);
518
719
  if (m_sendEvent)
@@ -523,6 +724,12 @@ public:
523
724
  UnmapViewOfFile(m_readbuf_p);
524
725
  if (m_mapFile)
525
726
  CloseHandle(m_mapFile);
727
+ m_sendEvent = NULL;
728
+ m_recvEvent = NULL;
729
+ m_writebuf_p = NULL;
730
+ m_readbuf_p = NULL;
731
+ m_mapFile = NULL;
732
+ connectionImple<platform_stream>::cleanup();
526
733
  }
527
734
 
528
735
  void connect()
@@ -551,8 +758,8 @@ public:
551
758
  // send processId and clientid;
552
759
  DWORD processId = GetCurrentProcessId();
553
760
  int size = 16;
554
- connectionBase::m_readbuf.resize(256);
555
- char* p = &connectionBase::m_readbuf[0];
761
+ char buf[256];
762
+ char* p = buf;
556
763
  memcpy(p, &size, sizeof(int));
557
764
  memcpy(p + 4, &processId, sizeof(DWORD));
558
765
  __int64 clientid = (__int64) this;
@@ -572,6 +779,15 @@ public:
572
779
  buffers* optionalBuffers() { return NULL; } // not support
573
780
 
574
781
  void setReadBufferSizeIf(size_t size) {} // not support
782
+
783
+ public:
784
+ pipeConnection(asio::ip::tcp::endpoint& ep, const std::string& pipeName)
785
+ : connectionImple<platform_stream>(ep), m_pipeName(pipeName),
786
+ m_mapFile(NULL), m_recvEvent(NULL), m_sendEvent(NULL),
787
+ m_writebuf_p(NULL), m_readbuf_p(NULL), m_sendBufferSize(0)
788
+
789
+ {
790
+ }
575
791
  };
576
792
  #endif // NOT WIN32
577
793