transactd 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/common/tdclc_32_2_2.dll +0 -0
- data/bin/common/tdclc_64_2_2.dll +0 -0
- data/build/swig/ruby/generate.cmd +45 -0
- data/build/swig/ruby/generate.sh +40 -0
- data/build/swig/ruby/tdclrb_wrap.cpp +406 -969
- data/build/swig/tdcl.i +88 -0
- data/build/tdclc/CMakeLists.txt +5 -1
- data/build/tdclc/tdclc.cbproj +1 -1
- data/build/tdclc/tdclc.rc +4 -4
- data/build/tdclcpp/tdclcpp.rc +4 -4
- data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
- data/build/tdclrb/tdclrb.rc +4 -4
- data/source/bzs/db/engine/mysql/database.cpp +165 -74
- data/source/bzs/db/engine/mysql/database.h +19 -5
- data/source/bzs/db/engine/mysql/dbManager.cpp +33 -11
- data/source/bzs/db/engine/mysql/dbManager.h +6 -1
- data/source/bzs/db/engine/mysql/mydebuglog.h +12 -0
- data/source/bzs/db/engine/mysql/mysqlInternal.h +10 -3
- data/source/bzs/db/engine/mysql/mysqlThd.cpp +20 -8
- data/source/bzs/db/protocol/hs/hsCommandExecuter.cpp +12 -7
- data/source/bzs/db/protocol/hs/hsCommandExecuter.h +1 -1
- data/source/bzs/db/protocol/tdap/client/activeTableImple.h +1 -0
- data/source/bzs/db/protocol/tdap/client/client.cpp +17 -15
- data/source/bzs/db/protocol/tdap/client/client.h +102 -30
- data/source/bzs/db/protocol/tdap/client/connectionPool.cpp +1 -1
- data/source/bzs/db/protocol/tdap/client/database.cpp +32 -10
- data/source/bzs/db/protocol/tdap/client/database.h +1 -0
- data/source/bzs/db/protocol/tdap/client/databaseFactory.cpp +0 -2
- data/source/bzs/db/protocol/tdap/client/dbDef.cpp +2 -0
- data/source/bzs/db/protocol/tdap/client/dllmain.cpp +47 -42
- data/source/bzs/db/protocol/tdap/client/fields.h +3 -1
- data/source/bzs/db/protocol/tdap/client/filter.h +3 -3
- data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +18 -2
- data/source/bzs/db/protocol/tdap/client/nsDatabase.h +3 -2
- data/source/bzs/db/protocol/tdap/client/nsTable.cpp +14 -6
- data/source/bzs/db/protocol/tdap/client/nsTable.h +12 -12
- data/source/bzs/db/protocol/tdap/client/recordsetImple.h +6 -3
- data/source/bzs/db/protocol/tdap/client/request.h +1 -0
- data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +101 -64
- data/source/bzs/db/protocol/tdap/client/sqlBuilder.h +3 -0
- data/source/bzs/db/protocol/tdap/client/stringConverter.h +9 -13
- data/source/bzs/db/protocol/tdap/client/table.cpp +73 -56
- data/source/bzs/db/protocol/tdap/client/table.h +8 -8
- data/source/bzs/db/protocol/tdap/client/trdboostapi.h +52 -100
- data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +8 -1
- data/source/bzs/db/protocol/tdap/mysql/request.h +6 -0
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +349 -189
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +28 -12
- data/source/bzs/db/protocol/tdap/tdapRequest.h +5 -4
- data/source/bzs/db/protocol/tdap/tdapSchema.h +6 -1
- data/source/bzs/db/protocol/tdap/tdapcapi.h +29 -4
- data/source/bzs/db/protocol/tdap/uri.h +297 -0
- data/source/bzs/db/transactd/appModule.cpp +41 -16
- data/source/bzs/db/transactd/appModule.h +1 -2
- data/source/bzs/db/transactd/transactd.cpp +37 -14
- data/source/bzs/env/crosscompile.h +1 -3
- data/source/bzs/example/queryData.cpp +2 -2
- data/source/bzs/netsvc/client/iconnection.h +3 -1
- data/source/bzs/netsvc/client/tcpClient.cpp +75 -28
- data/source/bzs/netsvc/client/tcpClient.h +94 -62
- data/source/bzs/netsvc/server/IAppModule.h +2 -2
- data/source/bzs/netsvc/server/serverCpt.cpp +17 -10
- data/source/bzs/netsvc/server/serverPipe.cpp +26 -19
- data/source/bzs/netsvc/server/serverTpool.cpp +8 -2
- data/source/bzs/rtl/debuglog.cpp +21 -5
- data/source/bzs/rtl/debuglog.h +1 -1
- data/source/bzs/test/tdclphp/transactd_Test.php +183 -37
- data/source/bzs/test/tdclphp/transactd_pool_Test.php +1 -2
- data/source/bzs/test/tdclrb/transactd_spec.rb +183 -39
- data/source/bzs/test/transactdBench/scaling_bench.cpp +3 -3
- data/source/bzs/test/trdclengn/test_trdclengn.cpp +172 -57
- data/source/global/boost/sha1.hpp +223 -0
- data/source/global/tdclatl/ConnectParams.cpp +2 -2
- data/source/global/tdclatl/ConnectParams.h +1 -1
- data/source/global/tdclatl/Database.cpp +18 -0
- data/source/global/tdclatl/Database.h +5 -0
- data/source/global/tdclatl/tdclatl.idl +23 -1
- data/source/linux/linuxTypes.h +2 -0
- metadata +8 -6
- data/bin/common/tdclc_32_2_1.dll +0 -0
- data/bin/common/tdclc_64_2_1.dll +0 -0
- data/source/bzs/db/protocol/tdap/client/memRecordset.cpp +0 -448
- data/source/bzs/db/protocol/tdap/client/memRecordset.h +0 -159
@@ -47,7 +47,7 @@ namespace cpt // connection per thread
|
|
47
47
|
unsigned int g_connections = 0;
|
48
48
|
unsigned int g_waitThread = 0;
|
49
49
|
// ---------------------------------------------------------------------------
|
50
|
-
//
|
50
|
+
// connection
|
51
51
|
// ---------------------------------------------------------------------------
|
52
52
|
#define READBUF_SIZE 66000
|
53
53
|
#define WRITEBUF_SIZE 66000
|
@@ -85,9 +85,15 @@ class connection : public iconnection, private boost::noncopyable
|
|
85
85
|
m_optionalBuffes.clear();
|
86
86
|
vecBuffer vbuf(m_result);
|
87
87
|
bzs::netsvc::server::IResultBuffer& buf = vbuf;
|
88
|
-
|
89
|
-
|
88
|
+
int ret = m_module->execute(buf, size, &m_optionalBuffes);
|
89
|
+
if (ret == EXECUTE_RESULT_QUIT)
|
90
90
|
return;
|
91
|
+
else if(ret == EXECUTE_RESULT_ACCESS_DNIED)
|
92
|
+
{
|
93
|
+
boost::asio::write(m_socket, buffer(&m_result[0], size),
|
94
|
+
boost::asio::transfer_all());
|
95
|
+
return;
|
96
|
+
}
|
91
97
|
else
|
92
98
|
{
|
93
99
|
m_readLen = 0;
|
@@ -200,6 +206,7 @@ public:
|
|
200
206
|
m_socket.set_option(
|
201
207
|
boost::asio::socket_base::send_buffer_size(1024 * 1024 * 10), ec);
|
202
208
|
|
209
|
+
//send handshake packet
|
203
210
|
size_t n = m_module->onAccept(&m_result[0], WRITEBUF_SIZE);
|
204
211
|
if (n)
|
205
212
|
boost::asio::write(m_socket, buffer(&m_result[0], n),
|
@@ -235,7 +242,7 @@ std::vector<connection*> connection::connections;
|
|
235
242
|
mutex connection::m_mutex;
|
236
243
|
|
237
244
|
// ---------------------------------------------------------------------------
|
238
|
-
//
|
245
|
+
// worker
|
239
246
|
// ---------------------------------------------------------------------------
|
240
247
|
|
241
248
|
class worker : private boost::noncopyable
|
@@ -323,7 +330,7 @@ public:
|
|
323
330
|
((IAppModuleBuilder*)app)->createSessionModule(
|
324
331
|
endpoint, m_connection.get(), SERVER_TYPE_CPT));
|
325
332
|
m_connection->setModule(mod);
|
326
|
-
if (mod->checkHost(hostCheckName))
|
333
|
+
if (mod->checkHost(hostCheckName, NULL, 0))
|
327
334
|
{
|
328
335
|
m_connection->sendConnectAccept();
|
329
336
|
m_connection->start(); // It does not return, unless a
|
@@ -372,7 +379,7 @@ std::vector<boost::shared_ptr<boost::thread> > worker::m_threads;
|
|
372
379
|
std::vector<worker*> worker::m_workers;
|
373
380
|
|
374
381
|
// ---------------------------------------------------------------------------
|
375
|
-
//
|
382
|
+
// listener
|
376
383
|
// ---------------------------------------------------------------------------
|
377
384
|
|
378
385
|
class listener
|
@@ -429,13 +436,13 @@ public:
|
|
429
436
|
};
|
430
437
|
|
431
438
|
// ---------------------------------------------------------------------------
|
432
|
-
//
|
439
|
+
// server
|
433
440
|
// ---------------------------------------------------------------------------
|
434
441
|
inotifyHandler* server::erh = NULL;
|
435
442
|
|
436
443
|
/** server
|
437
|
-
*
|
438
|
-
*
|
444
|
+
* If it starts, a server will create the exclusive thread for accpter
|
445
|
+
* and will go into an infinite loop.
|
439
446
|
*/
|
440
447
|
server::server(std::size_t max_connections, const char* hostCheckName)
|
441
448
|
: m_timer(m_ios), m_maxConnections(max_connections), m_stopped(false)
|
@@ -467,7 +474,7 @@ bool server::checkConnections()
|
|
467
474
|
{
|
468
475
|
while (connection::connections.size() > m_maxConnections)
|
469
476
|
{
|
470
|
-
Sleep(100
|
477
|
+
Sleep(100);
|
471
478
|
if (m_stopped)
|
472
479
|
return false;
|
473
480
|
}
|
@@ -92,14 +92,10 @@ void acceptor::accept(platform_stream& pipe)
|
|
92
92
|
m_fd = CreateNamedPipe(pipeName, // pipe name
|
93
93
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
94
94
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
95
|
-
PIPE_UNLIMITED_INSTANCES // max. instances
|
96
|
-
,
|
97
|
-
BUFSIZE //
|
98
|
-
,
|
99
|
-
BUFSIZE // input buffer size
|
100
|
-
,
|
101
|
-
0 // client time-out
|
102
|
-
,
|
95
|
+
PIPE_UNLIMITED_INSTANCES, // max. instances
|
96
|
+
BUFSIZE, // output buffer size
|
97
|
+
BUFSIZE, // input buffer size
|
98
|
+
0, // client time-out
|
103
99
|
&sa); // default security attribute
|
104
100
|
if (m_fd == INVALID_HANDLE_VALUE)
|
105
101
|
THROW_BZS_ERROR_WITH_MSG(getWindowsErrMsg(GetLastError()));
|
@@ -190,9 +186,10 @@ public:
|
|
190
186
|
return true;
|
191
187
|
DWORD ExitCode;
|
192
188
|
if (m_procHandle && GetExitCodeProcess(m_procHandle, &ExitCode))
|
193
|
-
|
189
|
+
{
|
194
190
|
if (STILL_ACTIVE != ExitCode)
|
195
191
|
return true;
|
192
|
+
}
|
196
193
|
if (m_module && m_module->isShutDown())
|
197
194
|
return true;
|
198
195
|
return false;
|
@@ -235,11 +232,13 @@ public:
|
|
235
232
|
|
236
233
|
bool recv(int checkTimeSpan, IExitCheckHandler* handler)
|
237
234
|
{
|
238
|
-
DWORD wait;
|
235
|
+
DWORD wait = WAIT_TIMEOUT;
|
239
236
|
do
|
240
237
|
{
|
238
|
+
if (wait == WAIT_ABANDONED)
|
239
|
+
return false;
|
241
240
|
if (m_cancel || (handler && (handler->isExit())))
|
242
|
-
return
|
241
|
+
return false;
|
243
242
|
} while (WAIT_OBJECT_0 !=
|
244
243
|
(wait = WaitForSingleObject(m_recv, checkTimeSpan)));
|
245
244
|
m_sent = false;
|
@@ -341,19 +340,23 @@ class connection : public iconnection, private noncopyable
|
|
341
340
|
return;
|
342
341
|
bool complete = false;
|
343
342
|
m_readLen = *((unsigned int*)m_sharedMem->readBuffer());
|
343
|
+
//When readLen = 0 , close connection
|
344
344
|
if (m_readLen == 0)
|
345
345
|
return;
|
346
346
|
m_module->onRead(m_sharedMem->readBuffer(), m_readLen, complete);
|
347
347
|
if (complete)
|
348
348
|
{
|
349
349
|
size_t size = 0;
|
350
|
-
|
351
|
-
|
350
|
+
int ret = m_module->execute(sharedMemBuffer(*m_sharedMem), size, NULL);
|
351
|
+
if (ret == EXECUTE_RESULT_QUIT)
|
352
352
|
return;
|
353
353
|
else
|
354
354
|
m_readLen = 0;
|
355
355
|
|
356
356
|
sentResult = m_comm->send();
|
357
|
+
//When named pipe, dissconnect from local client.
|
358
|
+
//if (ret == EXECUTE_RESULT_ACCESS_DNIED)
|
359
|
+
// return;
|
357
360
|
m_module->cleanup();
|
358
361
|
}
|
359
362
|
}
|
@@ -434,10 +437,15 @@ public:
|
|
434
437
|
m_exitHandler.reset(new exitCheckHnadler(clinetProcessID));
|
435
438
|
if (m_module)
|
436
439
|
m_exitHandler->setModule(m_module.get());
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
440
|
+
tmp[0] = 0x00; // signe of handshakable
|
441
|
+
memcpy(tmp + 3, &m_shareMemSize, sizeof(unsigned int));// sharemem size
|
442
|
+
//asio::write(m_socket, buffer(tmp, 7), e);
|
443
|
+
//len = asio::read(m_socket, buffer(buf, 9), e);
|
444
|
+
//if (len != 9)
|
445
|
+
// THROW_BZS_ERROR_WITH_MSG("handshake error");
|
446
|
+
//send handshake packet
|
447
|
+
m_module->onAccept(m_sharedMem->writeBuffer(), m_sharedMem->size());
|
448
|
+
m_comm->send();
|
441
449
|
asio::write(m_socket, buffer(tmp, 7), e);
|
442
450
|
run();
|
443
451
|
}
|
@@ -522,7 +530,6 @@ public:
|
|
522
530
|
*/
|
523
531
|
static worker* worker::get(const IAppModuleBuilder* app)
|
524
532
|
{
|
525
|
-
|
526
533
|
worker* p = findWaitThread();
|
527
534
|
if (p == NULL)
|
528
535
|
{
|
@@ -565,7 +572,7 @@ public:
|
|
565
572
|
((IAppModuleBuilder*)app)->createSessionModule(
|
566
573
|
endpoint, m_connection.get(), SERVER_TYPE_CPT));
|
567
574
|
m_connection->setModule(mod);
|
568
|
-
if (mod->checkHost(hostCheckName))
|
575
|
+
if (mod->checkHost(hostCheckName, NULL, 0))
|
569
576
|
m_connection->start(); // It does not return, unless a
|
570
577
|
// connection is close.
|
571
578
|
m_connection.reset();
|
@@ -153,6 +153,12 @@ class connection : public boost::enable_shared_from_this<connection>,
|
|
153
153
|
|
154
154
|
if (ret == EXECUTE_RESULT_QUIT)
|
155
155
|
return;
|
156
|
+
else if(ret == EXECUTE_RESULT_ACCESS_DNIED)
|
157
|
+
{
|
158
|
+
boost::asio::write(m_socket, buffer(&m_result[0], size),
|
159
|
+
boost::asio::transfer_all());
|
160
|
+
return;
|
161
|
+
}
|
156
162
|
|
157
163
|
m_optionalBuffes.insert(m_optionalBuffes.begin(),
|
158
164
|
buffer(&m_result[0], size));
|
@@ -170,7 +176,6 @@ class connection : public boost::enable_shared_from_this<connection>,
|
|
170
176
|
boost::bind(&connection::handle_write,
|
171
177
|
shared_from_this(),
|
172
178
|
boost::asio::placeholders::error));
|
173
|
-
|
174
179
|
return;
|
175
180
|
}
|
176
181
|
|
@@ -231,6 +236,7 @@ public:
|
|
231
236
|
|
232
237
|
void sendConnectAccept()
|
233
238
|
{
|
239
|
+
//send handshake packet
|
234
240
|
size_t n = m_module->onAccept(&m_result[0], WRITEBUF_SIZE);
|
235
241
|
if (n)
|
236
242
|
boost::asio::write(m_socket, buffer(&m_result[0], n),
|
@@ -313,7 +319,7 @@ public:
|
|
313
319
|
boost::shared_ptr<IAppModule> mod(m_app->createSessionModule(
|
314
320
|
endpoint, m_newConnection.get(), SERVER_TYPE_TPOOL));
|
315
321
|
m_newConnection->setModule(mod);
|
316
|
-
if (mod->checkHost(m_srv->hostCheckName()))
|
322
|
+
if (mod->checkHost(m_srv->hostCheckName(), NULL, 0))
|
317
323
|
{
|
318
324
|
m_newConnection->sendConnectAccept();
|
319
325
|
m_newConnection->start();
|
data/source/bzs/rtl/debuglog.cpp
CHANGED
@@ -74,12 +74,26 @@ void debuglog::dump(FILE* fp, const char* p, int size, int limit)
|
|
74
74
|
size = std::min<int>(size, limit);
|
75
75
|
for (int i = 0; i < size; i += 16)
|
76
76
|
{
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
const char* pp = p + i;
|
78
|
+
int max = std::min<int>(size - i, 16);
|
79
|
+
for (int j = 0; j < max; j++)
|
80
|
+
fprintf(fp, "%02X ", *((unsigned char*)(pp + j)));
|
81
|
+
|
82
|
+
if (max != 16)
|
83
|
+
{
|
84
|
+
for (int j = 0; j < 16 - max; j++)
|
85
|
+
fprintf(fp, " ");
|
86
|
+
}
|
87
|
+
|
80
88
|
fprintf(fp, " ");
|
81
|
-
for (int j = 0; j <
|
82
|
-
|
89
|
+
for (int j = 0; j < max; j++)
|
90
|
+
{
|
91
|
+
const char* p1 = pp + j;
|
92
|
+
if (*p1 >= ' ' && *p1 <= '~')
|
93
|
+
fprintf(fp, "%c", *p1);
|
94
|
+
else
|
95
|
+
fprintf(fp, " ");
|
96
|
+
}
|
83
97
|
fprintf(fp, "\n");
|
84
98
|
}
|
85
99
|
fprintf(fp, "\n");
|
@@ -91,6 +105,8 @@ void debuglog::writeDump(const char* msg, const char* ptr, int size)
|
|
91
105
|
FILE* fp = fileOpen(logfilename, "a+");
|
92
106
|
if (fp)
|
93
107
|
{
|
108
|
+
fputs(dateTime(), fp);
|
109
|
+
fputs(" ", fp);
|
94
110
|
fputs(msg, fp);
|
95
111
|
fputs("\n", fp);
|
96
112
|
dump(fp, ptr, size, INT_MAX);
|
data/source/bzs/rtl/debuglog.h
CHANGED
@@ -61,7 +61,7 @@ public:
|
|
61
61
|
#define DEBUG_WRITELOG(MSG)
|
62
62
|
#endif // DEBUG_LOG
|
63
63
|
|
64
|
-
#if defined(DEBUG_PROFILE) || defined(DEBUG_LOG)
|
64
|
+
#if defined(DEBUG_PROFILE) || defined(DEBUG_LOG) || defined(DEBUG_LOG_ERR)
|
65
65
|
#define DEBUG_PROFILE_INIT() bzs::rtl::debuglog::get()->init();
|
66
66
|
#define DEBUG_PROFILE_DEINIT() bzs::rtl::debuglog::get()->stop();
|
67
67
|
#else
|
@@ -42,7 +42,32 @@ define("FDI_NAMEW", 2);
|
|
42
42
|
define("BULKBUFSIZE", 65535 - 1000);
|
43
43
|
define("TEST_COUNT", 20000);
|
44
44
|
define("FIVE_PERCENT_OF_TEST_COUNT", TEST_COUNT / 20);
|
45
|
-
|
45
|
+
|
46
|
+
// multi thread test if `php_pthreads` exists.
|
47
|
+
if(class_exists('Thread')){
|
48
|
+
class SeekLessThanWorker extends Thread
|
49
|
+
{
|
50
|
+
public function __construct()
|
51
|
+
{
|
52
|
+
$this->value = -1;
|
53
|
+
}
|
54
|
+
public function run()
|
55
|
+
{
|
56
|
+
$dbm = new Bz\pooledDbManager(new Bz\connectParams(URL));
|
57
|
+
$tb = $dbm->table('user');
|
58
|
+
$tb->setFV(FDI_ID, 300000);
|
59
|
+
$tb->seekLessThan(false, Bz\transactd::ROW_LOCK_X);
|
60
|
+
$this->value = $tb->getFVint(FDI_ID);
|
61
|
+
$tb->unlock();
|
62
|
+
$tb->close();
|
63
|
+
$dbm->unUse();
|
64
|
+
}
|
65
|
+
public function getResult()
|
66
|
+
{
|
67
|
+
return $this->value;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
46
71
|
|
47
72
|
class transactdTest extends PHPUnit_Framework_TestCase
|
48
73
|
{
|
@@ -263,8 +288,9 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
263
288
|
$this->assertEquals($client_ver->majorVersion, Bz\transactd::CPP_INTERFACE_VER_MAJOR);
|
264
289
|
$this->assertEquals($client_ver->minorVersion, Bz\transactd::CPP_INTERFACE_VER_MINOR);
|
265
290
|
$this->assertEquals(chr($client_ver->type), 'N');
|
266
|
-
$
|
267
|
-
$
|
291
|
+
$my5x = ($server_ver->majorVersion == 5) && ($server_ver->minorVersion >= 5);
|
292
|
+
$maria10 = ($server_ver->majorVersion == 10) && ($server_ver->minorVersion == 0);
|
293
|
+
$this->assertTrue($my5x || $maria10);
|
268
294
|
$this->assertEquals(chr($server_ver->type), 'M');
|
269
295
|
$this->assertEquals($engine_ver->majorVersion, Bz\transactd::TRANSACTD_VER_MAJOR);
|
270
296
|
$this->assertEquals($engine_ver->minorVersion, Bz\transactd::TRANSACTD_VER_MINOR);
|
@@ -756,6 +782,9 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
756
782
|
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_NOT_FOUND_TI);
|
757
783
|
|
758
784
|
// clean up
|
785
|
+
$tb2->setFV(FDI_ID, 29999);
|
786
|
+
$tb2->seek();
|
787
|
+
$this->assertEquals($tb2->stat(), 0);
|
759
788
|
$tb2->del();
|
760
789
|
$this->assertEquals($tb2->stat(), 0);
|
761
790
|
|
@@ -784,6 +813,24 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
784
813
|
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
785
814
|
|
786
815
|
$db->endSnapshot();
|
816
|
+
|
817
|
+
// gap lock
|
818
|
+
$db->beginSnapshot(Bz\transactd::MULTILOCK_NOGAP_SHARE);
|
819
|
+
$tb->seekLast(); // id = 30000
|
820
|
+
$this->assertEquals($tb->stat(), 0);
|
821
|
+
$tb->seekPrev(); // id = 20002
|
822
|
+
$this->assertEquals($tb->stat(), 0);
|
823
|
+
$tb->seekPrev(); // id = 20001
|
824
|
+
$this->assertEquals($tb->stat(), 0);
|
825
|
+
|
826
|
+
$tb2->setFV(FDI_ID, 20002);
|
827
|
+
$tb2->seek(Bz\transactd::ROW_LOCK_X);
|
828
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
829
|
+
|
830
|
+
$tb2->seekLast(Bz\transactd::ROW_LOCK_X);
|
831
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
832
|
+
|
833
|
+
$db->endSnapshot();
|
787
834
|
}
|
788
835
|
public function testConflict()
|
789
836
|
{
|
@@ -954,6 +1001,37 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
954
1001
|
$this->assertEquals($tb->getFVint(FDI_ID), $last2);
|
955
1002
|
$db->endTrn();
|
956
1003
|
|
1004
|
+
// ----------------------------------------------------
|
1005
|
+
// Test use shared lock option
|
1006
|
+
// ----------------------------------------------------
|
1007
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
1008
|
+
$this->assertEquals(0, $db->stat());
|
1009
|
+
|
1010
|
+
$db2->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
1011
|
+
$this->assertEquals(0, $db2->stat());
|
1012
|
+
|
1013
|
+
$tb->seekLast(Bz\transactd::ROW_LOCK_S);
|
1014
|
+
$this->assertEquals(0, $tb->stat());
|
1015
|
+
$tb2->seekLast(Bz\transactd::ROW_LOCK_S);
|
1016
|
+
$this->assertEquals(0, $tb2->stat());
|
1017
|
+
|
1018
|
+
$tb->seekPrev(); // Lock(X)
|
1019
|
+
$this->assertEquals(0, $tb->stat());
|
1020
|
+
|
1021
|
+
$tb2->seekPrev(Bz\transactd::ROW_LOCK_S);
|
1022
|
+
$this->assertEquals(Bz\transactd::STATUS_LOCK_ERROR, $tb2->stat());
|
1023
|
+
|
1024
|
+
$tb->seekPrev(Bz\transactd::ROW_LOCK_S);
|
1025
|
+
$this->assertEquals(0, $tb->stat());
|
1026
|
+
$id = $tb->getFVint(FDI_ID);
|
1027
|
+
|
1028
|
+
$tb2->setFV(FDI_ID, $id);
|
1029
|
+
$tb2->seek(Bz\transactd::ROW_LOCK_S);
|
1030
|
+
$this->assertEquals(0, $tb2->stat());
|
1031
|
+
|
1032
|
+
$db2->endTrn();
|
1033
|
+
$db->endTrn();
|
1034
|
+
|
957
1035
|
// ----------------------------------------------------
|
958
1036
|
// Test Abort
|
959
1037
|
// ----------------------------------------------------
|
@@ -1255,6 +1333,9 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1255
1333
|
// No match records are unlocked.
|
1256
1334
|
$tb2->setFV(FDI_ID, 100);
|
1257
1335
|
$tb2->seek(Bz\transactd::ROW_LOCK_X);
|
1336
|
+
$this->assertEquals(0, $tb2->stat());
|
1337
|
+
$tb2->setFV(FDI_ID, 101);
|
1338
|
+
$tb2->seek(Bz\transactd::ROW_LOCK_X);
|
1258
1339
|
$this->assertEquals($tb2->stat(), 0);
|
1259
1340
|
$tb2->unlock();
|
1260
1341
|
$db->endTrn();
|
@@ -1318,8 +1399,11 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1318
1399
|
$tb2->seekNext(Bz\transactd::ROW_LOCK_X); // lock(X) third, second lock freed
|
1319
1400
|
$this->assertEquals($tb2->stat(), 0);
|
1320
1401
|
|
1321
|
-
$tb->seekNext(); // nobody lock second.
|
1322
|
-
|
1402
|
+
$tb->seekNext(); // nobody lock second. But REPEATABLE_READ tb2 lock all(no unlock)
|
1403
|
+
if ($db->trxIsolationServer() == Bz\transactd::SRV_ISO_REPEATABLE_READ)
|
1404
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
1405
|
+
else
|
1406
|
+
$this->assertEquals($tb->stat(), 0);
|
1323
1407
|
$tb->seekNext(Bz\transactd::ROW_LOCK_X); // Try lock(X) third
|
1324
1408
|
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
1325
1409
|
|
@@ -1345,10 +1429,15 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1345
1429
|
$tb->setFV(FDI_ID, 21000);
|
1346
1430
|
$tb->insert();
|
1347
1431
|
$this->assertEquals($tb->stat(), 0);
|
1432
|
+
|
1433
|
+
//cleanup
|
1434
|
+
$tb->setFV(FDI_ID, 21000);
|
1435
|
+
$tb->seek();
|
1436
|
+
$this->assertEquals($tb->stat(), 0);
|
1348
1437
|
$tb->del();
|
1349
1438
|
$this->assertEquals($tb->stat(), 0);
|
1350
1439
|
|
1351
|
-
// ---------
|
1440
|
+
// --------- Unlock test ---------------------------
|
1352
1441
|
// 1 unlock()
|
1353
1442
|
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
1354
1443
|
$this->assertEquals($tb->stat(), 0);
|
@@ -1404,7 +1493,11 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1404
1493
|
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
1405
1494
|
$this->assertEquals($tb2->stat(), 0);
|
1406
1495
|
$tb2->unlock();
|
1407
|
-
// ---------
|
1496
|
+
// --------- End Unlock test -----------------------
|
1497
|
+
|
1498
|
+
// --------- Invalid lock type test ----------------
|
1499
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_S);
|
1500
|
+
$this->assertEquals(Bz\transactd::STATUS_INVALID_LOCKTYPE, $tb2->stat());
|
1408
1501
|
}
|
1409
1502
|
public function testExclusive()
|
1410
1503
|
{
|
@@ -1423,23 +1516,21 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1423
1516
|
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
1424
1517
|
$this->assertEquals($db2->stat(), 0);
|
1425
1518
|
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF);
|
1519
|
+
// database open error. Check database::stat()
|
1426
1520
|
$this->assertEquals($db2->stat(), Bz\transactd::STATUS_CANNOT_LOCK_TABLE);
|
1427
1521
|
$tb->close();
|
1428
1522
|
$db->close();
|
1429
1523
|
$db2->close();
|
1430
1524
|
|
1431
1525
|
// ------------------------------------------------------
|
1432
|
-
// database
|
1526
|
+
// database READ EXCLUSIVE
|
1433
1527
|
// ------------------------------------------------------
|
1434
|
-
// table mode exclusive
|
1435
|
-
$db = new Bz\database();
|
1436
1528
|
$db->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_READONLY_EXCLUSIVE);
|
1437
1529
|
$this->assertEquals($db->stat(), 0);
|
1438
1530
|
$tb = $db->openTable(TABLENAME, Bz\transactd::TD_OPEN_READONLY_EXCLUSIVE);
|
1439
1531
|
$this->assertEquals($db->stat(), 0);
|
1440
1532
|
|
1441
1533
|
// Read only open
|
1442
|
-
$db2 = new Bz\database();
|
1443
1534
|
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF);
|
1444
1535
|
$this->assertEquals($db2->stat(), 0);
|
1445
1536
|
$db2->close();
|
@@ -1459,6 +1550,7 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1459
1550
|
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_READONLY_EXCLUSIVE);
|
1460
1551
|
$this->assertEquals($db2->stat(), 0);
|
1461
1552
|
$db2->close();
|
1553
|
+
$tb->close();
|
1462
1554
|
$db->close();
|
1463
1555
|
|
1464
1556
|
// ------------------------------------------------------
|
@@ -1473,10 +1565,10 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1473
1565
|
|
1474
1566
|
$tb2 = $db->openTable('group', Bz\transactd::TD_OPEN_EXCLUSIVE);
|
1475
1567
|
$this->assertEquals($db->stat(), 0);
|
1568
|
+
|
1476
1569
|
// Check tb2 Exclusive
|
1477
1570
|
$tb3 = $db2->openTable('group', Bz\transactd::TD_OPEN_NORMAL);
|
1478
1571
|
$this->assertEquals($db2->stat(), Bz\transactd::STATUS_CANNOT_LOCK_TABLE);
|
1479
|
-
|
1480
1572
|
for ($i = 1; $i < 5; $i++)
|
1481
1573
|
{
|
1482
1574
|
$tb2->setFV(FDI_ID, $i + 1);
|
@@ -1517,10 +1609,10 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1517
1609
|
$this->assertEquals($tb->stat(), 0);
|
1518
1610
|
|
1519
1611
|
// ------------------------------------------------------
|
1520
|
-
// Normal and Exclusive
|
1612
|
+
// Normal and Exclusive open tables mix transaction
|
1521
1613
|
// ------------------------------------------------------
|
1522
1614
|
$tb2 = $db->openTable('group', Bz\transactd::TD_OPEN_EXCLUSIVE);
|
1523
|
-
$this->assertEquals($
|
1615
|
+
$this->assertEquals($db->stat(), 0);
|
1524
1616
|
// Check tb2 Exclusive
|
1525
1617
|
$tb3 = $db2->openTable('group', Bz\transactd::TD_OPEN_NORMAL);
|
1526
1618
|
$this->assertEquals($db2->stat(), Bz\transactd::STATUS_CANNOT_LOCK_TABLE);
|
@@ -1586,6 +1678,70 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1586
1678
|
$v2 = $tb->getFVstr(FDI_NAME);
|
1587
1679
|
$this->assertEquals($v, $v2);
|
1588
1680
|
}
|
1681
|
+
public function testMissingUpdate()
|
1682
|
+
{
|
1683
|
+
if(! class_exists('Thread'))
|
1684
|
+
{
|
1685
|
+
echo(' * class Thread not found! * ');
|
1686
|
+
return;
|
1687
|
+
}
|
1688
|
+
$db = new Bz\database();
|
1689
|
+
$tb = $this->openTable($db);
|
1690
|
+
Bz\pooledDbManager::setMaxConnections(3);
|
1691
|
+
// Lock last record and insert to next of it
|
1692
|
+
$w = new SeekLessThanWorker();
|
1693
|
+
$tb->setFV(FDI_ID, 300000);
|
1694
|
+
$tb->seekLessThan(false, Bz\transactd::ROW_LOCK_X);
|
1695
|
+
$this->assertEquals($tb->stat(), 0);
|
1696
|
+
if ($tb->stat() == 0)
|
1697
|
+
{
|
1698
|
+
// Get lock(X) same record in parallel.
|
1699
|
+
$w->start();
|
1700
|
+
usleep(5000);
|
1701
|
+
$v = $tb->getFVint(FDI_ID);
|
1702
|
+
$tb->setFV(FDI_ID, ++$v);
|
1703
|
+
$tb->insert();
|
1704
|
+
$this->assertEquals($tb->stat(), 0);
|
1705
|
+
$w->join();
|
1706
|
+
$v2 = $w->getResult();
|
1707
|
+
|
1708
|
+
if ($db->trxIsolationServer() == Bz\transactd::SRV_ISO_REPEATABLE_READ)
|
1709
|
+
{ // $tb can not insert because $tb2 got gap lock with SRV_ISO_REPEATABLE_READ.
|
1710
|
+
// It is deadlock!
|
1711
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
1712
|
+
}
|
1713
|
+
else
|
1714
|
+
{ // When SRV_ISO_READ_COMMITED set, $tb2 get lock after $tb->insert.
|
1715
|
+
// But this is not READ_COMMITED !
|
1716
|
+
$this->assertEquals($tb->stat(), 0);
|
1717
|
+
$this->assertEquals($v2, $v - 1);
|
1718
|
+
// cleanup
|
1719
|
+
$tb->setFV(FDI_ID, $v);
|
1720
|
+
$tb->seek();
|
1721
|
+
$this->assertEquals($tb->stat(), 0);
|
1722
|
+
$tb->del();
|
1723
|
+
$this->assertEquals($tb->stat(), 0);
|
1724
|
+
}
|
1725
|
+
}
|
1726
|
+
// Lock last record and delete it
|
1727
|
+
$w = new SeekLessThanWorker();
|
1728
|
+
$tb->setFV(FDI_ID, 300000);
|
1729
|
+
$tb->seekLessThan(false, Bz\transactd::ROW_LOCK_X);
|
1730
|
+
$this->assertEquals($tb->stat(), 0);
|
1731
|
+
if ($tb->stat() == 0)
|
1732
|
+
{
|
1733
|
+
// Get lock(X) same record in parallel.
|
1734
|
+
$w->start();
|
1735
|
+
usleep(5000);
|
1736
|
+
$v = $tb->getFVint(FDI_ID);
|
1737
|
+
$tb->del();
|
1738
|
+
$this->assertEquals($tb->stat(), 0);
|
1739
|
+
$w->join();
|
1740
|
+
$v2 = $w->getResult();
|
1741
|
+
$this->assertNotEquals($v, $v2);
|
1742
|
+
}
|
1743
|
+
(new Bz\pooledDbManager())->reset(0);
|
1744
|
+
}
|
1589
1745
|
public function testInsert2()
|
1590
1746
|
{
|
1591
1747
|
$db = new Bz\database();
|
@@ -1611,13 +1767,16 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1611
1767
|
$db = new Bz\database();
|
1612
1768
|
$tb = $this->openTable($db);
|
1613
1769
|
$this->assertNotEquals($tb, NULL);
|
1770
|
+
$expected_count = 20003;
|
1771
|
+
if(! class_exists('Thread'))
|
1772
|
+
$expected_count = $expected_count + 1;
|
1614
1773
|
// estimate count
|
1615
1774
|
$count = $tb->recordCount(true);
|
1616
|
-
$is_valid_count = (abs($count -
|
1775
|
+
$is_valid_count = (abs($count - $expected_count) < 5000);
|
1617
1776
|
$this->assertTrue($is_valid_count);
|
1618
1777
|
if (! $is_valid_count)
|
1619
|
-
print("true record count = " .
|
1620
|
-
$this->assertEquals($tb->recordCount(false),
|
1778
|
+
print("true record count = " . $expected_count . " and estimate recordCount count = " . $count);
|
1779
|
+
$this->assertEquals($tb->recordCount(false), $expected_count); // true count
|
1621
1780
|
$vv = TEST_COUNT * 3 / 4 + 1;
|
1622
1781
|
$tb->clearBuffer();
|
1623
1782
|
$tb->setFV(FDI_ID, $vv);
|
@@ -1684,7 +1843,7 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1684
1843
|
$db2->connect(PROTOCOL . HOSTNAME, true);
|
1685
1844
|
$this->assertEquals($db2->stat(), 0);
|
1686
1845
|
unset($db2);
|
1687
|
-
$db->disconnect(
|
1846
|
+
$db->disconnect();
|
1688
1847
|
$this->assertEquals($db->stat(), 0);
|
1689
1848
|
}
|
1690
1849
|
// invalid host name
|
@@ -1696,24 +1855,24 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
1696
1855
|
print('bad host $db->stat() = ' . $db->stat());
|
1697
1856
|
$this->createDatabase($db);
|
1698
1857
|
$this->createTable($db);
|
1699
|
-
$db->
|
1858
|
+
$db->close();
|
1700
1859
|
$this->assertEquals($db->stat(), 0);
|
1701
1860
|
// true database name
|
1702
1861
|
$db->connect(PROTOCOL . HOSTNAME . DBNAME);
|
1703
1862
|
$this->assertEquals($db->stat(), 0);
|
1704
1863
|
if ($db->stat() == 0)
|
1705
1864
|
{
|
1706
|
-
$db->disconnect(
|
1865
|
+
$db->disconnect();
|
1707
1866
|
$this->assertEquals($db->stat(), 0);
|
1708
1867
|
}
|
1709
1868
|
// invalid database name
|
1710
1869
|
$this->dropDatabase($db);
|
1711
|
-
$db->disconnect(
|
1870
|
+
$db->disconnect();
|
1712
1871
|
$this->assertEquals($db->stat(), 0);
|
1713
1872
|
$db->connect(PROTOCOL . HOSTNAME . DBNAME);
|
1714
|
-
$this->assertEquals($db->stat(),
|
1715
|
-
$db->disconnect(
|
1716
|
-
$this->assertEquals($db->stat(),
|
1873
|
+
$this->assertEquals($db->stat(), Bz\transactd::ERROR_NO_DATABASE);
|
1874
|
+
$db->disconnect();
|
1875
|
+
$this->assertEquals($db->stat(), 1);
|
1717
1876
|
}
|
1718
1877
|
|
1719
1878
|
/* -----------------------------------------------------
|
@@ -3242,19 +3401,6 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
3242
3401
|
// $rs[0];
|
3243
3402
|
$this->assertEquals($rs[0]['group_name'], '1 group');
|
3244
3403
|
|
3245
|
-
/*
|
3246
|
-
sortFields orderRv;
|
3247
|
-
orderRv.add('group_name', false);
|
3248
|
-
rs.orderBy(orderRv);
|
3249
|
-
|
3250
|
-
sortFields order;
|
3251
|
-
order.add('group_name', true);
|
3252
|
-
rs.orderBy(order);
|
3253
|
-
BOOST_CHECK_MESSAGE(_tstring(rs[(size_t)0]['group_name'].c_str()) ==
|
3254
|
-
_tstring('1 group'),
|
3255
|
-
"group_name = 1 group "
|
3256
|
-
<< string(rs[(size_t)0]['group_name'].a_str()));
|
3257
|
-
*/
|
3258
3404
|
// All fields
|
3259
3405
|
$rs->clear();
|
3260
3406
|
$q->reset()->all();
|
@@ -90,7 +90,6 @@ class transactdPoolTest extends PHPUnit_Framework_TestCase
|
|
90
90
|
$dbm = new Bz\pooledDbManager($cp);
|
91
91
|
$atu = new Bz\ActiveTable($dbm, 'user');
|
92
92
|
$q = new Bz\query();
|
93
|
-
$rs = new Bz\RecordSet();
|
94
93
|
$atu->alias('名前', 'name');
|
95
94
|
$q->select('id', 'name', 'group')->where('id', '<=', 15000);
|
96
95
|
$rs = $atu->index(0)->keyValue(1)->read($q);
|
@@ -105,7 +104,7 @@ class transactdPoolTest extends PHPUnit_Framework_TestCase
|
|
105
104
|
public function testMultiThreads()
|
106
105
|
{
|
107
106
|
if(! class_exists('Thread')){
|
108
|
-
echo(' * class
|
107
|
+
echo(' * class Thread not found! * ');
|
109
108
|
return;
|
110
109
|
}
|
111
110
|
Bz\pooledDbManager::setMaxConnections(5);
|