vincentchu-handlersocket 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. data/ext/HandlerSocket-Plugin-for-MySQL/AUTHORS +22 -0
  2. data/ext/HandlerSocket-Plugin-for-MySQL/COPYING +30 -0
  3. data/ext/HandlerSocket-Plugin-for-MySQL/ChangeLog +12 -0
  4. data/ext/HandlerSocket-Plugin-for-MySQL/Makefile.am +87 -0
  5. data/ext/HandlerSocket-Plugin-for-MySQL/README +78 -0
  6. data/ext/HandlerSocket-Plugin-for-MySQL/autogen.sh +117 -0
  7. data/ext/HandlerSocket-Plugin-for-MySQL/client/Makefile.am +24 -0
  8. data/ext/HandlerSocket-Plugin-for-MySQL/client/hsclient.cpp +88 -0
  9. data/ext/HandlerSocket-Plugin-for-MySQL/client/hslongrun.cpp +1041 -0
  10. data/ext/HandlerSocket-Plugin-for-MySQL/client/hspool_test.pl +224 -0
  11. data/ext/HandlerSocket-Plugin-for-MySQL/client/hstest.cpp +1532 -0
  12. data/ext/HandlerSocket-Plugin-for-MySQL/client/hstest.pl +228 -0
  13. data/ext/HandlerSocket-Plugin-for-MySQL/client/hstest_hs.sh +4 -0
  14. data/ext/HandlerSocket-Plugin-for-MySQL/client/hstest_hs_more50.sh +4 -0
  15. data/ext/HandlerSocket-Plugin-for-MySQL/client/hstest_md.sh +7 -0
  16. data/ext/HandlerSocket-Plugin-for-MySQL/client/hstest_my.sh +3 -0
  17. data/ext/HandlerSocket-Plugin-for-MySQL/client/hstest_my_more50.sh +3 -0
  18. data/ext/HandlerSocket-Plugin-for-MySQL/configure.ac +144 -0
  19. data/ext/HandlerSocket-Plugin-for-MySQL/docs-en/about-handlersocket.en.txt +72 -0
  20. data/ext/HandlerSocket-Plugin-for-MySQL/docs-en/configuration-options.en.txt +99 -0
  21. data/ext/HandlerSocket-Plugin-for-MySQL/docs-en/installation.en.txt +92 -0
  22. data/ext/HandlerSocket-Plugin-for-MySQL/docs-en/perl-client.en.txt +135 -0
  23. data/ext/HandlerSocket-Plugin-for-MySQL/docs-en/protocol.en.txt +205 -0
  24. data/ext/HandlerSocket-Plugin-for-MySQL/docs-ja/about-handlersocket.ja.txt +51 -0
  25. data/ext/HandlerSocket-Plugin-for-MySQL/docs-ja/installation.ja.txt +88 -0
  26. data/ext/HandlerSocket-Plugin-for-MySQL/docs-ja/perl-client.ja.txt +127 -0
  27. data/ext/HandlerSocket-Plugin-for-MySQL/docs-ja/protocol.ja.txt +180 -0
  28. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/COPYRIGHT.txt +27 -0
  29. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/Makefile.am +10 -0
  30. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/Makefile.plain.template +31 -0
  31. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/database.cpp +1190 -0
  32. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/database.hpp +142 -0
  33. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/handlersocket.cpp +222 -0
  34. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/handlersocket.spec.template +29 -0
  35. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr.cpp +149 -0
  36. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr.hpp +58 -0
  37. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr_worker.cpp +951 -0
  38. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/hstcpsvr_worker.hpp +35 -0
  39. data/ext/HandlerSocket-Plugin-for-MySQL/handlersocket/mysql_incl.hpp +50 -0
  40. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/COPYRIGHT.txt +27 -0
  41. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/Makefile.am +12 -0
  42. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/Makefile.plain +27 -0
  43. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/allocator.hpp +64 -0
  44. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/auto_addrinfo.hpp +49 -0
  45. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/auto_file.hpp +64 -0
  46. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/auto_ptrcontainer.hpp +67 -0
  47. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/config.cpp +67 -0
  48. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/config.hpp +32 -0
  49. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/escape.cpp +127 -0
  50. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/escape.hpp +66 -0
  51. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/fatal.cpp +36 -0
  52. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/fatal.hpp +22 -0
  53. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/hstcpcli.cpp +441 -0
  54. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/hstcpcli.hpp +62 -0
  55. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/libhsclient.spec.template +39 -0
  56. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/mutex.hpp +51 -0
  57. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/socket.cpp +186 -0
  58. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/socket.hpp +51 -0
  59. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/string_buffer.hpp +118 -0
  60. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/string_ref.hpp +63 -0
  61. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/string_util.cpp +182 -0
  62. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/string_util.hpp +53 -0
  63. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/thread.hpp +84 -0
  64. data/ext/HandlerSocket-Plugin-for-MySQL/libhsclient/util.hpp +25 -0
  65. data/ext/HandlerSocket-Plugin-for-MySQL/misc/microbench-hs.log +130 -0
  66. data/ext/HandlerSocket-Plugin-for-MySQL/misc/microbench-my.log +125 -0
  67. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/COPYRIGHT.txt +27 -0
  68. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/Changes +6 -0
  69. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/HandlerSocket.xs +632 -0
  70. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/MANIFEST +8 -0
  71. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/Makefile.PL +18 -0
  72. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/Makefile.PL.installed +20 -0
  73. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/README +30 -0
  74. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/lib/Net/HandlerSocket.pm +68 -0
  75. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm +362 -0
  76. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/perl-Net-HandlerSocket.spec.template +127 -0
  77. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/ppport.h +6375 -0
  78. data/ext/HandlerSocket-Plugin-for-MySQL/perl-Net-HandlerSocket/t/Net-HandlerSocket.t +15 -0
  79. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/Makefile +79 -0
  80. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/common/binary_my.cnf +4 -0
  81. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/common/compat.sh +29 -0
  82. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/common/hstest.pm +66 -0
  83. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/Makefile +4 -0
  84. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/run.sh +27 -0
  85. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test01.expected +100 -0
  86. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test01.pl +38 -0
  87. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test02.expected +100 -0
  88. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test02.pl +49 -0
  89. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test03.expected +771 -0
  90. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test03.pl +61 -0
  91. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test04.expected +0 -0
  92. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test04.pl +63 -0
  93. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test05.expected +771 -0
  94. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test05.pl +59 -0
  95. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test06.expected +644 -0
  96. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test06.pl +90 -0
  97. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test07.expected +304 -0
  98. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test07.pl +98 -0
  99. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test08.expected +2 -0
  100. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test08.pl +48 -0
  101. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test09.expected +12 -0
  102. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test09.pl +67 -0
  103. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test10.expected +771 -0
  104. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test10.pl +93 -0
  105. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test11.expected +37 -0
  106. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test11.pl +112 -0
  107. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test12.expected +273 -0
  108. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test12.pl +134 -0
  109. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test13.expected +92 -0
  110. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test13.pl +92 -0
  111. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test14.expected +144 -0
  112. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test14.pl +80 -0
  113. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test15.expected +764 -0
  114. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test15.pl +114 -0
  115. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test16.expected +66 -0
  116. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test16.pl +88 -0
  117. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test17.expected +0 -0
  118. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test17.pl +125 -0
  119. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test18.expected +22 -0
  120. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test18.pl +63 -0
  121. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test19.expected +14894 -0
  122. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test19.pl +190 -0
  123. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test20.expected +2 -0
  124. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test20.pl +33 -0
  125. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test21.expected +11 -0
  126. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test21.pl +58 -0
  127. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test22.expected +9 -0
  128. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test22.pl +61 -0
  129. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test23.expected +101 -0
  130. data/ext/HandlerSocket-Plugin-for-MySQL/regtest/test_01_lib/test23.pl +53 -0
  131. data/ext/winebarrel-ruby-handlersocket-c19841e47ea2/README +33 -0
  132. data/ext/winebarrel-ruby-handlersocket-c19841e47ea2/extconf.rb +27 -0
  133. data/ext/winebarrel-ruby-handlersocket-c19841e47ea2/handlersocket.cpp +437 -0
  134. data/ext/winebarrel-ruby-handlersocket-c19841e47ea2/handlersocket.h +32 -0
  135. metadata +200 -0
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/perl
2
+
3
+ use strict;
4
+ use warnings;
5
+ use DB::HandlerSocket::Pool;
6
+ use DBI;
7
+
8
+ my %conf = ();
9
+ for my $i (@ARGV) {
10
+ my ($k, $v) = split(/=/, $i);
11
+ $conf{$k} = $v;
12
+ }
13
+
14
+ my $verbose = get_conf("verbose", 0);
15
+ my $actions_str = get_conf("actions",
16
+ "create,insert,verify,verify2,verify3,verify4,clean");
17
+ my $tablesize = get_conf("tablesize", 1000);
18
+ my $db = get_conf("db", "hstestdb");
19
+ my $table = get_conf("table", "testtbl");
20
+ my $table_schema = get_conf("table_schema", undef);
21
+ my $engine = get_conf("engine", "innodb");
22
+ my $host = get_conf("host", "localhost");
23
+ my $mysqlport = get_conf("mysqlport", 3306);
24
+ my $hsport_rd = get_conf("hsport_rd", 9998);
25
+ my $hsport_wr = get_conf("hsport_wr", 9999);
26
+ my $loop = get_conf("loop", 10000);
27
+ my $op = get_conf("op", "=");
28
+ my $ssps = get_conf("ssps", 0);
29
+ my $num_moreflds = get_conf("moreflds", 0);
30
+ my $moreflds_prefix = get_conf("moreflds_prefix", "f");
31
+ my $mysql_user = 'root';
32
+ my $mysql_password = '';
33
+
34
+ my $dsn = "DBI:mysql:database=;host=$host;port=$mysqlport"
35
+ . ";mysql_server_prepare=$ssps";
36
+ my $dbh = DBI->connect($dsn, $mysql_user, $mysql_password,
37
+ { RaiseError => 1 });
38
+ my $hsargs = { 'host' => $host, 'port' => $hsport_rd };
39
+ my $hspool = new DB::HandlerSocket::Pool({
40
+ hostmap => {
41
+ "$db.$table" => {
42
+ host => $host,
43
+ port => $hsport_rd,
44
+ },
45
+ },
46
+ resolve => undef,
47
+ error => undef,
48
+ });
49
+ $table_schema = "(k int primary key, fc30 varchar(30), ft text)"
50
+ if (!defined($table_schema));
51
+
52
+ my @actions = split(/,/, $actions_str);
53
+ for my $action (@actions) {
54
+ print "ACTION: $action\n";
55
+ eval "hstest_$action()";
56
+ if ($@) {
57
+ die $@;
58
+ }
59
+ print "ACTION: $action DONE\n";
60
+ }
61
+
62
+ sub get_conf {
63
+ my ($key, $def) = @_;
64
+ my $val = $conf{$key};
65
+ if ($val) {
66
+ print "$key=$val\n";
67
+ } else {
68
+ $val = $def;
69
+ my $defstr = $def || "(undef)";
70
+ print "$key=$defstr(default)\n";
71
+ }
72
+ return $val;
73
+ }
74
+
75
+ sub hstest_create {
76
+ $dbh->do("drop database if exists $db");
77
+ $dbh->do("create database $db");
78
+ $dbh->do("use $db");
79
+ $dbh->do("create table $table $table_schema engine=$engine");
80
+ }
81
+
82
+ sub hstest_dump {
83
+ $dbh->do("use $db");
84
+ my $sth = $dbh->prepare("select * from $table");
85
+ $sth->execute();
86
+ my $arr = $sth->fetchall_arrayref();
87
+ for my $rec (@$arr) {
88
+ print "REC:";
89
+ for my $row (@$rec) {
90
+ print " $row";
91
+ }
92
+ print "\n";
93
+ }
94
+ }
95
+
96
+ sub hstest_insert {
97
+ $dbh->do("use $db");
98
+ my $sth = $dbh->prepare("insert into $table values (?, ?, ?)");
99
+ for (my $k = 0; $k < $tablesize; ++$k) {
100
+ my $fc30 = "fc30_$k";
101
+ my $ft = "ft_$k";
102
+ $sth->execute($k, $fc30, $ft);
103
+ }
104
+ }
105
+
106
+ sub hstest_verify {
107
+ $dbh->do("use $db");
108
+ my $sth = $dbh->prepare("select * from $table order by k");
109
+ $sth->execute();
110
+ my $arr = $sth->fetchall_arrayref();
111
+ my $hsres = $hspool->index_find($db, $table, "PRIMARY", "k,fc30,ft",
112
+ ">=", [ 0 ], $tablesize, 0);
113
+ for (my $i = 0; $i < $tablesize; ++$i) {
114
+ my $rec = $arr->[$i];
115
+ my $differ = 0;
116
+ print "REC:" if $verbose;
117
+ for (my $j = 0; $j < 3; ++$j) {
118
+ my $fld = $rec->[$j];
119
+ my $hsidx = $i * 3 + $j;
120
+ my $hsfld = $hsres->[$hsidx];
121
+ if ($hsfld ne $fld) {
122
+ $differ = 1;
123
+ }
124
+ if ($differ) {
125
+ print " $fld:$hsfld" if $verbose;
126
+ } else {
127
+ print " $hsfld" if $verbose;
128
+ }
129
+ }
130
+ print "\n" if $verbose;
131
+ if ($differ) {
132
+ die "verification failed";
133
+ }
134
+ }
135
+ }
136
+
137
+ sub hstest_verify2 {
138
+ $dbh->do("use $db");
139
+ my $sth = $dbh->prepare("select * from $table order by k");
140
+ $sth->execute();
141
+ my $arr = $sth->fetchall_arrayref();
142
+ my $hsresa = $hspool->index_find_multi($db, $table, "PRIMARY",
143
+ "k,fc30,ft", [ [ -1, ">=", [ 0 ], $tablesize, 0 ] ]);
144
+ my $hsres = $hsresa->[0];
145
+ for (my $i = 0; $i < $tablesize; ++$i) {
146
+ my $rec = $arr->[$i];
147
+ my $differ = 0;
148
+ print "REC:" if $verbose;
149
+ for (my $j = 0; $j < 3; ++$j) {
150
+ my $fld = $rec->[$j];
151
+ my $hsidx = $i * 3 + $j;
152
+ my $hsfld = $hsres->[$hsidx];
153
+ if ($hsfld ne $fld) {
154
+ $differ = 1;
155
+ }
156
+ if ($differ) {
157
+ print " $fld:$hsfld" if $verbose;
158
+ } else {
159
+ print " $hsfld" if $verbose;
160
+ }
161
+ }
162
+ print "\n" if $verbose;
163
+ if ($differ) {
164
+ die "verification failed";
165
+ }
166
+ }
167
+ }
168
+
169
+ sub hashref_to_str {
170
+ my $href = $_[0];
171
+ my $r = '';
172
+ for my $k (sort keys %$href) {
173
+ my $v = $href->{$k};
174
+ $r .= "($k=>$v)";
175
+ }
176
+ return $r;
177
+ }
178
+
179
+ sub hstest_verify3 {
180
+ $dbh->do("use $db");
181
+ my $sth = $dbh->prepare("select * from $table order by k");
182
+ $sth->execute();
183
+ my $hsres_t = $hspool->index_find($db, $table, "PRIMARY", "k,fc30,ft",
184
+ ">=", [ 0 ], $tablesize, 0);
185
+ my $hsres = DB::HandlerSocket::Pool::result_single_to_hasharr(
186
+ [ 'k', 'fc30', 'ft' ], $hsres_t);
187
+ for (my $i = 0; $i < $tablesize; ++$i) {
188
+ my $mystr = hashref_to_str($sth->fetchrow_hashref());
189
+ my $hsstr = hashref_to_str($hsres->[$i]);
190
+ if ($mystr ne $hsstr) {
191
+ print "DIFF my=[$mystr] hs=[$hsstr]\n" if $verbose;
192
+ die "verification failed";
193
+ } else {
194
+ print "OK $hsstr\n" if $verbose;
195
+ }
196
+ }
197
+ }
198
+
199
+ sub hstest_verify4 {
200
+ $dbh->do("use $db");
201
+ my $sth = $dbh->prepare("select * from $table order by k");
202
+ $sth->execute();
203
+ my $hsres_t = $hspool->index_find($db, $table, "PRIMARY", "k,fc30,ft",
204
+ ">=", [ 0 ], $tablesize, 0);
205
+ my $hsres = DB::HandlerSocket::Pool::result_single_to_hashhash(
206
+ [ 'k', 'fc30', 'ft' ], 'k', $hsres_t);
207
+ my $rechash = $sth->fetchall_hashref('k');
208
+ while (my ($k, $href) = each (%$rechash)) {
209
+ my $mystr = hashref_to_str($href);
210
+ my $hsstr = hashref_to_str($hsres->{$k});
211
+ if ($mystr ne $hsstr) {
212
+ print "DIFF my=[$mystr] hs=[$hsstr]\n" if $verbose;
213
+ die "verification failed";
214
+ } else {
215
+ print "OK $hsstr\n" if $verbose;
216
+ }
217
+ }
218
+ }
219
+
220
+ sub hstest_clean {
221
+ $hspool->clear_pool();
222
+ $dbh->do("drop database if exists $db");
223
+ }
224
+
@@ -0,0 +1,1532 @@
1
+
2
+ // vim:sw=2:ai
3
+
4
+ #include <signal.h>
5
+ #include <sys/time.h>
6
+ #include <stdio.h>
7
+ #include <string.h>
8
+ #include <vector>
9
+ #include <stdlib.h>
10
+ #include <memory>
11
+ #include <errno.h>
12
+ #include <mysql.h>
13
+ #include <time.h>
14
+ #include <sys/types.h>
15
+ #include <sys/stat.h>
16
+ #include <fcntl.h>
17
+
18
+ #include "util.hpp"
19
+ #include "auto_ptrcontainer.hpp"
20
+ #include "socket.hpp"
21
+ #include "thread.hpp"
22
+ #include "hstcpcli.hpp"
23
+
24
+ #if __GNUC__ >= 4
25
+ long atomic_exchange_and_add(volatile long *valp, long c)
26
+ {
27
+ return __sync_fetch_and_add(valp, c);
28
+ }
29
+ #else
30
+ #include <bits/atomicity.h>
31
+ using namespace __gnu_cxx;
32
+ long atomic_exchange_and_add(volatile long *valp, long c)
33
+ {
34
+ return __exchange_and_add((volatile _Atomic_word *)valp, c);
35
+ }
36
+ #endif
37
+
38
+ namespace dena {
39
+
40
+ struct auto_mysql : private noncopyable {
41
+ auto_mysql() : db(0) {
42
+ reset();
43
+ }
44
+ ~auto_mysql() {
45
+ if (db) {
46
+ mysql_close(db);
47
+ }
48
+ }
49
+ void reset() {
50
+ if (db) {
51
+ mysql_close(db);
52
+ }
53
+ if ((db = mysql_init(0)) == 0) {
54
+ fatal_abort("failed to initialize mysql client");
55
+ }
56
+ }
57
+ operator MYSQL *() const { return db; }
58
+ private:
59
+ MYSQL *db;
60
+ };
61
+
62
+ struct auto_mysql_res : private noncopyable {
63
+ auto_mysql_res(MYSQL *db) {
64
+ res = mysql_store_result(db);
65
+ }
66
+ ~auto_mysql_res() {
67
+ if (res) {
68
+ mysql_free_result(res);
69
+ }
70
+ }
71
+ operator MYSQL_RES *() const { return res; }
72
+ private:
73
+ MYSQL_RES *res;
74
+ };
75
+
76
+ struct auto_mysql_stmt : private noncopyable {
77
+ auto_mysql_stmt(MYSQL *db) {
78
+ stmt = mysql_stmt_init(db);
79
+ }
80
+ ~auto_mysql_stmt() {
81
+ if (stmt) {
82
+ mysql_stmt_close(stmt);
83
+ }
84
+ }
85
+ operator MYSQL_STMT *() const { return stmt; }
86
+ private:
87
+ MYSQL_STMT *stmt;
88
+ };
89
+
90
+ namespace {
91
+
92
+ double
93
+ gettimeofday_double()
94
+ {
95
+ struct timeval tv = { };
96
+ if (gettimeofday(&tv, 0) != 0) {
97
+ fatal_abort("gettimeofday");
98
+ }
99
+ return static_cast<double>(tv.tv_usec) / 1000000 + tv.tv_sec;
100
+ }
101
+
102
+ // unused
103
+ void
104
+ wait_close(int fd)
105
+ {
106
+ char buf[1024];
107
+ while (true) {
108
+ int r = read(fd, buf, sizeof(buf));
109
+ if (r <= 0) {
110
+ break;
111
+ }
112
+ }
113
+ }
114
+
115
+ // unused
116
+ void
117
+ gentle_close(int fd)
118
+ {
119
+ int r = shutdown(fd, SHUT_WR);
120
+ if (r != 0) {
121
+ return;
122
+ }
123
+ wait_close(fd);
124
+ }
125
+
126
+ };
127
+
128
+ struct hstest_shared {
129
+ config conf;
130
+ socket_args arg;
131
+ int verbose;
132
+ size_t loop;
133
+ size_t pipe;
134
+ char op;
135
+ long num_threads;
136
+ mutable volatile long count;
137
+ mutable volatile long conn_count;
138
+ long wait_conn;
139
+ volatile char *keygen;
140
+ long keygen_size;
141
+ mutable volatile int enable_timing;
142
+ int usleep;
143
+ int dump;
144
+ hstest_shared() : verbose(0), loop(0), pipe(0), op('G'), num_threads(0),
145
+ count(0), conn_count(0), wait_conn(0), keygen(0), keygen_size(0),
146
+ enable_timing(0), usleep(0), dump(0) { }
147
+ void increment_count(unsigned int c = 1) const volatile {
148
+ atomic_exchange_and_add(&count, c);
149
+ }
150
+ void increment_conn(unsigned int c) const volatile {
151
+ atomic_exchange_and_add(&conn_count, c);
152
+ while (wait_conn != 0 && conn_count < wait_conn) {
153
+ sleep(1);
154
+ }
155
+ // fprintf(stderr, "wait_conn=%ld done\n", wait_conn);
156
+ }
157
+ };
158
+
159
+ struct hstest_thread {
160
+ struct arg_type {
161
+ size_t id;
162
+ const hstest_shared& sh;
163
+ bool watch_flag;
164
+ arg_type(size_t i, const hstest_shared& s, bool w)
165
+ : id(i), sh(s), watch_flag(w) { }
166
+ };
167
+ hstest_thread(const arg_type& a) : arg(a), io_success_count(0),
168
+ op_success_count(0), response_min(99999), response_max(0),
169
+ response_sum(0), response_avg(0) { }
170
+ void operator ()();
171
+ void test_1();
172
+ void test_2_3(int test_num);
173
+ void test_4_5(int test_num);
174
+ void test_6(int test_num);
175
+ void test_7(int test_num);
176
+ void test_8(int test_num);
177
+ void test_9(int test_num);
178
+ void test_10(int test_num);
179
+ void test_11(int test_num);
180
+ void test_12(int test_num);
181
+ void test_21(int test_num);
182
+ void test_22(int test_num);
183
+ void test_watch();
184
+ void sleep_if();
185
+ void set_timing(double time_spent);
186
+ arg_type arg;
187
+ auto_file fd;
188
+ size_t io_success_count;
189
+ size_t op_success_count;
190
+ double response_min, response_max, response_sum, response_avg;
191
+ };
192
+
193
+ void
194
+ hstest_thread::test_1()
195
+ {
196
+ char buf[1024];
197
+ unsigned int seed = arg.id;
198
+ seed ^= arg.sh.conf.get_int("seed_xor", 0);
199
+ std::string err;
200
+ if (socket_connect(fd, arg.sh.arg, err) != 0) {
201
+ fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
202
+ return;
203
+ }
204
+ const char op = arg.sh.op;
205
+ const int tablesize = arg.sh.conf.get_int("tablesize", 0);
206
+ for (size_t i = 0; i < arg.sh.loop; ++i) {
207
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
208
+ int k = 0, v = 0, len = 0;
209
+ if (op == 'G') {
210
+ k = rand_r(&seed);
211
+ v = rand_r(&seed); /* unused */
212
+ if (tablesize != 0) {
213
+ k &= tablesize;
214
+ }
215
+ len = snprintf(buf, sizeof(buf), "%c\tk%d\n", op, k);
216
+ } else {
217
+ k = rand_r(&seed);
218
+ v = rand_r(&seed);
219
+ if (tablesize != 0) {
220
+ k &= tablesize;
221
+ }
222
+ len = snprintf(buf, sizeof(buf), "%c\tk%d\tv%d\n", op, k, v);
223
+ }
224
+ const int wlen = write(fd.get(), buf, len);
225
+ if (wlen != len) {
226
+ return;
227
+ }
228
+ }
229
+ size_t read_cnt = 0;
230
+ size_t read_pos = 0;
231
+ while (read_cnt < arg.sh.pipe) {
232
+ const int rlen = read(fd.get(), buf + read_pos, sizeof(buf) - read_pos);
233
+ if (rlen <= 0) {
234
+ return;
235
+ }
236
+ read_pos += rlen;
237
+ while (true) {
238
+ const char *const p = static_cast<const char *>(memchr(buf, '\n',
239
+ read_pos));
240
+ if (p == 0) {
241
+ break;
242
+ }
243
+ ++read_cnt;
244
+ ++io_success_count;
245
+ arg.sh.increment_count();
246
+ if (p != buf && buf[0] == '=') {
247
+ ++op_success_count;
248
+ }
249
+ const size_t rest_size = buf + read_pos - (p + 1);
250
+ if (rest_size != 0) {
251
+ memmove(buf, p + 1, rest_size);
252
+ }
253
+ read_pos = rest_size;
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+ void
260
+ hstest_thread::test_2_3(int test_num)
261
+ {
262
+ #if 0
263
+ char buf_k[128], buf_v[128];
264
+ unsigned int seed = arg.id;
265
+ op_base_t op = static_cast<op_base_t>(arg.sh.op);
266
+ micli_ptr hnd;
267
+ if (test_num == 2) {
268
+ hnd = micli_i::create_remote(arg.sh.conf);
269
+ } else if (test_num == 3) {
270
+ // hnd = micli_i::create_inproc(arg.sh.localdb);
271
+ }
272
+ if (hnd.get() == 0) {
273
+ return;
274
+ }
275
+ for (size_t i = 0; i < arg.sh.loop; ++i) {
276
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
277
+ int k = 0, v = 0, klen = 0, vlen = 0;
278
+ k = rand_r(&seed);
279
+ klen = snprintf(buf_k, sizeof(buf_k), "k%d", k);
280
+ v = rand_r(&seed); /* unused */
281
+ vlen = snprintf(buf_v, sizeof(buf_v), "v%d", v);
282
+ string_ref arr[2];
283
+ arr[0] = string_ref(buf_k, klen);
284
+ arr[1] = string_ref(buf_v, vlen);
285
+ pstrarr_ptr rec(arr, 2);
286
+ if (hnd->execute(op, 0, 0, rec.get_const())) {
287
+ ++io_success_count;
288
+ arg.sh.increment_count();
289
+ const dataset& res = hnd->get_result_ref();
290
+ if (res.size() == 1) {
291
+ ++op_success_count;
292
+ }
293
+ }
294
+ }
295
+ }
296
+ #endif
297
+ }
298
+
299
+ void
300
+ hstest_thread::test_4_5(int test_num)
301
+ {
302
+ #if 0
303
+ char buf_k[128], buf_v[8192];
304
+ memset(buf_v, ' ', sizeof(buf_v));
305
+ unsigned int seed = arg.id;
306
+ op_base_t op = static_cast<op_base_t>(arg.sh.op);
307
+ micli_ptr hnd;
308
+ if (test_num == 4) {
309
+ hnd = micli_i::create_remote(arg.sh.conf);
310
+ } else if (test_num == 5) {
311
+ hnd = micli_i::create_inproc(arg.sh.localdb);
312
+ }
313
+ if (hnd.get() == 0) {
314
+ return;
315
+ }
316
+ for (size_t i = 0; i < arg.sh.loop; ++i) {
317
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
318
+ int k = 0, klen = 0, vlen = 0;
319
+ k = i & 0x0000ffffUL;
320
+ if (k == 0) {
321
+ fprintf(stderr, "k=0\n");
322
+ }
323
+ klen = snprintf(buf_k, sizeof(buf_k), "k%d", k);
324
+ vlen = rand_r(&seed) % 8192;
325
+ string_ref arr[2];
326
+ arr[0] = string_ref(buf_k, klen);
327
+ arr[1] = string_ref(buf_v, vlen);
328
+ pstrarr_ptr rec(arr, 2);
329
+ if (hnd->execute(op, 0, 0, rec.get_const())) {
330
+ ++io_success_count;
331
+ const dataset& res = hnd->get_result_ref();
332
+ if (res.size() == 1) {
333
+ ++op_success_count;
334
+ }
335
+ }
336
+ }
337
+ }
338
+ #endif
339
+ }
340
+
341
+ void
342
+ hstest_thread::test_6(int test_num)
343
+ {
344
+ int count = arg.sh.conf.get_int("count", 1);
345
+ auto_file fds[count];
346
+ for (int i = 0; i < count; ++i) {
347
+ const double t1 = gettimeofday_double();
348
+ std::string err;
349
+ if (socket_connect(fds[i], arg.sh.arg, err) != 0) {
350
+ fprintf(stderr, "id=%zu i=%d err=%s\n", arg.id, i, err.c_str());
351
+ }
352
+ const double t2 = gettimeofday_double();
353
+ if (t2 - t1 > 1) {
354
+ fprintf(stderr, "id=%zu i=%d time %f\n", arg.id, i, t2 - t1);
355
+ }
356
+ }
357
+ }
358
+
359
+ void
360
+ hstest_thread::test_7(int num)
361
+ {
362
+ /*
363
+ set foo 0 0 10
364
+ 0123456789
365
+ STORED
366
+ get foo
367
+ VALUE foo 0 10
368
+ 0123456789
369
+ END
370
+ get var
371
+ END
372
+ */
373
+ char buf[1024];
374
+ const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
375
+ unsigned int seed = arg.id;
376
+ seed ^= arg.sh.conf.get_int("seed_xor", 0);
377
+ const int tablesize = arg.sh.conf.get_int("tablesize", 0);
378
+ const char op = arg.sh.op;
379
+ for (size_t i = 0; i < arg.sh.loop; ++i) {
380
+ const double tm1 = gettimeofday_double();
381
+ std::string err;
382
+ if (fd.get() < 0 && socket_connect(fd, arg.sh.arg, err) != 0) {
383
+ fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
384
+ return;
385
+ }
386
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
387
+ int k = 0, v = 0, len = 0;
388
+ if (op == 'G') {
389
+ k = rand_r(&seed);
390
+ v = rand_r(&seed); /* unused */
391
+ if (tablesize != 0) {
392
+ k &= tablesize;
393
+ }
394
+ len = snprintf(buf, sizeof(buf), "get k%d\r\n", k);
395
+ } else {
396
+ k = rand_r(&seed);
397
+ v = rand_r(&seed);
398
+ if (tablesize != 0) {
399
+ k &= tablesize;
400
+ }
401
+ char vbuf[1024];
402
+ int vlen = snprintf(vbuf, sizeof(vbuf),
403
+ "v%d"
404
+ // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
405
+ // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
406
+ // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
407
+ // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
408
+ // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
409
+ , v);
410
+ len = snprintf(buf, sizeof(buf), "set k%d 0 0 %d\r\n%s\r\n",
411
+ k, vlen, vbuf);
412
+ }
413
+ const int wlen = write(fd.get(), buf, len);
414
+ if (wlen != len) {
415
+ return;
416
+ }
417
+ }
418
+ size_t read_cnt = 0;
419
+ size_t read_pos = 0;
420
+ bool read_response_done = false;
421
+ bool expect_value = false;
422
+ while (!read_response_done) {
423
+ const int rlen = read(fd.get(), buf + read_pos, sizeof(buf) - read_pos);
424
+ if (rlen <= 0) {
425
+ return;
426
+ }
427
+ read_pos += rlen;
428
+ while (true) {
429
+ const char *const p = static_cast<const char *>(memchr(buf, '\n',
430
+ read_pos));
431
+ if (p == 0) {
432
+ break;
433
+ }
434
+ ++read_cnt;
435
+ if (expect_value) {
436
+ expect_value = false;
437
+ } else if (p >= buf + 6 && memcmp(buf, "VALUE ", 6) == 0) {
438
+ expect_value = true;
439
+ ++op_success_count;
440
+ } else {
441
+ if (p == buf + 7 && memcmp(buf, "STORED\r", 7) == 0) {
442
+ ++op_success_count;
443
+ }
444
+ read_response_done = true;
445
+ }
446
+ const size_t rest_size = buf + read_pos - (p + 1);
447
+ if (rest_size != 0) {
448
+ memmove(buf, p + 1, rest_size);
449
+ }
450
+ read_pos = rest_size;
451
+ }
452
+ ++io_success_count;
453
+ }
454
+ arg.sh.increment_count();
455
+ if (!keep_connection) {
456
+ fd.close();
457
+ }
458
+ const double tm2 = gettimeofday_double();
459
+ set_timing(tm2 - tm1);
460
+ sleep_if();
461
+ }
462
+ }
463
+
464
+ struct rec {
465
+ std::string key;
466
+ std::string value;
467
+ };
468
+
469
+ void
470
+ hstest_thread::test_8(int test_num)
471
+ {
472
+ #if 0
473
+ char buf_k[128], buf_v[128];
474
+ unsigned int seed = arg.id;
475
+ // op_base_t op = static_cast<op_base_t>(arg.sh.op);
476
+ using namespace boost::multi_index;
477
+ typedef member<rec, std::string, &rec::key> rec_get_key;
478
+ typedef ordered_unique<rec_get_key> oui;
479
+ typedef multi_index_container< rec, indexed_by<oui> > mic;
480
+ #if 0
481
+ typedef std::map<std::string, std::string> m_type;
482
+ m_type m;
483
+ #endif
484
+ mic m;
485
+ for (size_t i = 0; i < arg.sh.loop; ++i) {
486
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
487
+ int k = 0, v = 0, klen = 0, vlen = 0;
488
+ k = rand_r(&seed);
489
+ klen = snprintf(buf_k, sizeof(buf_k), "k%d", k);
490
+ v = rand_r(&seed); /* unused */
491
+ vlen = snprintf(buf_v, sizeof(buf_v), "v%d", v);
492
+ const std::string ks(buf_k, klen);
493
+ const std::string vs(buf_v, vlen);
494
+ rec r;
495
+ r.key = ks;
496
+ r.value = vs;
497
+ m.insert(r);
498
+ // m.insert(std::make_pair(ks, vs));
499
+ ++io_success_count;
500
+ ++op_success_count;
501
+ arg.sh.increment_count();
502
+ }
503
+ }
504
+ #endif
505
+ }
506
+
507
+ struct mysqltest_thread_initobj : private noncopyable {
508
+ mysqltest_thread_initobj() {
509
+ mysql_thread_init();
510
+ }
511
+ ~mysqltest_thread_initobj() {
512
+ mysql_thread_end();
513
+ }
514
+ };
515
+
516
+ void
517
+ hstest_thread::test_9(int test_num)
518
+ {
519
+ /* create table hstest
520
+ * ( k varchar(255) not null, v varchar(255) not null, primary key(k))
521
+ * engine = innodb; */
522
+ auto_mysql db;
523
+ // mysqltest_thread_initobj initobj;
524
+ std::string err;
525
+ const char op = arg.sh.op;
526
+ const std::string suffix = arg.sh.conf.get_str("value_suffix", "upd");
527
+ unsigned long long err_cnt = 0;
528
+ unsigned long long query_cnt = 0;
529
+ #if 0
530
+ my_bool reconnect = 0;
531
+ if (mysql_options(db, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
532
+ err = "mysql_options() failed";
533
+ ++err_cnt;
534
+ return;
535
+ }
536
+ #endif
537
+ unsigned int seed = time(0) + arg.id + 1;
538
+ seed ^= arg.sh.conf.get_int("seed_xor", 0);
539
+ drand48_data randbuf;
540
+ srand48_r(seed, &randbuf);
541
+ const std::string mysql_host = arg.sh.conf.get_str("host", "localhost");
542
+ const int mysql_port = arg.sh.conf.get_int("mysqlport", 3306);
543
+ const int num = arg.sh.loop;
544
+ const std::string mysql_user = arg.sh.conf.get_str("mysqluser", "root");
545
+ const std::string mysql_passwd = arg.sh.conf.get_str("mysqlpass", "");
546
+ const std::string mysql_dbname = arg.sh.conf.get_str("dbname", "hstest");
547
+ const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
548
+ const int verbose = arg.sh.conf.get_int("verbose", 1);
549
+ const int tablesize = arg.sh.conf.get_int("tablesize", 10000);
550
+ const int moreflds = arg.sh.conf.get_int("moreflds", 0);
551
+ const std::string moreflds_prefix = arg.sh.conf.get_str(
552
+ "moreflds_prefix", "column0123456789_");
553
+ const int use_handler = arg.sh.conf.get_int("handler", 0);
554
+ const int sched_flag = arg.sh.conf.get_int("sched", 0);
555
+ const int use_in = arg.sh.conf.get_int("in", 0);
556
+ const int ssps = use_in ? 0 : arg.sh.conf.get_int("ssps", 0);
557
+ std::string flds = "v";
558
+ for (int i = 0; i < moreflds; ++i) {
559
+ char buf[1024];
560
+ snprintf(buf, sizeof(buf), ",%s%d", moreflds_prefix.c_str(), i);
561
+ flds += std::string(buf);
562
+ }
563
+ int connected = 0;
564
+ std::auto_ptr<auto_mysql_stmt> stmt;
565
+ string_buffer wbuf;
566
+ for (int i = 0; i < num; ++i) {
567
+ const double tm1 = gettimeofday_double();
568
+ const int flags = 0;
569
+ if (connected == 0) {
570
+ if (!mysql_real_connect(db, mysql_host.c_str(),
571
+ mysql_user.c_str(), mysql_user.empty() ? 0 : mysql_passwd.c_str(),
572
+ mysql_dbname.c_str(), mysql_port, 0, flags)) {
573
+ err = "failed to connect: " + std::string(mysql_error(db));
574
+ if (verbose >= 1) {
575
+ fprintf(stderr, "e=[%s]\n", err.c_str());
576
+ }
577
+ ++err_cnt;
578
+ return;
579
+ }
580
+ arg.sh.increment_conn(1);
581
+ }
582
+ int r = 0;
583
+ if (connected == 0 && use_handler) {
584
+ const char *const q = "handler hstest_table1 open";
585
+ r = mysql_real_query(db, q, strlen(q));
586
+ if (r != 0) {
587
+ err = 1;
588
+ }
589
+ }
590
+ if (connected == 0 && ssps) {
591
+ stmt.reset(new auto_mysql_stmt(db));
592
+ const char *const q = "select v from hstest_table1 where k = ?";
593
+ r = mysql_stmt_prepare(*stmt, q, strlen(q));
594
+ if (r != 0) {
595
+ fprintf(stderr, "ssps err\n");
596
+ ++err_cnt;
597
+ return;
598
+ }
599
+ }
600
+ connected = 1;
601
+ std::string result_str;
602
+ unsigned int err = 0;
603
+ unsigned int num_flds = 0, num_affected_rows = 0;
604
+ int got_data = 0;
605
+ char buf_query[16384];
606
+ int buf_query_len = 0;
607
+ int k = 0, v = 0;
608
+ {
609
+ double kf = 0, vf = 0;
610
+ drand48_r(&randbuf, &kf);
611
+ drand48_r(&randbuf, &vf);
612
+ k = int(kf * tablesize);
613
+ v = int(vf * tablesize);
614
+ #if 0
615
+ k = rand_r(&seed);
616
+ v = rand_r(&seed);
617
+ if (tablesize != 0) {
618
+ k %= tablesize;
619
+ }
620
+ #endif
621
+ if (op == 'G') {
622
+ if (use_handler) {
623
+ buf_query_len = snprintf(buf_query, sizeof(buf_query),
624
+ "handler hstest_table1 read `primary` = ( '%d' )", k);
625
+ // TODO: moreflds
626
+ } else if (ssps) {
627
+ //
628
+ } else if (use_in) {
629
+ wbuf.clear();
630
+ char *p = wbuf.make_space(1024);
631
+ int len = snprintf(p, 1024, "select %s from hstest_table1 where k in ('%d'", flds.c_str(), k);
632
+ wbuf.space_wrote(len);
633
+ for (int j = 1; j < use_in; ++j) {
634
+ /* generate more key */
635
+ drand48_r(&randbuf, &kf);
636
+ k = int(kf * tablesize);
637
+ p = wbuf.make_space(1024);
638
+ int len = snprintf(p, 1024, ", '%d'", k);
639
+ wbuf.space_wrote(len);
640
+ }
641
+ wbuf.append_literal(")");
642
+ } else {
643
+ buf_query_len = snprintf(buf_query, sizeof(buf_query),
644
+ "select %s from hstest_table1 where k = '%d'", flds.c_str(), k);
645
+ }
646
+ } else if (op == 'U') {
647
+ buf_query_len = snprintf(buf_query, sizeof(buf_query),
648
+ "update hstest_table1 set v = '%d_%d%s' where k = '%d'",
649
+ v, k, suffix.c_str(), k);
650
+ } else if (op == 'R') {
651
+ buf_query_len = snprintf(buf_query, sizeof(buf_query),
652
+ "replace into hstest_table1 values ('%d', 'v%d')", k, v);
653
+ // TODO: moreflds
654
+ }
655
+ }
656
+ if (r == 0) {
657
+ if (ssps) {
658
+ MYSQL_BIND bind[1] = { };
659
+ bind[0].buffer_type = MYSQL_TYPE_LONG;
660
+ bind[0].buffer = (char *)&k;
661
+ bind[0].is_null = 0;
662
+ bind[0].length = 0;
663
+ if (mysql_stmt_bind_param(*stmt, bind)) {
664
+ fprintf(stderr, "err: %s\n", mysql_stmt_error(*stmt));
665
+ ++err_cnt;
666
+ return;
667
+ }
668
+ r = mysql_stmt_execute(*stmt);
669
+ // fprintf(stderr, "stmt exec\n");
670
+ } else if (use_in) {
671
+ r = mysql_real_query(db, wbuf.begin(), wbuf.size());
672
+ } else {
673
+ r = mysql_real_query(db, buf_query, buf_query_len);
674
+ // fprintf(stderr, "real query\n");
675
+ }
676
+ ++query_cnt;
677
+ }
678
+ if (r != 0) {
679
+ err = 1;
680
+ } else if (ssps) {
681
+ if (verbose >= 0) {
682
+ char resbuf[1024];
683
+ unsigned long res_len = 0;
684
+ MYSQL_BIND bind[1] = { };
685
+ bind[0].buffer_type = MYSQL_TYPE_STRING;
686
+ bind[0].buffer = resbuf;
687
+ bind[0].buffer_length = sizeof(resbuf);
688
+ bind[0].length = &res_len;
689
+ if (mysql_stmt_bind_result(*stmt, bind)) {
690
+ fprintf(stderr, "err: %s\n", mysql_stmt_error(*stmt));
691
+ ++err_cnt;
692
+ return;
693
+ }
694
+ if (mysql_stmt_fetch(*stmt)) {
695
+ fprintf(stderr, "err: %s\n", mysql_stmt_error(*stmt));
696
+ ++err_cnt;
697
+ return;
698
+ }
699
+ if (!result_str.empty()) {
700
+ result_str += " ";
701
+ }
702
+ result_str += std::string(resbuf, res_len);
703
+ // fprintf(stderr, "SSPS RES: %s\n", result_str.c_str());
704
+ got_data = 1;
705
+ } else {
706
+ got_data = 1;
707
+ }
708
+ } else {
709
+ auto_mysql_res res(db);
710
+ if (res != 0) {
711
+ if (verbose >= 0) {
712
+ num_flds = mysql_num_fields(res);
713
+ MYSQL_ROW row = 0;
714
+ while ((row = mysql_fetch_row(res)) != 0) {
715
+ got_data += 1;
716
+ unsigned long *const lengths = mysql_fetch_lengths(res);
717
+ if (verbose >= 2) {
718
+ for (unsigned int i = 0; i < num_flds; ++i) {
719
+ if (!result_str.empty()) {
720
+ result_str += " ";
721
+ }
722
+ result_str += std::string(row[i], lengths[i]);
723
+ }
724
+ }
725
+ }
726
+ } else {
727
+ MYSQL_ROW row = 0;
728
+ while ((row = mysql_fetch_row(res)) != 0) {
729
+ got_data += 1;
730
+ }
731
+ }
732
+ } else {
733
+ if (mysql_field_count(db) == 0) {
734
+ num_affected_rows = mysql_affected_rows(db);
735
+ } else {
736
+ err = 1;
737
+ }
738
+ }
739
+ }
740
+ if (verbose >= 2 || (verbose >= 1 && err != 0)) {
741
+ if (err) {
742
+ ++err_cnt;
743
+ const char *const errstr = mysql_error(db);
744
+ fprintf(stderr, "e=[%s] a=%u q=[%s]\n", errstr,
745
+ num_affected_rows, buf_query);
746
+ } else {
747
+ fprintf(stderr, "a=%u q=[%s] r=[%s]\n", num_affected_rows, buf_query,
748
+ result_str.c_str());
749
+ }
750
+ }
751
+ if (err == 0) {
752
+ ++io_success_count;
753
+ if (num_affected_rows > 0 || got_data > 0) {
754
+ op_success_count += got_data;
755
+ } else {
756
+ if (verbose >= 1) {
757
+ fprintf(stderr, "k=%d numaff=%u gotdata=%d\n",
758
+ k, num_affected_rows, got_data);
759
+ }
760
+ }
761
+ arg.sh.increment_count();
762
+ }
763
+ if (!keep_connection) {
764
+ if (stmt.get() != 0) {
765
+ stmt.reset();
766
+ }
767
+ db.reset();
768
+ connected = 0;
769
+ }
770
+ const double tm2 = gettimeofday_double();
771
+ set_timing(tm2 - tm1);
772
+ sleep_if();
773
+ if (sched_flag) {
774
+ sched_yield();
775
+ }
776
+ }
777
+ if (verbose >= 1) {
778
+ fprintf(stderr, "thread finished (error_count=%llu)\n", err_cnt);
779
+ }
780
+ }
781
+
782
+ void
783
+ hstest_thread::test_10(int test_num)
784
+ {
785
+ const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
786
+ unsigned int seed = time(0) + arg.id + 1;
787
+ seed ^= arg.sh.conf.get_int("seed_xor", 0);
788
+ drand48_data randbuf;
789
+ srand48_r(seed, &randbuf);
790
+ std::string err;
791
+ int keepconn_count = 0;
792
+ const char op = arg.sh.op;
793
+ const int verbose = arg.sh.conf.get_int("verbose", 1);
794
+ const std::string suffix = arg.sh.conf.get_str("value_suffix", "upd");
795
+ const int tablesize = arg.sh.conf.get_int("tablesize", 10000);
796
+ const int firstkey = arg.sh.conf.get_int("firstkey", 0);
797
+ const int sched_flag = arg.sh.conf.get_int("sched", 0);
798
+ const int moreflds = arg.sh.conf.get_int("moreflds", 0);
799
+ const std::string dbname = arg.sh.conf.get_str("dbname", "hstest");
800
+ const std::string table = arg.sh.conf.get_str("table", "hstest_table1");
801
+ const std::string index = arg.sh.conf.get_str("index", "PRIMARY");
802
+ const std::string field = arg.sh.conf.get_str("field", "v");
803
+ const int use_in = arg.sh.conf.get_int("in", 0);
804
+ const std::string moreflds_prefix = arg.sh.conf.get_str(
805
+ "moreflds_prefix", "column0123456789_");
806
+ const int dump = arg.sh.dump;
807
+ const int nodup = arg.sh.conf.get_int("nodup", 0);
808
+ std::string moreflds_str;
809
+ for (int i = 0; i < moreflds; ++i) {
810
+ char sbuf[1024];
811
+ snprintf(sbuf, sizeof(sbuf), ",%s%d", moreflds_prefix.c_str(), i);
812
+ moreflds_str += std::string(sbuf);
813
+ }
814
+ string_buffer wbuf;
815
+ char rbuf[16384];
816
+ for (size_t i = 0; i < arg.sh.loop; ++i) {
817
+ int len = 0, rlen = 0, wlen = 0;
818
+ #if 0
819
+ const double tm1 = gettimeofday_double();
820
+ #endif
821
+ if (fd.get() < 0) {
822
+ if (socket_connect(fd, arg.sh.arg, err) != 0) {
823
+ fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
824
+ return;
825
+ }
826
+ char *wp = wbuf.make_space(1024);
827
+ len = snprintf(wp, 1024,
828
+ "P\t1\t%s\t%s\tPRIMARY\t%s%s\n", dbname.c_str(), table.c_str(),
829
+ field.c_str(), moreflds_str.c_str());
830
+ /* pst_num, db, table, index, retflds */
831
+ wbuf.space_wrote(len);
832
+ wlen = write(fd.get(), wbuf.begin(), len);
833
+ if (len != wlen) {
834
+ fprintf(stderr, "write: %d %d\n", len, wlen);
835
+ return;
836
+ }
837
+ wbuf.clear();
838
+ rlen = read(fd.get(), rbuf, sizeof(rbuf));
839
+ if (rlen <= 0 || rbuf[rlen - 1] != '\n') {
840
+ fprintf(stderr, "read: rlen=%d errno=%d\n", rlen, errno);
841
+ return;
842
+ }
843
+ if (rbuf[0] != '0') {
844
+ fprintf(stderr, "failed to open table\n");
845
+ return;
846
+ }
847
+ arg.sh.increment_conn(1);
848
+ }
849
+ const double tm1 = gettimeofday_double();
850
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
851
+ int k = 0, v = 0;
852
+ {
853
+ while (true) {
854
+ double kf = 0, vf = 0;
855
+ drand48_r(&randbuf, &kf);
856
+ drand48_r(&randbuf, &vf);
857
+ k = int(kf * tablesize) + firstkey;
858
+ v = int(vf * tablesize) + firstkey;
859
+ if (k - firstkey < arg.sh.keygen_size) {
860
+ volatile char *const ptr = arg.sh.keygen + (k - firstkey);
861
+ // int oldv = __sync_fetch_and_or(ptr, 1);
862
+ int oldv = *ptr;
863
+ *ptr += 1;
864
+ if (nodup && oldv != 0) {
865
+ if (dump) {
866
+ fprintf(stderr, "retry\n");
867
+ }
868
+ continue;
869
+ }
870
+ } else {
871
+ if (nodup) {
872
+ if (dump) {
873
+ fprintf(stderr, "retry2\n");
874
+ }
875
+ continue;
876
+ }
877
+ }
878
+ size_t len = 0;
879
+ if (op == 'G') {
880
+ if (use_in) {
881
+ char *wp = wbuf.make_space(1024);
882
+ len = snprintf(wp, 1024, "1\t=\t1\t\t%d\t0\t@\t0\t%d\t%d",
883
+ use_in, use_in, k);
884
+ wbuf.space_wrote(len);
885
+ for (int j = 1; j < use_in; ++j) {
886
+ drand48_r(&randbuf, &kf);
887
+ k = int(kf * tablesize) + firstkey;
888
+ char *wp = wbuf.make_space(1024);
889
+ len = snprintf(wp, 1024, "\t%d", k);
890
+ wbuf.space_wrote(len);
891
+ }
892
+ wbuf.append_literal("\n");
893
+ } else {
894
+ char *wp = wbuf.make_space(1024);
895
+ len = snprintf(wp, 1024, "1\t=\t1\t%d\n", k);
896
+ wbuf.space_wrote(len);
897
+ }
898
+ } else if (op == 'U') {
899
+ char *wp = wbuf.make_space(1024);
900
+ len = snprintf(wp, 1024,
901
+ "1\t=\t1\t%d\t1\t0\tU\t%d_%d%s\n", k, v, k, suffix.c_str());
902
+ wbuf.space_wrote(len);
903
+ }
904
+ break;
905
+ }
906
+ }
907
+ }
908
+ wlen = write(fd.get(), wbuf.begin(), wbuf.size());
909
+ if (wlen != wbuf.size()) {
910
+ fprintf(stderr, "write: %d %d\n", (int)wbuf.size(), wlen);
911
+ return;
912
+ }
913
+ wbuf.clear();
914
+ size_t read_cnt = 0;
915
+ size_t read_pos = 0;
916
+ while (read_cnt < arg.sh.pipe) {
917
+ rlen = read(fd.get(), rbuf + read_pos, sizeof(rbuf) - read_pos);
918
+ if (rlen <= 0) {
919
+ fprintf(stderr, "read: %d\n", rlen);
920
+ return;
921
+ }
922
+ read_pos += rlen;
923
+ while (true) {
924
+ const char *const nl = static_cast<const char *>(memchr(rbuf, '\n',
925
+ read_pos));
926
+ if (nl == 0) {
927
+ break;
928
+ }
929
+ ++read_cnt;
930
+ ++io_success_count;
931
+ const char *t1 = static_cast<const char *>(memchr(rbuf, '\t',
932
+ nl - rbuf));
933
+ if (t1 == 0) {
934
+ fprintf(stderr, "error \n");
935
+ break;
936
+ }
937
+ ++t1;
938
+ const char *t2 = static_cast<const char *>(memchr(t1, '\t',
939
+ nl - t1));
940
+ if (t2 == 0) {
941
+ if (verbose > 1) {
942
+ fprintf(stderr, "key: notfound \n");
943
+ }
944
+ break;
945
+ }
946
+ ++t2;
947
+ if (t1 == rbuf + 2 && rbuf[0] == '0') {
948
+ if (op == 'G') {
949
+ ++op_success_count;
950
+ arg.sh.increment_count();
951
+ } else if (op == 'U') {
952
+ const char *t3 = t2;
953
+ while (t3 != nl && t3[0] >= 0x10) {
954
+ ++t3;
955
+ }
956
+ if (t3 != t2 + 1 || t2[0] != '1') {
957
+ const std::string mess(t2, t3);
958
+ fprintf(stderr, "mod: %s\n", mess.c_str());
959
+ } else {
960
+ ++op_success_count;
961
+ arg.sh.increment_count();
962
+ if (arg.sh.dump && arg.sh.pipe == 1) {
963
+ fwrite(wbuf.begin(), wbuf.size(), 1, stderr);
964
+ }
965
+ }
966
+ }
967
+ } else {
968
+ const char *t3 = t2;
969
+ while (t3 != nl && t3[0] >= 0x10) {
970
+ ++t3;
971
+ }
972
+ const std::string mess(t2, t3);
973
+ fprintf(stderr, "err: %s\n", mess.c_str());
974
+ }
975
+ const size_t rest_size = rbuf + read_pos - (nl + 1);
976
+ if (rest_size != 0) {
977
+ memmove(rbuf, nl + 1, rest_size);
978
+ }
979
+ read_pos = rest_size;
980
+ }
981
+ }
982
+ if (!keep_connection) {
983
+ fd.reset();
984
+ arg.sh.increment_conn(-1);
985
+ } else if (keep_connection > 1 && ++keepconn_count > keep_connection) {
986
+ keepconn_count = 0;
987
+ fd.reset();
988
+ arg.sh.increment_conn(-1);
989
+ }
990
+ const double tm2 = gettimeofday_double();
991
+ set_timing(tm2 - tm1);
992
+ sleep_if();
993
+ if (sched_flag) {
994
+ sched_yield();
995
+ }
996
+ }
997
+ if (dump) {
998
+ fprintf(stderr, "done\n");
999
+ }
1000
+ }
1001
+
1002
+ void
1003
+ hstest_thread::sleep_if()
1004
+ {
1005
+ if (arg.sh.usleep) {
1006
+ struct timespec ts = {
1007
+ arg.sh.usleep / 1000000,
1008
+ (arg.sh.usleep % 1000000) * 1000
1009
+ };
1010
+ nanosleep(&ts, 0);
1011
+ }
1012
+ }
1013
+
1014
+ void
1015
+ hstest_thread::set_timing(double time_spent)
1016
+ {
1017
+ response_min = std::min(response_min, time_spent);
1018
+ response_max = std::max(response_max, time_spent);
1019
+ response_sum += time_spent;
1020
+ if (op_success_count != 0) {
1021
+ response_avg = response_sum / op_success_count;
1022
+ }
1023
+ }
1024
+
1025
+ void
1026
+ hstest_thread::test_11(int test_num)
1027
+ {
1028
+ const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
1029
+ const int tablesize = arg.sh.conf.get_int("tablesize", 0);
1030
+ unsigned int seed = arg.id;
1031
+ seed ^= arg.sh.conf.get_int("seed_xor", 0);
1032
+ std::string err;
1033
+ hstcpcli_ptr cli;
1034
+ for (size_t i = 0; i < arg.sh.loop; ++i) {
1035
+ if (cli.get() == 0) {
1036
+ cli = hstcpcli_i::create(arg.sh.arg);
1037
+ cli->request_buf_open_index(0, "hstest", "hstest_table1", "", "v");
1038
+ /* pst_num, db, table, index, retflds */
1039
+ if (cli->request_send() != 0) {
1040
+ fprintf(stderr, "reuqest_send: %s\n", cli->get_error().c_str());
1041
+ return;
1042
+ }
1043
+ size_t num_flds = 0;
1044
+ if (cli->response_recv(num_flds) != 0) {
1045
+ fprintf(stderr, "reuqest_recv: %s\n", cli->get_error().c_str());
1046
+ return;
1047
+ }
1048
+ cli->response_buf_remove();
1049
+ }
1050
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
1051
+ char buf[256];
1052
+ int k = 0, v = 0, len = 0;
1053
+ {
1054
+ k = rand_r(&seed);
1055
+ v = rand_r(&seed); /* unused */
1056
+ if (tablesize != 0) {
1057
+ k &= tablesize;
1058
+ }
1059
+ len = snprintf(buf, sizeof(buf), "%d", k);
1060
+ }
1061
+ const string_ref key(buf, len);
1062
+ const string_ref op("=", 1);
1063
+ cli->request_buf_exec_generic(0, op, &key, 1, 1, 0, string_ref(), 0, 0);
1064
+ }
1065
+ if (cli->request_send() != 0) {
1066
+ fprintf(stderr, "reuqest_send: %s\n", cli->get_error().c_str());
1067
+ return;
1068
+ }
1069
+ size_t read_cnt = 0;
1070
+ for (size_t j = 0; j < arg.sh.pipe; ++j) {
1071
+ size_t num_flds = 0;
1072
+ if (cli->response_recv(num_flds) != 0) {
1073
+ fprintf(stderr, "reuqest_recv: %s\n", cli->get_error().c_str());
1074
+ return;
1075
+ }
1076
+ {
1077
+ ++read_cnt;
1078
+ ++io_success_count;
1079
+ arg.sh.increment_count();
1080
+ {
1081
+ ++op_success_count;
1082
+ }
1083
+ }
1084
+ cli->response_buf_remove();
1085
+ }
1086
+ if (!keep_connection) {
1087
+ cli.reset();
1088
+ }
1089
+ }
1090
+ }
1091
+
1092
+ void
1093
+ hstest_thread::test_watch()
1094
+ {
1095
+ const int timelimit = arg.sh.conf.get_int("timelimit", 0);
1096
+ const int timelimit_offset = timelimit / 2;
1097
+ int loop = 0;
1098
+ double t1 = 0, t2 = 0;
1099
+ size_t cnt_t1 = 0, cnt_t2 = 0;
1100
+ size_t prev_cnt = 0;
1101
+ double now_f = 0;
1102
+ while (true) {
1103
+ sleep(1);
1104
+ const size_t cnt = arg.sh.count;
1105
+ const size_t df = cnt - prev_cnt;
1106
+ prev_cnt = cnt;
1107
+ const double now_prev = now_f;
1108
+ now_f = gettimeofday_double();
1109
+ if (now_prev != 0) {
1110
+ const double rps = static_cast<double>(df) / (now_f - now_prev);
1111
+ fprintf(stderr, "now: %zu cntdiff: %zu tdiff: %f rps: %f\n",
1112
+ static_cast<size_t>(now_f), df, now_f - now_prev, rps);
1113
+ }
1114
+ if (timelimit != 0) {
1115
+ if (arg.sh.wait_conn == 0 || arg.sh.conn_count >= arg.sh.wait_conn) {
1116
+ ++loop;
1117
+ }
1118
+ if (loop == timelimit_offset) {
1119
+ t1 = gettimeofday_double();
1120
+ cnt_t1 = cnt;
1121
+ arg.sh.enable_timing = 1;
1122
+ fprintf(stderr, "start timing\n");
1123
+ } else if (loop == timelimit_offset + timelimit) {
1124
+ t2 = gettimeofday_double();
1125
+ cnt_t2 = cnt;
1126
+ const size_t cnt_diff = cnt_t2 - cnt_t1;
1127
+ const double tdiff = t2 - t1;
1128
+ const double qps = cnt_diff / (tdiff != 0 ? tdiff : 1);
1129
+ fprintf(stderr, "(%f: %zu, %f: %zu), %10.5f qps\n",
1130
+ t1, cnt_t1, t2, cnt_t2, qps);
1131
+ size_t keycnt = 0;
1132
+ for (int i = 0; i < arg.sh.keygen_size; ++i) {
1133
+ if (arg.sh.keygen[i]) {
1134
+ ++keycnt;
1135
+ }
1136
+ }
1137
+ fprintf(stderr, "keygen=%zu\n", keycnt);
1138
+ break;
1139
+ }
1140
+ }
1141
+ }
1142
+ #if 0
1143
+ int loop = 0;
1144
+ double t1 = 0, t2 = 0;
1145
+ size_t cnt_t1 = 0, cnt_t2 = 0;
1146
+ size_t prev_cnt = 0;
1147
+ while (true) {
1148
+ sleep(1);
1149
+ const size_t cnt = arg.sh.count;
1150
+ const size_t df = cnt - prev_cnt;
1151
+ prev_cnt = cnt;
1152
+ const size_t now = time(0);
1153
+ fprintf(stderr, "%zu %zu\n", now, df);
1154
+ if (timelimit != 0) {
1155
+ ++loop;
1156
+ if (loop == timelimit_offset) {
1157
+ t1 = gettimeofday_double();
1158
+ cnt_t1 = cnt;
1159
+ } else if (loop == timelimit_offset + timelimit) {
1160
+ t2 = gettimeofday_double();
1161
+ cnt_t2 = cnt;
1162
+ const size_t cnt_diff = cnt_t2 - cnt_t1;
1163
+ const double tdiff = t2 - t1;
1164
+ const double qps = cnt_diff / (tdiff != 0 ? tdiff : 1);
1165
+ fprintf(stderr, "(%f: %zu, %f: %zu), %10.5f qps\n",
1166
+ t1, cnt_t1, t2, cnt_t2, qps);
1167
+ size_t keycnt = 0;
1168
+ for (int i = 0; i < arg.sh.keygen_size; ++i) {
1169
+ if (arg.sh.keygen[i]) {
1170
+ ++keycnt;
1171
+ }
1172
+ }
1173
+ fprintf(stderr, "keygen=%zu\n", keycnt);
1174
+ _exit(0);
1175
+ }
1176
+ }
1177
+ }
1178
+ #endif
1179
+ }
1180
+
1181
+ void
1182
+ hstest_thread::test_12(int test_num)
1183
+ {
1184
+ /* NOTE: num_threads should be 1 */
1185
+ /* create table hstest
1186
+ * ( k varchar(255) not null, v varchar(255) not null, primary key(k))
1187
+ * engine = innodb; */
1188
+ mysqltest_thread_initobj initobj;
1189
+ auto_mysql db;
1190
+ std::string err;
1191
+ unsigned long long err_cnt = 0;
1192
+ unsigned long long query_cnt = 0;
1193
+ #if 0
1194
+ my_bool reconnect = 0;
1195
+ if (mysql_options(db, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
1196
+ err = "mysql_options() failed";
1197
+ ++err_cnt;
1198
+ return;
1199
+ }
1200
+ #endif
1201
+ const std::string mysql_host = arg.sh.conf.get_str("host", "localhost");
1202
+ const int mysql_port = arg.sh.conf.get_int("mysqlport", 3306);
1203
+ const unsigned int num = arg.sh.loop;
1204
+ const size_t pipe = arg.sh.pipe;
1205
+ const std::string mysql_user = arg.sh.conf.get_str("mysqluser", "root");
1206
+ const std::string mysql_passwd = arg.sh.conf.get_str("mysqlpass", "");
1207
+ const std::string mysql_dbname = arg.sh.conf.get_str("db", "hstest");
1208
+ const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
1209
+ const int verbose = arg.sh.conf.get_int("verbose", 1);
1210
+ const int use_handler = arg.sh.conf.get_int("handler", 0);
1211
+ int connected = 0;
1212
+ unsigned int k = 0;
1213
+ string_buffer buf;
1214
+ for (unsigned int i = 0; i < num; ++i) {
1215
+ const int flags = 0;
1216
+ if (connected == 0 && !mysql_real_connect(db, mysql_host.c_str(),
1217
+ mysql_user.c_str(), mysql_user.empty() ? 0 : mysql_passwd.c_str(),
1218
+ mysql_dbname.c_str(), mysql_port, 0, flags)) {
1219
+ err = "failed to connect: " + std::string(mysql_error(db));
1220
+ if (verbose >= 1) {
1221
+ fprintf(stderr, "e=[%s]\n", err.c_str());
1222
+ }
1223
+ ++err_cnt;
1224
+ return;
1225
+ }
1226
+ int r = 0;
1227
+ if (connected == 0 && use_handler) {
1228
+ const char *const q = "handler hstest open";
1229
+ r = mysql_real_query(db, q, strlen(q));
1230
+ if (r != 0) {
1231
+ err = 1;
1232
+ }
1233
+ }
1234
+ connected = 1;
1235
+ std::string result_str;
1236
+ unsigned int err = 0;
1237
+ unsigned int num_flds = 0, num_affected_rows = 0;
1238
+ int got_data = 0;
1239
+ buf.clear();
1240
+ buf.append_literal("insert into hstest values ");
1241
+ for (size_t j = 0; j < pipe; ++j) {
1242
+ const unsigned int v = ~k;
1243
+ if (j != 0) {
1244
+ buf.append_literal(",");
1245
+ }
1246
+ char *wp = buf.make_space(64);
1247
+ int buf_query_len = snprintf(wp, 64, "('k%u', 'v%u')", k, v);
1248
+ buf.space_wrote(buf_query_len);
1249
+ ++k;
1250
+ }
1251
+ if (r == 0) {
1252
+ r = mysql_real_query(db, buf.begin(), buf.size());
1253
+ ++query_cnt;
1254
+ }
1255
+ if (r != 0) {
1256
+ err = 1;
1257
+ } else {
1258
+ auto_mysql_res res(db);
1259
+ if (res != 0) {
1260
+ if (verbose >= 0) {
1261
+ num_flds = mysql_num_fields(res);
1262
+ MYSQL_ROW row = 0;
1263
+ while ((row = mysql_fetch_row(res)) != 0) {
1264
+ got_data = 1;
1265
+ unsigned long *const lengths = mysql_fetch_lengths(res);
1266
+ if (verbose >= 2) {
1267
+ for (unsigned int i = 0; i < num_flds; ++i) {
1268
+ if (!result_str.empty()) {
1269
+ result_str += " ";
1270
+ }
1271
+ result_str += std::string(row[i], lengths[i]);
1272
+ }
1273
+ }
1274
+ }
1275
+ }
1276
+ } else {
1277
+ if (mysql_field_count(db) == 0) {
1278
+ num_affected_rows = mysql_affected_rows(db);
1279
+ } else {
1280
+ err = 1;
1281
+ }
1282
+ }
1283
+ }
1284
+ if (verbose >= 2 || (verbose >= 1 && err != 0)) {
1285
+ if (err) {
1286
+ ++err_cnt;
1287
+ const char *const errstr = mysql_error(db);
1288
+ fprintf(stderr, "e=[%s] a=%u q=[%s]\n", errstr,
1289
+ num_affected_rows, std::string(buf.begin(), buf.size()).c_str());
1290
+ } else {
1291
+ fprintf(stderr, "a=%u q=[%s] r=[%s]\n", num_affected_rows,
1292
+ std::string(buf.begin(), buf.size()).c_str(),
1293
+ result_str.c_str());
1294
+ }
1295
+ }
1296
+ if (err == 0) {
1297
+ ++io_success_count;
1298
+ if (num_affected_rows > 0 || got_data > 0) {
1299
+ ++op_success_count;
1300
+ }
1301
+ arg.sh.increment_count(pipe);
1302
+ }
1303
+ if (!keep_connection) {
1304
+ db.reset();
1305
+ connected = 0;
1306
+ }
1307
+ }
1308
+ if (verbose >= 1) {
1309
+ fprintf(stderr, "thread finished (error_count=%llu)\n", err_cnt);
1310
+ }
1311
+ }
1312
+
1313
+ void
1314
+ hstest_thread::test_21(int num)
1315
+ {
1316
+ /* fsync test */
1317
+ unsigned int id = arg.id;
1318
+ std::string err;
1319
+ #if 0
1320
+ if (socket_connect(fd, arg.sh.arg, err) != 0) {
1321
+ fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
1322
+ return;
1323
+ }
1324
+ #endif
1325
+ auto_file logfd;
1326
+ char fname[1024];
1327
+ snprintf(fname, sizeof(fname), "synctest_%u", id);
1328
+ int open_flags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND;
1329
+ logfd.reset(open(fname, open_flags, 0644));
1330
+ if (logfd.get() < 0) {
1331
+ fprintf(stderr, "open: %s: %d %s\n", fname, errno, strerror(errno));
1332
+ return;
1333
+ }
1334
+ char buf[1024];
1335
+ unsigned long long count = 0;
1336
+ while (true) {
1337
+ snprintf(buf, sizeof(buf), "%u %llu\n", id, count);
1338
+ const size_t len = strlen(buf);
1339
+ if (write(logfd.get(), buf, len) != (ssize_t)len) {
1340
+ fprintf(stderr, "write: %s: %d %s\n", fname, errno, strerror(errno));
1341
+ return;
1342
+ }
1343
+ #if 0
1344
+ if (write(fd.get(), buf, len) != (ssize_t)len) {
1345
+ fprintf(stderr, "write(sock): %d %s\n", errno, strerror(errno));
1346
+ return;
1347
+ }
1348
+ #endif
1349
+ if (fdatasync(logfd.get()) != 0) {
1350
+ fprintf(stderr, "fsync: %s: %d %s\n", fname, errno, strerror(errno));
1351
+ return;
1352
+ }
1353
+ ++count;
1354
+ ++op_success_count;
1355
+ arg.sh.increment_count();
1356
+ }
1357
+ }
1358
+
1359
+ void
1360
+ hstest_thread::test_22(int num)
1361
+ {
1362
+ /* dd if=/dev/zero of=dummy.dat bs=1024M count=100 */
1363
+ unsigned int id = arg.id;
1364
+ std::string err;
1365
+ auto_file filefd;
1366
+ char fname[1024];
1367
+ snprintf(fname, sizeof(fname), "dummy.dat");
1368
+ int open_flags = O_RDONLY | O_DIRECT;
1369
+ filefd.reset(open(fname, open_flags, 0644));
1370
+ if (filefd.get() < 0) {
1371
+ fprintf(stderr, "open: %s: %d %s\n", fname, errno, strerror(errno));
1372
+ return;
1373
+ }
1374
+ char buf_x[4096 * 2];
1375
+ char *const buf = (char *)(size_t(buf_x + 4096) / 4096 * 4096);
1376
+ unsigned long long count = 0;
1377
+ drand48_data randbuf;
1378
+ unsigned long long seed = time(0);
1379
+ seed *= 10;
1380
+ seed += id;
1381
+ srand48_r(seed, &randbuf);
1382
+ for (unsigned int i = 0; i < arg.sh.loop; ++i) {
1383
+ double kf = 0;
1384
+ drand48_r(&randbuf, &kf);
1385
+ kf *= (209715200 / 1);
1386
+ // fprintf(stderr, "v=%f\n", kf);
1387
+ off_t v = static_cast<off_t>(kf);
1388
+ v %= (209715200 / 1);
1389
+ v *= (512 * 1);
1390
+ const double tm1 = gettimeofday_double();
1391
+ const ssize_t r = pread(filefd.get(), buf, (512 * 1), v);
1392
+ const double tm2 = gettimeofday_double();
1393
+ if (r < 0) {
1394
+ fprintf(stderr, "pread: %s: %d %s\n", fname, errno, strerror(errno));
1395
+ return;
1396
+ }
1397
+ ++count;
1398
+ ++op_success_count;
1399
+ arg.sh.increment_count();
1400
+ set_timing(tm2 - tm1);
1401
+ }
1402
+ }
1403
+
1404
+ void
1405
+ hstest_thread::operator ()()
1406
+ {
1407
+ if (arg.watch_flag) {
1408
+ return test_watch();
1409
+ }
1410
+ int test_num = arg.sh.conf.get_int("test", 1);
1411
+ if (test_num == 1) {
1412
+ test_1();
1413
+ } else if (test_num == 2 || test_num == 3) {
1414
+ test_2_3(test_num);
1415
+ } else if (test_num == 4 || test_num == 5) {
1416
+ test_4_5(test_num);
1417
+ } else if (test_num == 6) {
1418
+ test_6(test_num);
1419
+ } else if (test_num == 7) {
1420
+ test_7(test_num);
1421
+ } else if (test_num == 8) {
1422
+ test_8(test_num);
1423
+ } else if (test_num == 9) {
1424
+ test_9(test_num);
1425
+ } else if (test_num == 10) {
1426
+ test_10(test_num);
1427
+ } else if (test_num == 11) {
1428
+ test_11(test_num);
1429
+ } else if (test_num == 12) {
1430
+ test_12(test_num);
1431
+ } else if (test_num == 21) {
1432
+ test_21(test_num);
1433
+ } else if (test_num == 22) {
1434
+ test_22(test_num);
1435
+ }
1436
+ const int halt = arg.sh.conf.get_int("halt", 0);
1437
+ if (halt) {
1438
+ fprintf(stderr, "thread halted\n");
1439
+ while (true) {
1440
+ sleep(100000);
1441
+ }
1442
+ }
1443
+ fprintf(stderr, "thread finished\n");
1444
+ }
1445
+
1446
+ int
1447
+ hstest_main(int argc, char **argv)
1448
+ {
1449
+ ignore_sigpipe();
1450
+ hstest_shared shared;
1451
+ parse_args(argc, argv, shared.conf);
1452
+ shared.conf["port"] = shared.conf["hsport"];
1453
+ shared.arg.set(shared.conf);
1454
+ shared.loop = shared.conf.get_int("num", 1000);
1455
+ shared.pipe = shared.conf.get_int("pipe", 1);
1456
+ shared.verbose = shared.conf.get_int("verbose", 1);
1457
+ const int tablesize = shared.conf.get_int("tablesize", 0);
1458
+ std::vector<char> keygen(tablesize);
1459
+ shared.keygen = &keygen[0];
1460
+ shared.keygen_size = tablesize;
1461
+ shared.usleep = shared.conf.get_int("usleep", 0);
1462
+ shared.dump = shared.conf.get_int("dump", 0);
1463
+ shared.num_threads = shared.conf.get_int("num_threads", 10);
1464
+ shared.wait_conn = shared.conf.get_int("wait_conn", 0);
1465
+ const std::string op = shared.conf.get_str("op", "G");
1466
+ if (op.size() > 0) {
1467
+ shared.op = op[0];
1468
+ }
1469
+ #if 0
1470
+ const int localdb_flag = shared.conf.get_int("local", 0);
1471
+ if (localdb_flag) {
1472
+ shared.localdb = database_i::create(shared.conf);
1473
+ }
1474
+ #endif
1475
+ const int num_thrs = shared.num_threads;
1476
+ typedef thread<hstest_thread> thread_type;
1477
+ typedef std::auto_ptr<thread_type> thread_ptr;
1478
+ typedef auto_ptrcontainer< std::vector<thread_type *> > thrs_type;
1479
+ thrs_type thrs;
1480
+ for (int i = 0; i < num_thrs; ++i) {
1481
+ const hstest_thread::arg_type arg(i, shared, false);
1482
+ thread_ptr thr(new thread<hstest_thread>(arg));
1483
+ thrs.push_back_ptr(thr);
1484
+ }
1485
+ for (size_t i = 0; i < thrs.size(); ++i) {
1486
+ thrs[i]->start();
1487
+ }
1488
+ thread_ptr watch_thread;
1489
+ const int timelimit = shared.conf.get_int("timelimit", 0);
1490
+ {
1491
+ const hstest_thread::arg_type arg(0, shared, true);
1492
+ watch_thread = thread_ptr(new thread<hstest_thread>(arg));
1493
+ watch_thread->start();
1494
+ }
1495
+ size_t iocnt = 0, opcnt = 0;
1496
+ double respmin = 999999, respmax = 0;
1497
+ double respsum = 0;
1498
+ if (timelimit != 0) {
1499
+ watch_thread->join();
1500
+ }
1501
+ for (size_t i = 0; i < thrs.size(); ++i) {
1502
+ if (timelimit == 0) {
1503
+ thrs[i]->join();
1504
+ }
1505
+ iocnt += (*thrs[i])->io_success_count;
1506
+ opcnt += (*thrs[i])->op_success_count;
1507
+ respmin = std::min(respmin, (*thrs[i])->response_min);
1508
+ respmax = std::max(respmax, (*thrs[i])->response_max);
1509
+ respsum += (*thrs[i])->response_sum;
1510
+ }
1511
+ fprintf(stderr, "io_success_count=%zu op_success_count=%zu\n", iocnt, opcnt);
1512
+ fprintf(stderr, "respmin=%f respmax=%f respsum=%f respavg=%f\n",
1513
+ respmin, respmax, respsum, respsum / opcnt);
1514
+ size_t keycnt = 0;
1515
+ for (size_t i = 0; i < keygen.size(); ++i) {
1516
+ if (keygen[i]) {
1517
+ ++keycnt;
1518
+ }
1519
+ }
1520
+ fprintf(stderr, "keycnt=%zu\n", keycnt);
1521
+ _exit(0);
1522
+ return 0;
1523
+ }
1524
+
1525
+ };
1526
+
1527
+ int
1528
+ main(int argc, char **argv)
1529
+ {
1530
+ return dena::hstest_main(argc, argv);
1531
+ }
1532
+