transactd 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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