PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/src/grntest.c

https://github.com/darashi/groonga
C | 3166 lines | 2783 code | 301 blank | 82 comment | 599 complexity | 50263db86204365b5f486ae06e68be0a MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /* -*- c-basic-offset: 2 -*- */
  2. /*
  3. Copyright(C) 2010-2011 Brazil
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License version 2.1 as published by the Free Software Foundation.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with this library; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14. */
  15. #ifdef HAVE_CONFIG_H
  16. #include "config.h"
  17. #endif /* HAVE_CONFIG_H */
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #ifdef HAVE_SYS_WAIT_H
  25. #include <sys/wait.h>
  26. #endif /* HAVE_SYS_WAIT_H */
  27. #ifdef HAVE_SYS_SOCKET_H
  28. #include <sys/socket.h>
  29. #endif /* HAVE_SYS_SOCKET_H */
  30. #ifdef HAVE_NETINET_IN_H
  31. #include <netinet/in.h>
  32. #endif /* HAVE_NETINET_IN_H */
  33. #include "lib/str.h"
  34. #include "lib/com.h"
  35. #include "lib/db.h"
  36. #ifdef WIN32
  37. #include <windows.h>
  38. #include <stddef.h>
  39. #else
  40. #include <sys/param.h>
  41. #include <sys/utsname.h>
  42. #include <sys/statvfs.h>
  43. #include <libgen.h>
  44. #endif /* WIN32 */
  45. /*
  46. #define DEBUG_FTP
  47. #define DEBUG_HTTP
  48. */
  49. #define FTPUSER "anonymous"
  50. #define FTPPASSWD "grntest"
  51. #define FTPSERVER "ftp.groonga.org"
  52. #define FTPBUF 20000
  53. #define DEFAULT_PORT 10041
  54. #define DEFAULT_DEST "localhost"
  55. #define OUT_JSON 0
  56. #define OUT_TSV 1
  57. static int grntest_outtype = OUT_JSON;
  58. static grn_critical_section grntest_cs;
  59. static int grntest_stop_flag = 0;
  60. static int grntest_detail_on = 0;
  61. static int grntest_remote_mode = 0;
  62. static int grntest_localonly_mode = 0;
  63. static int grntest_owndb_mode = 0;
  64. static int grntest_onmemory_mode = 0;
  65. static grn_bool grntest_ftp_mode = GRN_FALSE;
  66. #define TMPFILE "_grntest.tmp"
  67. static grn_ctx grntest_server_context;
  68. static FILE *grntest_log_file;
  69. #define OS_LINUX64 "LINUX64"
  70. #define OS_LINUX32 "LINUX32"
  71. #define OS_WINDOWS64 "WINDOWS64"
  72. #define OS_WINDOWS32 "WINDOWS32"
  73. #ifdef WIN32
  74. typedef SOCKET socket_t;
  75. #define SOCKETERROR INVALID_SOCKET
  76. #define socketclose closesocket
  77. static const char *groonga_path = "groonga.exe";
  78. static PROCESS_INFORMATION grntest_pi;
  79. #else
  80. static pid_t grntest_server_id = 0;
  81. typedef int socket_t;
  82. #define socketclose close
  83. #define SOCKETERROR -1
  84. static const char *groonga_path = "groonga";
  85. #endif /* WIN32 */
  86. static const char *groonga_protocol = "gqtp";
  87. static char *grntest_osinfo;
  88. static int grntest_sigint = 0;
  89. static grn_obj *grntest_db = NULL;
  90. #define MAX_CON_JOB 10
  91. #define MAX_CON 64
  92. #define BUF_LEN 1024
  93. #define MAX_PATH_LEN 256
  94. #define J_DO_LOCAL 1 /* do_local */
  95. #define J_DO_GQTP 2 /* do_gqtp */
  96. #define J_DO_HTTP 3 /* do_http */
  97. #define J_REP_LOCAL 4 /* rep_local */
  98. #define J_REP_GQTP 5 /* rep_gqtp */
  99. #define J_REP_HTTP 6 /* rep_http */
  100. #define J_OUT_LOCAL 7 /* out_local */
  101. #define J_OUT_GQTP 8 /* out_gqtp */
  102. #define J_OUT_HTTP 9 /* out_http */
  103. #define J_TEST_LOCAL 10 /* test_local */
  104. #define J_TEST_GQTP 11 /* test_gqtp */
  105. #define J_TEST_HTTP 12 /* test_http */
  106. static char grntest_username[BUF_LEN];
  107. static char grntest_scriptname[BUF_LEN];
  108. static char grntest_date[BUF_LEN];
  109. static char grntest_serverhost[BUF_LEN];
  110. static int grntest_serverport;
  111. static const char *grntest_dbpath;
  112. struct job {
  113. char jobname[BUF_LEN];
  114. char commandfile[BUF_LEN];
  115. int qnum;
  116. int jobtype;
  117. int concurrency;
  118. int ntimes;
  119. int done;
  120. long long int max;
  121. long long int min;
  122. FILE *outputlog;
  123. FILE *inputlog;
  124. char logfile[BUF_LEN];
  125. };
  126. struct task {
  127. char *file;
  128. grn_obj *commands;
  129. int jobtype;
  130. int ntimes;
  131. int qnum;
  132. int job_id;
  133. long long int max;
  134. long long int min;
  135. socket_t http_socket;
  136. grn_obj http_response;
  137. };
  138. static struct task grntest_task[MAX_CON];
  139. static struct job grntest_job[MAX_CON];
  140. static int grntest_jobdone;
  141. static int grntest_jobnum;
  142. static grn_ctx grntest_ctx[MAX_CON];
  143. static grn_obj *grntest_owndb[MAX_CON];
  144. static grn_obj grntest_starttime, grntest_jobs_start;
  145. static int
  146. grntest_atoi(const char *str, const char *end, const char **rest)
  147. {
  148. while (grn_isspace(str, GRN_ENC_UTF8) == 1) {
  149. str++;
  150. }
  151. return grn_atoi(str, end, rest);
  152. }
  153. static int
  154. out_p(int jobtype)
  155. {
  156. if (jobtype == J_OUT_LOCAL) {
  157. return 1;
  158. }
  159. if (jobtype == J_OUT_GQTP) {
  160. return 1;
  161. }
  162. if (jobtype == J_OUT_HTTP) {
  163. return 1;
  164. }
  165. return 0;
  166. }
  167. static int
  168. test_p(int jobtype)
  169. {
  170. if (jobtype == J_TEST_LOCAL) {
  171. return 1;
  172. }
  173. if (jobtype == J_TEST_GQTP) {
  174. return 1;
  175. }
  176. if (jobtype == J_TEST_HTTP) {
  177. return 1;
  178. }
  179. return 0;
  180. }
  181. static int
  182. report_p(int jobtype)
  183. {
  184. if (jobtype == J_REP_LOCAL) {
  185. return 1;
  186. }
  187. if (jobtype == J_REP_GQTP) {
  188. return 1;
  189. }
  190. if (jobtype == J_REP_HTTP) {
  191. return 1;
  192. }
  193. return 0;
  194. }
  195. static int
  196. gqtp_p(int jobtype)
  197. {
  198. if (jobtype == J_DO_GQTP) {
  199. return 1;
  200. }
  201. if (jobtype == J_REP_GQTP) {
  202. return 1;
  203. }
  204. if (jobtype == J_OUT_GQTP) {
  205. return 1;
  206. }
  207. if (jobtype == J_TEST_GQTP) {
  208. return 1;
  209. }
  210. return 0;
  211. }
  212. static int
  213. http_p(int jobtype)
  214. {
  215. if (jobtype == J_DO_HTTP) {
  216. return 1;
  217. }
  218. if (jobtype == J_REP_HTTP) {
  219. return 1;
  220. }
  221. if (jobtype == J_OUT_HTTP) {
  222. return 1;
  223. }
  224. if (jobtype == J_TEST_HTTP) {
  225. return 1;
  226. }
  227. return 0;
  228. }
  229. static int
  230. error_exit_in_thread(intptr_t code)
  231. {
  232. fprintf(stderr,
  233. "Fatal error! Check script file or database!: %ld\n", (long)code);
  234. fflush(stderr);
  235. CRITICAL_SECTION_ENTER(grntest_cs);
  236. grntest_stop_flag = 1;
  237. CRITICAL_SECTION_LEAVE(grntest_cs);
  238. #ifdef WIN32
  239. _endthreadex(code);
  240. #else
  241. pthread_exit((void *)code);
  242. #endif /* WIN32 */
  243. return 0;
  244. }
  245. static void
  246. escape_command(grn_ctx *ctx, char *in, int ilen, grn_obj *escaped_command)
  247. {
  248. int i = 0;
  249. while (i < ilen) {
  250. if ((in[i] == '\\') || (in[i] == '\"') || (in[i] == '/')) {
  251. GRN_TEXT_PUTC(ctx, escaped_command, '\\');
  252. GRN_TEXT_PUTC(ctx, escaped_command, in[i]);
  253. i++;
  254. } else {
  255. switch (in[i]) {
  256. case '\b':
  257. GRN_TEXT_PUTS(ctx, escaped_command, "\\b");
  258. i++;
  259. break;
  260. case '\f':
  261. GRN_TEXT_PUTS(ctx, escaped_command, "\\f");
  262. i++;
  263. break;
  264. case '\n':
  265. GRN_TEXT_PUTS(ctx, escaped_command, "\\n");
  266. i++;
  267. break;
  268. case '\r':
  269. GRN_TEXT_PUTS(ctx, escaped_command, "\\r");
  270. i++;
  271. break;
  272. case '\t':
  273. GRN_TEXT_PUTS(ctx, escaped_command, "\\t");
  274. i++;
  275. break;
  276. default:
  277. GRN_TEXT_PUTC(ctx, escaped_command, in[i]);
  278. i++;
  279. break;
  280. }
  281. }
  282. }
  283. GRN_TEXT_PUTC(ctx, escaped_command, '\0');
  284. }
  285. static int
  286. report_command(grn_ctx *ctx, char *command, char *ret, int task_id,
  287. grn_obj *start_time, grn_obj *end_time)
  288. {
  289. int i, len, clen;
  290. long long int start, end;
  291. grn_obj result, escaped_command;
  292. GRN_TEXT_INIT(&result, 0);
  293. if (strncmp(ret, "[[", 2) == 0) {
  294. i = 2;
  295. len = 1;
  296. while (ret[i] != ']') {
  297. i++;
  298. len++;
  299. if (ret[i] == '\0') {
  300. fprintf(stderr, "Error results:command=[%s]\n", command);
  301. error_exit_in_thread(3);
  302. }
  303. }
  304. len++;
  305. grn_text_esc(ctx, &result, ret + 1, len);
  306. } else {
  307. grn_text_esc(ctx, &result, ret, strlen(ret));
  308. }
  309. start = GRN_TIME_VALUE(start_time) - GRN_TIME_VALUE(&grntest_starttime);
  310. end = GRN_TIME_VALUE(end_time) - GRN_TIME_VALUE(&grntest_starttime);
  311. clen = strlen(command);
  312. GRN_TEXT_INIT(&escaped_command, 0);
  313. escape_command(ctx, command, clen, &escaped_command);
  314. if (grntest_outtype == OUT_TSV) {
  315. fprintf(grntest_log_file, "report\t%d\t%s\t%" GRN_FMT_LLD "\t%" GRN_FMT_LLD "\t%.*s\n",
  316. task_id, GRN_TEXT_VALUE(&escaped_command), start, end,
  317. (int)GRN_TEXT_LEN(&result), GRN_TEXT_VALUE(&result));
  318. } else {
  319. fprintf(grntest_log_file, "[%d, \"%s\", %" GRN_FMT_LLD ", %" GRN_FMT_LLD ", %.*s],\n",
  320. task_id, GRN_TEXT_VALUE(&escaped_command), start, end,
  321. (int)GRN_TEXT_LEN(&result), GRN_TEXT_VALUE(&result));
  322. }
  323. fflush(grntest_log_file);
  324. GRN_OBJ_FIN(ctx, &escaped_command);
  325. GRN_OBJ_FIN(ctx, &result);
  326. return 0;
  327. }
  328. static int
  329. output_result_final(grn_ctx *ctx, int qnum)
  330. {
  331. grn_obj end_time;
  332. long long int latency, self;
  333. double sec, qps;
  334. GRN_TIME_INIT(&end_time, 0);
  335. GRN_TIME_NOW(ctx, &end_time);
  336. latency = GRN_TIME_VALUE(&end_time) - GRN_TIME_VALUE(&grntest_starttime);
  337. self = latency;
  338. sec = self / (double)1000000;
  339. qps = (double)qnum / sec;
  340. if (grntest_outtype == OUT_TSV) {
  341. fprintf(grntest_log_file, "total\t%" GRN_FMT_LLD "\t%f\t%d\n", latency, qps, qnum);
  342. } else {
  343. fprintf(grntest_log_file,
  344. "{\"total\": %" GRN_FMT_LLD ", \"qps\": %f, \"queries\": %d}]\n", latency, qps, qnum);
  345. }
  346. grn_obj_close(ctx, &end_time);
  347. return 0;
  348. }
  349. static int
  350. output_sysinfo(char *sysinfo)
  351. {
  352. if (grntest_outtype == OUT_TSV) {
  353. fprintf(grntest_log_file, "%s", sysinfo);
  354. } else {
  355. fprintf(grntest_log_file, "[%s\n", sysinfo);
  356. }
  357. return 0;
  358. }
  359. /* #define ENABLE_ERROR_REPORT 1 */
  360. #ifdef ENABLE_ERROR_REPORT
  361. static int
  362. error_command(grn_ctx *ctx, char *command, int task_id)
  363. {
  364. fprintf(stderr, "error!:command=[%s] task_id = %d\n", command, task_id);
  365. fflush(stderr);
  366. error_exit_in_thread(1);
  367. return 0;
  368. }
  369. #endif
  370. static void
  371. normalize_output(char *output, int length,
  372. char **normalized_output, int *normalized_length)
  373. {
  374. int i;
  375. *normalized_output = NULL;
  376. *normalized_length = length;
  377. for (i = 0; i < length; i++) {
  378. if (!strncmp(output + i, "],", 2)) {
  379. *normalized_output = output + i + 2;
  380. *normalized_length -= i + 2;
  381. break;
  382. }
  383. }
  384. if (!*normalized_output) {
  385. if (length > 2 && strncmp(output + length - 2, "]]", 2)) {
  386. *normalized_output = output + length;
  387. *normalized_length = 0;
  388. } else {
  389. *normalized_output = output;
  390. }
  391. }
  392. }
  393. static grn_bool
  394. same_result_p(char *expect, int expected_length, char *result, int result_length)
  395. {
  396. char *normalized_expected, *normalized_result;
  397. int normalized_expected_length, normalized_result_length;
  398. normalize_output(expect, expected_length,
  399. &normalized_expected, &normalized_expected_length);
  400. normalize_output(result, result_length,
  401. &normalized_result, &normalized_result_length);
  402. return((normalized_expected_length == normalized_result_length) &&
  403. strncmp(normalized_expected, normalized_result,
  404. normalized_expected_length) == 0);
  405. }
  406. static socket_t
  407. open_socket(char *host, int port)
  408. {
  409. socket_t sock;
  410. struct hostent *servhost;
  411. struct sockaddr_in server;
  412. u_long inaddr;
  413. int ret;
  414. servhost = gethostbyname(host);
  415. if (servhost == NULL){
  416. fprintf(stderr, "Bad hostname [%s]\n", host);
  417. return -1;
  418. }
  419. inaddr = *(u_long*)(servhost->h_addr_list[0]);
  420. memset(&server, 0, sizeof(struct sockaddr_in));
  421. server.sin_family = AF_INET;
  422. server.sin_port = htons(port);
  423. server.sin_addr = *(struct in_addr*)&inaddr;
  424. sock = socket(AF_INET, SOCK_STREAM, 0);
  425. if (sock == -1) {
  426. fprintf(stderr, "socket error\n");
  427. return -1;
  428. }
  429. ret = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
  430. if (ret == -1) {
  431. fprintf(stderr, "connect error\n");
  432. return -1;
  433. }
  434. return sock;
  435. }
  436. static int
  437. write_to_server(socket_t socket, char *buf)
  438. {
  439. #ifdef DEBUG_FTP
  440. fprintf(stderr, "send:%s", buf);
  441. #endif
  442. send(socket, buf, strlen(buf), 0);
  443. return 0;
  444. }
  445. #define OUTPUT_TYPE "output_type"
  446. #define OUTPUT_TYPE_LEN (sizeof(OUTPUT_TYPE) - 1)
  447. static void
  448. command_line_to_uri_path(grn_ctx *ctx, grn_obj *uri, char *command)
  449. {
  450. char tok_type;
  451. int offset = 0, have_key = 0;
  452. const char *p, *e, *v;
  453. grn_obj buf, *expr = NULL;
  454. grn_expr_var *vars;
  455. unsigned nvars;
  456. GRN_TEXT_INIT(&buf, 0);
  457. p = command;
  458. e = command + strlen(command);
  459. p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type);
  460. if ((expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)))) {
  461. grn_obj params, output_type;
  462. GRN_TEXT_INIT(&params, 0);
  463. GRN_TEXT_INIT(&output_type, 0);
  464. vars = ((grn_proc *)expr)->vars;
  465. nvars = ((grn_proc *)expr)->nvars;
  466. GRN_TEXT_PUTS(ctx, uri, "/d/");
  467. GRN_TEXT_PUT(ctx, uri, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
  468. while (p < e) {
  469. GRN_BULK_REWIND(&buf);
  470. p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type);
  471. v = GRN_TEXT_VALUE(&buf);
  472. switch (tok_type) {
  473. case GRN_TOK_VOID :
  474. p = e;
  475. break;
  476. case GRN_TOK_SYMBOL :
  477. if (GRN_TEXT_LEN(&buf) > 2 && v[0] == '-' && v[1] == '-') {
  478. int l = GRN_TEXT_LEN(&buf) - 2;
  479. v += 2;
  480. if (l == OUTPUT_TYPE_LEN && !memcmp(v, OUTPUT_TYPE, OUTPUT_TYPE_LEN)) {
  481. GRN_BULK_REWIND(&output_type);
  482. p = grn_text_unesc_tok(ctx, &output_type, p, e, &tok_type);
  483. break;
  484. }
  485. if (GRN_TEXT_LEN(&params)) {
  486. GRN_TEXT_PUTS(ctx, &params, "&");
  487. }
  488. grn_text_urlenc(ctx, &params, v, l);
  489. have_key = 1;
  490. break;
  491. }
  492. /* fallthru */
  493. case GRN_TOK_STRING :
  494. case GRN_TOK_QUOTE :
  495. if (!have_key) {
  496. if (offset < nvars) {
  497. if (GRN_TEXT_LEN(&params)) {
  498. GRN_TEXT_PUTS(ctx, &params, "&");
  499. }
  500. grn_text_urlenc(ctx, &params,
  501. vars[offset].name, vars[offset].name_size);
  502. offset++;
  503. }
  504. }
  505. GRN_TEXT_PUTS(ctx, &params, "=");
  506. grn_text_urlenc(ctx, &params, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
  507. have_key = 0;
  508. break;
  509. }
  510. }
  511. GRN_TEXT_PUTS(ctx, uri, ".");
  512. if (GRN_TEXT_LEN(&output_type)) {
  513. GRN_TEXT_PUT(ctx, uri,
  514. GRN_TEXT_VALUE(&output_type), GRN_TEXT_LEN(&output_type));
  515. } else {
  516. GRN_TEXT_PUTS(ctx, uri, "json");
  517. }
  518. if (GRN_TEXT_LEN(&params) > 0) {
  519. GRN_TEXT_PUTS(ctx, uri, "?");
  520. GRN_TEXT_PUT(ctx, uri, GRN_TEXT_VALUE(&params), GRN_TEXT_LEN(&params));
  521. }
  522. GRN_OBJ_FIN(ctx, &params);
  523. GRN_OBJ_FIN(ctx, &output_type);
  524. }
  525. GRN_OBJ_FIN(ctx, &buf);
  526. }
  527. static void
  528. command_send_http(grn_ctx *ctx, char *command, int type, int task_id)
  529. {
  530. socket_t http_socket;
  531. grn_obj buf;
  532. http_socket = open_socket(grntest_serverhost, grntest_serverport);
  533. if (http_socket == SOCKETERROR) {
  534. fprintf(stderr, "failed to connect to groonga at %s:%d via HTTP: ",
  535. grntest_serverhost, grntest_serverport);
  536. #ifdef WIN32
  537. fprintf(stderr, "%d\n", GetLastError());
  538. #else
  539. fprintf(stderr, "%s\n", strerror(errno));
  540. #endif
  541. error_exit_in_thread(100);
  542. }
  543. grntest_task[task_id].http_socket = http_socket;
  544. GRN_BULK_REWIND(&grntest_task[task_id].http_response);
  545. GRN_TEXT_INIT(&buf, 0);
  546. GRN_TEXT_PUTS(ctx, &buf, "GET ");
  547. if (strncmp(command, "/d/", 3) == 0) {
  548. GRN_TEXT_PUTS(ctx, &buf, command);
  549. } else {
  550. command_line_to_uri_path(ctx, &buf, command);
  551. }
  552. #ifdef DEBUG_HTTP
  553. fprintf(stderr, "command: <%s>\n", command);
  554. fprintf(stderr, "path: <%.*s>\n",
  555. (int)GRN_TEXT_LEN(&buf), GRN_TEXT_VALUE(&buf));
  556. #endif
  557. GRN_TEXT_PUTS(ctx, &buf, " HTTP/1.1\r\n");
  558. GRN_TEXT_PUTS(ctx, &buf, "Host: ");
  559. GRN_TEXT_PUTS(ctx, &buf, grntest_serverhost);
  560. GRN_TEXT_PUTS(ctx, &buf, "\r\n");
  561. GRN_TEXT_PUTS(ctx, &buf, "User-Agent: grntest/");
  562. GRN_TEXT_PUTS(ctx, &buf, grn_get_version());
  563. GRN_TEXT_PUTS(ctx, &buf, "\r\n");
  564. GRN_TEXT_PUTS(ctx, &buf, "Connection: close\r\n");
  565. GRN_TEXT_PUTS(ctx, &buf, "\r\n");
  566. GRN_TEXT_PUTC(ctx, &buf, '\0');
  567. write_to_server(http_socket, GRN_TEXT_VALUE(&buf));
  568. GRN_OBJ_FIN(ctx, &buf);
  569. }
  570. static void
  571. command_send_ctx(grn_ctx *ctx, char *command, int type, int task_id)
  572. {
  573. grn_ctx_send(ctx, command, strlen(command), 0);
  574. /* fix me.
  575. when command fails, ctx->rc is not 0 in local mode!
  576. if (ctx->rc) {
  577. fprintf(stderr, "ctx_send:rc=%d:command:%s\n", ctx->rc, command);
  578. error_exit_in_thread(1);
  579. }
  580. */
  581. }
  582. static void
  583. command_send(grn_ctx *ctx, char *command, int type, int task_id)
  584. {
  585. if (http_p(type)) {
  586. command_send_http(ctx, command, type, task_id);
  587. } else {
  588. command_send_ctx(ctx, command, type, task_id);
  589. }
  590. }
  591. static void
  592. command_recv_http(grn_ctx *ctx, int type, int task_id,
  593. char **res, int *res_len, int *flags)
  594. {
  595. int len;
  596. char buf[BUF_LEN];
  597. char *p, *e;
  598. socket_t http_socket;
  599. grn_obj *http_response;
  600. http_socket = grntest_task[task_id].http_socket;
  601. http_response = &grntest_task[task_id].http_response;
  602. while ((len = recv(http_socket, buf, BUF_LEN - 1, 0))) {
  603. #ifdef DEBUG_HTTP
  604. fprintf(stderr, "receive: <%.*s>\n", len, buf);
  605. #endif
  606. GRN_TEXT_PUT(ctx, http_response, buf, len);
  607. }
  608. p = GRN_TEXT_VALUE(http_response);
  609. e = p + GRN_TEXT_LEN(http_response);
  610. while (p < e) {
  611. if (p[0] != '\r') {
  612. p++;
  613. continue;
  614. }
  615. if (e - p >= 4) {
  616. if (!memcmp(p, "\r\n\r\n", 4)) {
  617. *res = p + 4;
  618. *res_len = e - *res;
  619. #ifdef DEBUG_HTTP
  620. fprintf(stderr, "body: <%.*s>\n", *res_len, *res);
  621. #endif
  622. break;
  623. }
  624. p += 4;
  625. } else {
  626. *res = NULL;
  627. *res_len = 0;
  628. break;
  629. }
  630. }
  631. socketclose(http_socket);
  632. grntest_task[task_id].http_socket = 0;
  633. }
  634. static void
  635. command_recv_ctx(grn_ctx *ctx, int type, int task_id,
  636. char **res, int *res_len, int *flags)
  637. {
  638. grn_ctx_recv(ctx, res, res_len, flags);
  639. if (ctx->rc) {
  640. fprintf(stderr, "ctx_recv:rc=%d\n", ctx->rc);
  641. error_exit_in_thread(1);
  642. }
  643. }
  644. static void
  645. command_recv(grn_ctx *ctx, int type, int task_id,
  646. char **res, int *res_len, int *flags)
  647. {
  648. if (http_p(type)) {
  649. command_recv_http(ctx, type, task_id, res, res_len, flags);
  650. } else {
  651. command_recv_ctx(ctx, type, task_id, res, res_len, flags);
  652. }
  653. }
  654. static int
  655. shutdown_server(void)
  656. {
  657. char *res;
  658. int flags, res_len;
  659. int job_type;
  660. int task_id = 0;
  661. if (grntest_remote_mode) {
  662. return 0;
  663. }
  664. job_type = grntest_task[task_id].jobtype;
  665. command_send(&grntest_server_context, "shutdown", job_type, task_id);
  666. if (grntest_server_context.rc) {
  667. fprintf(stderr, "ctx_send:rc=%d\n", grntest_server_context.rc);
  668. exit(1);
  669. }
  670. command_recv(&grntest_server_context, job_type, task_id,
  671. &res, &res_len, &flags);
  672. return 0;
  673. }
  674. static int
  675. do_load_command(grn_ctx *ctx, char *command, int type, int task_id,
  676. long long int *load_start)
  677. {
  678. char *res;
  679. int res_len, flags, ret;
  680. grn_obj start_time, end_time;
  681. GRN_TIME_INIT(&start_time, 0);
  682. if (*load_start == 0) {
  683. GRN_TIME_NOW(ctx, &start_time);
  684. *load_start = GRN_TIME_VALUE(&start_time);
  685. } else {
  686. GRN_TIME_SET(ctx, &start_time, *load_start);
  687. }
  688. command_send(ctx, command, type, task_id);
  689. do {
  690. command_recv(ctx, type, task_id, &res, &res_len, &flags);
  691. if (res_len) {
  692. long long int self;
  693. GRN_TIME_INIT(&end_time, 0);
  694. GRN_TIME_NOW(ctx, &end_time);
  695. self = GRN_TIME_VALUE(&end_time) - *load_start;
  696. if (grntest_task[task_id].max < self) {
  697. grntest_task[task_id].max = self;
  698. }
  699. if (grntest_task[task_id].min > self) {
  700. grntest_task[task_id].min = self;
  701. }
  702. if (report_p(grntest_task[task_id].jobtype)) {
  703. unsigned char tmpbuf[BUF_LEN];
  704. if (res_len < BUF_LEN) {
  705. strncpy(tmpbuf, res, res_len);
  706. tmpbuf[res_len] = '\0';
  707. } else {
  708. strncpy(tmpbuf, res, BUF_LEN - 2);
  709. tmpbuf[BUF_LEN -2] = '\0';
  710. }
  711. report_command(ctx, "load", tmpbuf, task_id, &start_time, &end_time);
  712. }
  713. if (out_p(grntest_task[task_id].jobtype)) {
  714. fwrite(res, 1, res_len, grntest_job[grntest_task[task_id].job_id].outputlog);
  715. fputc('\n', grntest_job[grntest_task[task_id].job_id].outputlog);
  716. fflush(grntest_job[grntest_task[task_id].job_id].outputlog);
  717. }
  718. if (test_p(grntest_task[task_id].jobtype)) {
  719. grn_obj log;
  720. FILE *input;
  721. FILE *output;
  722. GRN_TEXT_INIT(&log, 0);
  723. input = grntest_job[grntest_task[task_id].job_id].inputlog;
  724. output = grntest_job[grntest_task[task_id].job_id].outputlog;
  725. if (grn_text_fgets(ctx, &log, input) != GRN_SUCCESS) {
  726. GRN_LOG(ctx, GRN_ERROR, "Cannot get input-log");
  727. error_exit_in_thread(55);
  728. }
  729. if (GRN_TEXT_VALUE(&log)[GRN_TEXT_LEN(&log) - 1] == '\n') {
  730. grn_bulk_truncate(ctx, &log, GRN_TEXT_LEN(&log) - 1);
  731. }
  732. if (!same_result_p(GRN_TEXT_VALUE(&log), GRN_TEXT_LEN(&log),
  733. res, res_len)) {
  734. fprintf(output, "DIFF:command:%s\n", command);
  735. fprintf(output, "DIFF:result:");
  736. fwrite(res, 1, res_len, output);
  737. fputc('\n', output);
  738. fprintf(output, "DIFF:expect:%.*s\n",
  739. (int)GRN_TEXT_LEN(&log), GRN_TEXT_VALUE(&log));
  740. fflush(output);
  741. }
  742. GRN_OBJ_FIN(ctx, &log);
  743. }
  744. grn_obj_close(ctx, &end_time);
  745. ret = 1;
  746. break;
  747. } else {
  748. ret = 0;
  749. break;
  750. }
  751. } while ((flags & GRN_CTX_MORE));
  752. grn_obj_close(ctx, &start_time);
  753. return ret;
  754. }
  755. static int
  756. do_command(grn_ctx *ctx, char *command, int type, int task_id)
  757. {
  758. char *res;
  759. int res_len, flags;
  760. grn_obj start_time, end_time;
  761. GRN_TIME_INIT(&start_time, 0);
  762. GRN_TIME_NOW(ctx, &start_time);
  763. command_send(ctx, command, type, task_id);
  764. do {
  765. command_recv(ctx, type, task_id, &res, &res_len, &flags);
  766. if (res_len) {
  767. long long int self;
  768. GRN_TIME_INIT(&end_time, 0);
  769. GRN_TIME_NOW(ctx, &end_time);
  770. self = GRN_TIME_VALUE(&end_time) - GRN_TIME_VALUE(&start_time);
  771. if (grntest_task[task_id].max < self) {
  772. grntest_task[task_id].max = self;
  773. }
  774. if (grntest_task[task_id].min > self) {
  775. grntest_task[task_id].min = self;
  776. }
  777. if (report_p(grntest_task[task_id].jobtype)) {
  778. unsigned char tmpbuf[BUF_LEN];
  779. if (res_len < BUF_LEN) {
  780. strncpy(tmpbuf, res, res_len);
  781. tmpbuf[res_len] = '\0';
  782. } else {
  783. strncpy(tmpbuf, res, BUF_LEN - 2);
  784. tmpbuf[BUF_LEN -2] = '\0';
  785. }
  786. report_command(ctx, command, tmpbuf, task_id, &start_time, &end_time);
  787. }
  788. if (out_p(grntest_task[task_id].jobtype)) {
  789. fwrite(res, 1, res_len, grntest_job[grntest_task[task_id].job_id].outputlog);
  790. fputc('\n', grntest_job[grntest_task[task_id].job_id].outputlog);
  791. fflush(grntest_job[grntest_task[task_id].job_id].outputlog);
  792. }
  793. if (test_p(grntest_task[task_id].jobtype)) {
  794. grn_obj log;
  795. FILE *input;
  796. FILE *output;
  797. GRN_TEXT_INIT(&log, 0);
  798. input = grntest_job[grntest_task[task_id].job_id].inputlog;
  799. output = grntest_job[grntest_task[task_id].job_id].outputlog;
  800. if (grn_text_fgets(ctx, &log, input) != GRN_SUCCESS) {
  801. GRN_LOG(ctx, GRN_ERROR, "Cannot get input-log");
  802. error_exit_in_thread(55);
  803. }
  804. if (GRN_TEXT_VALUE(&log)[GRN_TEXT_LEN(&log) - 1] == '\n') {
  805. grn_bulk_truncate(ctx, &log, GRN_TEXT_LEN(&log) - 1);
  806. }
  807. if (!same_result_p(GRN_TEXT_VALUE(&log), GRN_TEXT_LEN(&log),
  808. res, res_len)) {
  809. fprintf(output, "DIFF:command:%s\n", command);
  810. fprintf(output, "DIFF:result:");
  811. fwrite(res, 1, res_len, output);
  812. fputc('\n', output);
  813. fprintf(output, "DIFF:expect:%.*s\n",
  814. (int)GRN_TEXT_LEN(&log), GRN_TEXT_VALUE(&log));
  815. fflush(output);
  816. }
  817. GRN_OBJ_FIN(ctx, &log);
  818. }
  819. grn_obj_close(ctx, &end_time);
  820. break;
  821. } else {
  822. #ifdef ENABLE_ERROR_REPORT
  823. error_command(ctx, command, task_id);
  824. #endif
  825. }
  826. } while ((flags & GRN_CTX_MORE));
  827. grn_obj_close(ctx, &start_time);
  828. return 0;
  829. }
  830. static int
  831. comment_p(char *command)
  832. {
  833. if (command[0] == '#') {
  834. return 1;
  835. }
  836. return 0;
  837. }
  838. static int
  839. load_command_p(char *command)
  840. {
  841. int i = 0;
  842. while (grn_isspace(&command[i], GRN_ENC_UTF8) == 1) {
  843. i++;
  844. }
  845. if (command[i] == '\0') {
  846. return 0;
  847. }
  848. if (!strncmp(&command[i], "load", 4)) {
  849. return 1;
  850. }
  851. return 0;
  852. }
  853. static int
  854. worker_sub(grn_ctx *ctx, grn_obj *log, int task_id)
  855. {
  856. int i, load_mode, load_count;
  857. grn_obj end_time;
  858. long long int total_elapsed_time, job_elapsed_time;
  859. double sec, qps;
  860. long long int load_start;
  861. struct task *task;
  862. struct job *job;
  863. task = &(grntest_task[task_id]);
  864. task->max = 0LL;
  865. task->min = 9223372036854775807LL;
  866. task->qnum = 0;
  867. for (i = 0; i < task->ntimes; i++) {
  868. if (task->file != NULL) {
  869. FILE *fp;
  870. grn_obj line;
  871. fp = fopen(task->file, "r");
  872. if (!fp) {
  873. fprintf(stderr, "Cannot open %s\n",grntest_task[task_id].file);
  874. error_exit_in_thread(1);
  875. }
  876. load_mode = 0;
  877. load_count = 0;
  878. load_start = 0LL;
  879. GRN_TEXT_INIT(&line, 0);
  880. while (grn_text_fgets(ctx, &line, fp) == GRN_SUCCESS) {
  881. if (GRN_TEXT_VALUE(&line)[GRN_TEXT_LEN(&line) - 1] == '\n') {
  882. grn_bulk_truncate(ctx, &line, GRN_TEXT_LEN(&line) - 1);
  883. }
  884. if (GRN_TEXT_LEN(&line) == 0) {
  885. GRN_BULK_REWIND(&line);
  886. continue;
  887. }
  888. GRN_TEXT_PUTC(ctx, &line, '\0');
  889. if (comment_p(GRN_TEXT_VALUE(&line))) {
  890. GRN_BULK_REWIND(&line);
  891. continue;
  892. }
  893. if (load_command_p(GRN_TEXT_VALUE(&line))) {
  894. load_mode = 1;
  895. load_count = 1;
  896. }
  897. if (load_mode == 1) {
  898. if (do_load_command(&grntest_ctx[task_id], GRN_TEXT_VALUE(&line),
  899. task->jobtype,
  900. task_id, &load_start)) {
  901. task->qnum += load_count;
  902. load_mode = 0;
  903. load_count = 0;
  904. load_start = 0LL;
  905. }
  906. load_count++;
  907. GRN_BULK_REWIND(&line);
  908. continue;
  909. }
  910. do_command(&grntest_ctx[task_id], GRN_TEXT_VALUE(&line),
  911. task->jobtype,
  912. task_id);
  913. task->qnum++;
  914. GRN_BULK_REWIND(&line);
  915. if (grntest_sigint) {
  916. goto exit;
  917. }
  918. }
  919. GRN_OBJ_FIN(ctx, &line);
  920. fclose(fp);
  921. } else {
  922. int i, n_commands;
  923. grn_obj *commands;
  924. commands = task->commands;
  925. if (!commands) {
  926. error_exit_in_thread(1);
  927. }
  928. load_mode = 0;
  929. n_commands = GRN_BULK_VSIZE(commands) / sizeof(grn_obj *);
  930. for (i = 0; i < n_commands; i++) {
  931. grn_obj *command;
  932. command = GRN_PTR_VALUE_AT(commands, i);
  933. if (load_command_p(GRN_TEXT_VALUE(command))) {
  934. load_mode = 1;
  935. }
  936. if (load_mode == 1) {
  937. if (do_load_command(&grntest_ctx[task_id],
  938. GRN_TEXT_VALUE(command),
  939. task->jobtype, task_id, &load_start)) {
  940. load_mode = 0;
  941. load_start = 0LL;
  942. task->qnum++;
  943. }
  944. continue;
  945. }
  946. do_command(&grntest_ctx[task_id],
  947. GRN_TEXT_VALUE(command),
  948. task->jobtype, task_id);
  949. task->qnum++;
  950. if (grntest_sigint) {
  951. goto exit;
  952. }
  953. }
  954. }
  955. }
  956. exit:
  957. GRN_TIME_INIT(&end_time, 0);
  958. GRN_TIME_NOW(&grntest_ctx[task_id], &end_time);
  959. total_elapsed_time = GRN_TIME_VALUE(&end_time) - GRN_TIME_VALUE(&grntest_starttime);
  960. job_elapsed_time = GRN_TIME_VALUE(&end_time) - GRN_TIME_VALUE(&grntest_jobs_start);
  961. CRITICAL_SECTION_ENTER(grntest_cs);
  962. job = &(grntest_job[task->job_id]);
  963. if (job->max < task->max) {
  964. job->max = task->max;
  965. }
  966. if (job->min > task->min) {
  967. job->min = task->min;
  968. }
  969. job->qnum += task->qnum;
  970. job->done++;
  971. if (job->done == job->concurrency) {
  972. char tmpbuf[BUF_LEN];
  973. sec = job_elapsed_time / (double)1000000;
  974. qps = (double)job->qnum/ sec;
  975. grntest_jobdone++;
  976. if (grntest_outtype == OUT_TSV) {
  977. sprintf(tmpbuf,
  978. "job\t"
  979. "%s\t"
  980. "%" GRN_FMT_LLD "\t"
  981. "%" GRN_FMT_LLD "\t"
  982. "%f\t"
  983. "%" GRN_FMT_LLD "\t"
  984. "%" GRN_FMT_LLD "\t"
  985. "%d\n",
  986. job->jobname,
  987. total_elapsed_time,
  988. job_elapsed_time,
  989. qps,
  990. job->min,
  991. job->max,
  992. job->qnum);
  993. } else {
  994. sprintf(tmpbuf,
  995. "{\"job\": \"%s\", "
  996. "\"total_elapsed_time\": %" GRN_FMT_LLD ", "
  997. "\"job_elapsed_time\": %" GRN_FMT_LLD ", "
  998. "\"qps\": %f, "
  999. "\"min\": %" GRN_FMT_LLD ", "
  1000. "\"max\": %" GRN_FMT_LLD ", "
  1001. "\"queries\": %d}",
  1002. job->jobname,
  1003. total_elapsed_time,
  1004. job_elapsed_time,
  1005. qps,
  1006. job->min,
  1007. job->max,
  1008. job->qnum);
  1009. if (grntest_jobdone < grntest_jobnum) {
  1010. strcat(tmpbuf, ",");
  1011. }
  1012. }
  1013. GRN_TEXT_PUTS(ctx, log, tmpbuf);
  1014. if (grntest_jobdone == grntest_jobnum) {
  1015. if (grntest_outtype == OUT_TSV) {
  1016. fprintf(grntest_log_file, "%.*s",
  1017. (int)GRN_TEXT_LEN(log), GRN_TEXT_VALUE(log));
  1018. } else {
  1019. if (grntest_detail_on) {
  1020. fseek(grntest_log_file, -2, SEEK_CUR);
  1021. fprintf(grntest_log_file, "],\n");
  1022. }
  1023. fprintf(grntest_log_file, "\"summary\": [");
  1024. fprintf(grntest_log_file, "%.*s",
  1025. (int)GRN_TEXT_LEN(log), GRN_TEXT_VALUE(log));
  1026. fprintf(grntest_log_file, "]");
  1027. }
  1028. fflush(grntest_log_file);
  1029. }
  1030. }
  1031. grn_obj_close(&grntest_ctx[task_id], &end_time);
  1032. CRITICAL_SECTION_LEAVE(grntest_cs);
  1033. return 0;
  1034. }
  1035. typedef struct _grntest_worker {
  1036. grn_ctx *ctx;
  1037. grn_obj log;
  1038. int task_id;
  1039. } grntest_worker;
  1040. #ifdef WIN32
  1041. static int
  1042. __stdcall
  1043. worker(void *val)
  1044. {
  1045. grntest_worker *worker = val;
  1046. worker_sub(worker->ctx, &worker->log, worker->task_id);
  1047. return 0;
  1048. }
  1049. #else
  1050. static void *
  1051. worker(void *val)
  1052. {
  1053. grntest_worker *worker = val;
  1054. worker_sub(worker->ctx, &worker->log, worker->task_id);
  1055. return NULL;
  1056. }
  1057. #endif /* WIN32 */
  1058. #ifdef WIN32
  1059. static int
  1060. thread_main(grn_ctx *ctx, int num)
  1061. {
  1062. int i;
  1063. int ret;
  1064. HANDLE pthread[MAX_CON];
  1065. grntest_worker *workers[MAX_CON];
  1066. for (i = 0; i < num; i++) {
  1067. workers[i] = GRN_MALLOC(sizeof(grntest_worker));
  1068. workers[i]->ctx = &grntest_ctx[i];
  1069. GRN_TEXT_INIT(&workers[i]->log, 0);
  1070. workers[i]->task_id = i;
  1071. pthread[i] = (HANDLE)_beginthreadex(NULL, 0, worker, (void *)workers[i],
  1072. 0, NULL);
  1073. if (pthread[i]== (HANDLE)0) {
  1074. fprintf(stderr, "thread failed:%d\n", i);
  1075. error_exit_in_thread(1);
  1076. }
  1077. }
  1078. ret = WaitForMultipleObjects(num, pthread, TRUE, INFINITE);
  1079. if (ret == WAIT_TIMEOUT) {
  1080. fprintf(stderr, "timeout\n");
  1081. error_exit_in_thread(1);
  1082. }
  1083. for (i = 0; i < num; i++) {
  1084. CloseHandle(pthread[i]);
  1085. GRN_OBJ_FIN(workers[i]->ctx, &workers[i]->log);
  1086. GRN_FREE(workers[i]);
  1087. }
  1088. return 0;
  1089. }
  1090. #else
  1091. static int
  1092. thread_main(grn_ctx *ctx, int num)
  1093. {
  1094. intptr_t i;
  1095. int ret;
  1096. pthread_t pthread[MAX_CON];
  1097. grntest_worker *workers[MAX_CON];
  1098. for (i = 0; i < num; i++) {
  1099. workers[i] = GRN_MALLOC(sizeof(grntest_worker));
  1100. workers[i]->ctx = &grntest_ctx[i];
  1101. GRN_TEXT_INIT(&workers[i]->log, 0);
  1102. workers[i]->task_id = i;
  1103. ret = pthread_create(&pthread[i], NULL, worker, (void *)workers[i]);
  1104. if (ret) {
  1105. fprintf(stderr, "Cannot create thread:ret=%d\n", ret);
  1106. error_exit_in_thread(1);
  1107. }
  1108. }
  1109. for (i = 0; i < num; i++) {
  1110. ret = pthread_join(pthread[i], NULL);
  1111. GRN_OBJ_FIN(workers[i]->ctx, &workers[i]->log);
  1112. GRN_FREE(workers[i]);
  1113. if (ret) {
  1114. fprintf(stderr, "Cannot join thread:ret=%d\n", ret);
  1115. error_exit_in_thread(1);
  1116. }
  1117. }
  1118. return 0;
  1119. }
  1120. #endif
  1121. static int
  1122. error_exit(grn_ctx *ctx, int ret)
  1123. {
  1124. fflush(stderr);
  1125. shutdown_server();
  1126. grn_ctx_fin(ctx);
  1127. grn_fin();
  1128. exit(ret);
  1129. }
  1130. static int
  1131. get_sysinfo(const char *path, char *result, int olen)
  1132. {
  1133. char tmpbuf[256];
  1134. #ifdef WIN32
  1135. int cinfo[4];
  1136. ULARGE_INTEGER dinfo;
  1137. char cpustring[64];
  1138. SYSTEM_INFO sinfo;
  1139. MEMORYSTATUSEX minfo;
  1140. OSVERSIONINFO osinfo;
  1141. if (grntest_outtype == OUT_TSV) {
  1142. result[0] = '\0';
  1143. sprintf(tmpbuf, "script\t%s\n", grntest_scriptname);
  1144. strcat(result, tmpbuf);
  1145. sprintf(tmpbuf, "user\t%s\n", grntest_username);
  1146. strcat(result, tmpbuf);
  1147. sprintf(tmpbuf, "date\t%s\n", grntest_date);
  1148. strcat(result, tmpbuf);
  1149. } else {
  1150. strcpy(result, "{");
  1151. sprintf(tmpbuf, "\"script\": \"%s.scr\",\n", grntest_scriptname);
  1152. strcat(result, tmpbuf);
  1153. sprintf(tmpbuf, " \"user\": \"%s\",\n", grntest_username);
  1154. strcat(result, tmpbuf);
  1155. sprintf(tmpbuf, " \"date\": \"%s\",\n", grntest_date);
  1156. strcat(result, tmpbuf);
  1157. }
  1158. memset(cpustring, 0, 64);
  1159. #ifndef __GNUC__
  1160. __cpuid(cinfo, 0x80000002);
  1161. memcpy(cpustring, cinfo, 16);
  1162. __cpuid(cinfo, 0x80000003);
  1163. memcpy(cpustring+16, cinfo, 16);
  1164. __cpuid(cinfo, 0x80000004);
  1165. memcpy(cpustring+32, cinfo, 16);
  1166. #endif
  1167. if (grntest_outtype == OUT_TSV) {
  1168. sprintf(tmpbuf, "%s\n", cpustring);
  1169. } else {
  1170. sprintf(tmpbuf, " \"CPU\": \"%s\",\n", cpustring);
  1171. }
  1172. strcat(result, tmpbuf);
  1173. if (sizeof(int *) == 8) {
  1174. grntest_osinfo = OS_WINDOWS64;
  1175. if (grntest_outtype == OUT_TSV) {
  1176. sprintf(tmpbuf, "64BIT\n");
  1177. } else {
  1178. sprintf(tmpbuf, " \"BIT\": 64,\n");
  1179. }
  1180. } else {
  1181. grntest_osinfo = OS_WINDOWS32;
  1182. if (grntest_outtype == OUT_TSV) {
  1183. sprintf(tmpbuf, "32BIT\n");
  1184. } else {
  1185. sprintf(tmpbuf, " \"BIT\": 32,\n");
  1186. }
  1187. }
  1188. strcat(result, tmpbuf);
  1189. GetSystemInfo(&sinfo);
  1190. if (grntest_outtype == OUT_TSV) {
  1191. sprintf(tmpbuf, "CORE\t%d\n", sinfo.dwNumberOfProcessors);
  1192. } else {
  1193. sprintf(tmpbuf, " \"CORE\": %d,\n", sinfo.dwNumberOfProcessors);
  1194. }
  1195. strcat(result, tmpbuf);
  1196. minfo.dwLength = sizeof(MEMORYSTATUSEX);
  1197. GlobalMemoryStatusEx(&minfo);
  1198. if (grntest_outtype == OUT_TSV) {
  1199. sprintf(tmpbuf, "RAM\t%I64dMByte\n", minfo.ullTotalPhys/(1024*1024));
  1200. } else {
  1201. sprintf(tmpbuf, " \"RAM\": \"%I64dMByte\",\n", minfo.ullTotalPhys/(1024*1024));
  1202. }
  1203. strcat(result, tmpbuf);
  1204. GetDiskFreeSpaceEx(NULL, NULL, &dinfo, NULL);
  1205. if (grntest_outtype == OUT_TSV) {
  1206. sprintf(tmpbuf, "HDD\t%I64dKBytes\n", dinfo.QuadPart/1024 );
  1207. } else {
  1208. sprintf(tmpbuf, " \"HDD\": \"%I64dKBytes\",\n", dinfo.QuadPart/1024 );
  1209. }
  1210. strcat(result, tmpbuf);
  1211. osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osinfo);
  1212. if (grntest_outtype == OUT_TSV) {
  1213. sprintf(tmpbuf, "Windows %d.%d\n", osinfo.dwMajorVersion, osinfo.dwMinorVersion);
  1214. } else {
  1215. sprintf(tmpbuf, " \"OS\": \"Windows %d.%d\",\n", osinfo.dwMajorVersion,
  1216. osinfo.dwMinorVersion);
  1217. }
  1218. strcat(result, tmpbuf);
  1219. if (grntest_outtype == OUT_TSV) {
  1220. sprintf(tmpbuf, "%s\n", grntest_serverhost);
  1221. } else {
  1222. sprintf(tmpbuf, " \"HOST\": \"%s\",\n", grntest_serverhost);
  1223. }
  1224. strcat(result, tmpbuf);
  1225. if (grntest_outtype == OUT_TSV) {
  1226. sprintf(tmpbuf, "%d\n", grntest_serverport);
  1227. } else {
  1228. sprintf(tmpbuf, " \"PORT\": \"%d\",\n", grntest_serverport);
  1229. }
  1230. strcat(result, tmpbuf);
  1231. if (grntest_outtype == OUT_TSV) {
  1232. sprintf(tmpbuf, "%s\"\n", grn_get_version());
  1233. } else {
  1234. sprintf(tmpbuf, " \"VERSION\": \"%s\"\n", grn_get_version());
  1235. }
  1236. strcat(result, tmpbuf);
  1237. if (grntest_outtype != OUT_TSV) {
  1238. strcat(result, "}");
  1239. }
  1240. #else /* linux only */
  1241. FILE *fp;
  1242. int ret;
  1243. int cpunum = 0;
  1244. int minfo = 0;
  1245. int unevictable = 0;
  1246. int mlocked = 0;
  1247. char cpustring[256];
  1248. struct utsname ubuf;
  1249. struct statvfs vfsbuf;
  1250. if (grntest_outtype == OUT_TSV) {
  1251. result[0] = '\0';
  1252. sprintf(tmpbuf, "sctipt\t%s\n", grntest_scriptname);
  1253. strcat(result, tmpbuf);
  1254. sprintf(tmpbuf, "user\t%s\n", grntest_username);
  1255. strcat(result, tmpbuf);
  1256. sprintf(tmpbuf, "date\t%s\n", grntest_date);
  1257. strcat(result, tmpbuf);
  1258. } else {
  1259. strcpy(result, "{");
  1260. sprintf(tmpbuf, "\"script\": \"%s.scr\",\n", grntest_scriptname);
  1261. strcat(result, tmpbuf);
  1262. sprintf(tmpbuf, " \"user\": \"%s\",\n", grntest_username);
  1263. strcat(result, tmpbuf);
  1264. sprintf(tmpbuf, " \"date\": \"%s\",\n", grntest_date);
  1265. strcat(result, tmpbuf);
  1266. }
  1267. fp = fopen("/proc/cpuinfo", "r");
  1268. if (!fp) {
  1269. fprintf(stderr, "Cannot open cpuinfo\n");
  1270. exit(1);
  1271. }
  1272. while (fgets(tmpbuf, 256, fp) != NULL) {
  1273. tmpbuf[strlen(tmpbuf)-1] = '\0';
  1274. if (!strncmp(tmpbuf, "model name\t: ", 13)) {
  1275. strcpy(cpustring, &tmpbuf[13]);
  1276. }
  1277. }
  1278. fclose(fp);
  1279. cpunum = sysconf(_SC_NPROCESSORS_CONF);
  1280. if (grntest_outtype == OUT_TSV) {
  1281. sprintf(tmpbuf, "%s\n", cpustring);
  1282. } else {
  1283. sprintf(tmpbuf, " \"CPU\": \"%s\",\n", cpustring);
  1284. }
  1285. strcat(result, tmpbuf);
  1286. if (sizeof(int *) == 8) {
  1287. grntest_osinfo = OS_LINUX64;
  1288. if (grntest_outtype == OUT_TSV) {
  1289. sprintf(tmpbuf, "64BIT\n");
  1290. } else {
  1291. sprintf(tmpbuf, " \"BIT\": 64,\n");
  1292. }
  1293. } else {
  1294. grntest_osinfo = OS_LINUX32;
  1295. if (grntest_outtype == OUT_TSV) {
  1296. sprintf(tmpbuf, "32BIT\n");
  1297. } else {
  1298. sprintf(tmpbuf, " \"BIT\": 32,\n");
  1299. }
  1300. }
  1301. strcat(result, tmpbuf);
  1302. if (grntest_outtype == OUT_TSV) {
  1303. sprintf(tmpbuf, "CORE\t%d\n", cpunum);
  1304. } else {
  1305. sprintf(tmpbuf, " \"CORE\": %d,\n", cpunum);
  1306. }
  1307. strcat(result, tmpbuf);
  1308. fp = fopen("/proc/meminfo", "r");
  1309. if (!fp) {
  1310. fprintf(stderr, "Cannot open meminfo\n");
  1311. exit(1);
  1312. }
  1313. while (fgets(tmpbuf, 256, fp) != NULL) {
  1314. tmpbuf[strlen(tmpbuf)-1] = '\0';
  1315. if (!strncmp(tmpbuf, "MemTotal:", 9)) {
  1316. minfo = grntest_atoi(&tmpbuf[10], &tmpbuf[10] + 40, NULL);
  1317. }
  1318. if (!strncmp(tmpbuf, "Unevictable:", 12)) {
  1319. unevictable = grntest_atoi(&tmpbuf[13], &tmpbuf[13] + 40, NULL);
  1320. }
  1321. if (!strncmp(tmpbuf, "Mlocked:", 8)) {
  1322. mlocked = grntest_atoi(&tmpbuf[9], &tmpbuf[9] + 40, NULL);
  1323. }
  1324. }
  1325. fclose(fp);
  1326. if (grntest_outtype == OUT_TSV) {
  1327. sprintf(tmpbuf, "%dMBytes\n", minfo/1024);
  1328. strcat(result, tmpbuf);
  1329. sprintf(tmpbuf, "%dMBytes_Unevictable\n", unevictable/1024);
  1330. strcat(result, tmpbuf);
  1331. sprintf(tmpbuf, "%dMBytes_Mlocked\n", mlocked/1024);
  1332. strcat(result, tmpbuf);
  1333. } else {
  1334. sprintf(tmpbuf, " \"RAM\": \"%dMBytes\",\n", minfo/1024);
  1335. strcat(result, tmpbuf);
  1336. sprintf(tmpbuf, " \"Unevictable\": \"%dMBytes\",\n", unevictable/1024);
  1337. strcat(result, tmpbuf);
  1338. sprintf(tmpbuf, " \"Mlocked\": \"%dMBytes\",\n", mlocked/1024);
  1339. strcat(result, tmpbuf);
  1340. }
  1341. ret = statvfs(path, &vfsbuf);
  1342. if (ret) {
  1343. fprintf(stderr, "Cannot access %s\n", path);
  1344. exit(1);
  1345. }
  1346. if (grntest_outtype == OUT_TSV) {
  1347. sprintf(tmpbuf, "%luKBytes\n", vfsbuf.f_blocks * 4);
  1348. } else {
  1349. sprintf(tmpbuf, " \"HDD\": \"%luKBytes\",\n", vfsbuf.f_blocks * 4);
  1350. }
  1351. strcat(result, tmpbuf);
  1352. uname(&ubuf);
  1353. if (grntest_outtype == OUT_TSV) {
  1354. sprintf(tmpbuf, "%s %s\n", ubuf.sysname, ubuf.release);
  1355. } else {
  1356. sprintf(tmpbuf, " \"OS\": \"%s %s\",\n", ubuf.sysname, ubuf.release);
  1357. }
  1358. strcat(result, tmpbuf);
  1359. if (grntest_outtype == OUT_TSV) {
  1360. sprintf(tmpbuf, "%s\n", grntest_serverhost);
  1361. } else {
  1362. sprintf(tmpbuf, " \"HOST\": \"%s\",\n", grntest_serverhost);
  1363. }
  1364. strcat(result, tmpbuf);
  1365. if (grntest_outtype == OUT_TSV) {
  1366. sprintf(tmpbuf, "%d\n", grntest_serverport);
  1367. } else {
  1368. sprintf(tmpbuf, " \"PORT\": \"%d\",\n", grntest_serverport);
  1369. }
  1370. strcat(result, tmpbuf);
  1371. if (grntest_outtype == OUT_TSV) {
  1372. sprintf(tmpbuf, "%s\n", grn_get_version());
  1373. } else {
  1374. sprintf(tmpbuf, " \"VERSION\": \"%s\"\n", grn_get_version());
  1375. }
  1376. strcat(result, tmpbuf);
  1377. if (grntest_outtype != OUT_TSV) {
  1378. strcat(result, "},");
  1379. }
  1380. #endif /* WIN32 */
  1381. if (strlen(result) >= olen) {
  1382. fprintf(stderr, "buffer overrun in get_sysinfo!\n");
  1383. exit(1);
  1384. }
  1385. return 0;
  1386. }
  1387. static int
  1388. start_server(const char *dbpath, int r)
  1389. {
  1390. int ret;
  1391. char optbuf[BUF_LEN];
  1392. #ifdef WIN32
  1393. char tmpbuf[BUF_LEN];
  1394. STARTUPINFO si;
  1395. if (strlen(dbpath) > BUF_LEN - 100) {
  1396. fprintf(stderr, "too long dbpath!\n");
  1397. exit(1);
  1398. }
  1399. strcpy(tmpbuf, groonga_path);
  1400. strcat(tmpbuf, " -s --protocol ");
  1401. strcat(tmpbuf, groonga_protocol);
  1402. strcat(tmpbuf, " -p ");
  1403. sprintf(optbuf, "%d ", grntest_serverport);
  1404. strcat(tmpbuf, optbuf);
  1405. strcat(tmpbuf, dbpath);
  1406. memset(&si, 0, sizeof(STARTUPINFO));
  1407. si.cb=sizeof(STARTUPINFO);
  1408. ret = CreateProcess(NULL, tmpbuf, NULL, NULL, FALSE,
  1409. 0, NULL, NULL, &si, &grntest_pi);
  1410. if (ret == 0) {
  1411. fprintf(stderr, "Cannot start groonga server: <%s>: error=%d\n",
  1412. groonga_path, GetLastError());
  1413. exit(1);
  1414. }
  1415. #else
  1416. pid_t pid;
  1417. pid = fork();
  1418. if (pid < 0) {
  1419. fprintf(stderr, "Cannot start groonga server:Cannot fork\n");
  1420. exit(1);
  1421. }
  1422. sprintf(optbuf, "%d", grntest_serverport);
  1423. if (pid == 0) {
  1424. ret = execlp(groonga_path, groonga_path,
  1425. "-s",
  1426. "--protocol", groonga_protocol,
  1427. "-p", optbuf,
  1428. dbpath, (char*)NULL);
  1429. if (ret == -1) {
  1430. fprintf(stderr, "Cannot start groonga server: <%s>: errno=%d\n",
  1431. groonga_path, errno);
  1432. exit(1);
  1433. }
  1434. }
  1435. else {
  1436. grntest_server_id = pid;
  1437. }
  1438. #endif /* WIN32 */
  1439. return 0;
  1440. }
  1441. static int
  1442. parse_line(char *buf, int start, int end, int num)
  1443. {
  1444. int i, j, error_flag = 0, out_or_test = 0;
  1445. char tmpbuf[BUF_LEN];
  1446. grntest_job[num].concurrency = 1;
  1447. grntest_job[num].ntimes = 1;
  1448. grntest_job[num].done = 0;
  1449. grntest_job[num].qnum = 0;
  1450. grntest_job[num].max = 0LL;
  1451. grntest_job[num].min = 9223372036854775807LL;
  1452. grntest_job[num].outputlog = NULL;
  1453. grntest_job[num].inputlog = NULL;
  1454. strncpy(grntest_job[num].jobname, &buf[start], end - start);
  1455. grntest_job[num].jobname[end - start] = '\0';
  1456. i = start;
  1457. while (i < end) {
  1458. if (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1459. i++;
  1460. continue;
  1461. }
  1462. if (!strncmp(&buf[i], "do_local", 8)) {
  1463. grntest_job[num].jobtype = J_DO_LOCAL;
  1464. i = i + 8;
  1465. break;
  1466. }
  1467. if (!strncmp(&buf[i], "do_gqtp", 7)) {
  1468. grntest_job[num].jobtype = J_DO_GQTP;
  1469. i = i + 7;
  1470. break;
  1471. }
  1472. if (!strncmp(&buf[i], "do_http", 7)) {
  1473. grntest_job[num].jobtype = J_DO_HTTP;
  1474. i = i + 7;
  1475. break;
  1476. }
  1477. if (!strncmp(&buf[i], "rep_local", 9)) {
  1478. grntest_job[num].jobtype = J_REP_LOCAL;
  1479. i = i + 9;
  1480. break;
  1481. }
  1482. if (!strncmp(&buf[i], "rep_gqtp", 8)) {
  1483. grntest_job[num].jobtype = J_REP_GQTP;
  1484. i = i + 8;
  1485. break;
  1486. }
  1487. if (!strncmp(&buf[i], "rep_http", 8)) {
  1488. grntest_job[num].jobtype = J_REP_HTTP;
  1489. i = i + 8;
  1490. break;
  1491. }
  1492. if (!strncmp(&buf[i], "out_local", 9)) {
  1493. grntest_job[num].jobtype = J_OUT_LOCAL;
  1494. i = i + 9;
  1495. out_or_test = 1;
  1496. break;
  1497. }
  1498. if (!strncmp(&buf[i], "out_gqtp", 8)) {
  1499. grntest_job[num].jobtype = J_OUT_GQTP;
  1500. i = i + 8;
  1501. out_or_test = 1;
  1502. break;
  1503. }
  1504. if (!strncmp(&buf[i], "out_http", 8)) {
  1505. grntest_job[num].jobtype = J_OUT_HTTP;
  1506. i = i + 8;
  1507. out_or_test = 1;
  1508. break;
  1509. }
  1510. if (!strncmp(&buf[i], "test_local", 10)) {
  1511. grntest_job[num].jobtype = J_TEST_LOCAL;
  1512. i = i + 10;
  1513. out_or_test = 1;
  1514. break;
  1515. }
  1516. if (!strncmp(&buf[i], "test_gqtp", 9)) {
  1517. grntest_job[num].jobtype = J_TEST_GQTP;
  1518. i = i + 9;
  1519. out_or_test = 1;
  1520. break;
  1521. }
  1522. if (!strncmp(&buf[i], "test_http", 9)) {
  1523. grntest_job[num].jobtype = J_TEST_HTTP;
  1524. i = i + 9;
  1525. out_or_test = 1;
  1526. break;
  1527. }
  1528. error_flag = 1;
  1529. i++;
  1530. }
  1531. if (error_flag) {
  1532. return 3;
  1533. }
  1534. if (i == end) {
  1535. return 1;
  1536. }
  1537. if (grn_isspace(&buf[i], GRN_ENC_UTF8) != 1) {
  1538. return 4;
  1539. }
  1540. i++;
  1541. while (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1542. i++;
  1543. continue;
  1544. }
  1545. j = 0;
  1546. while (i < end) {
  1547. if (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1548. break;
  1549. }
  1550. grntest_job[num].commandfile[j] = buf[i];
  1551. i++;
  1552. j++;
  1553. if (j > 255) {
  1554. return 5;
  1555. }
  1556. }
  1557. grntest_job[num].commandfile[j] = '\0';
  1558. while (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1559. i++;
  1560. }
  1561. if (i == end) {
  1562. if (out_or_test) {
  1563. fprintf(stderr, "log(test)_local(gqtp|http) needs log(test)_filename\n");
  1564. return 11;
  1565. }
  1566. return 0;
  1567. }
  1568. j = 0;
  1569. while (i < end) {
  1570. if (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1571. break;
  1572. }
  1573. tmpbuf[j] = buf[i];
  1574. i++;
  1575. j++;
  1576. if (j >= BUF_LEN) {
  1577. return 6;
  1578. }
  1579. }
  1580. tmpbuf[j] ='\0';
  1581. if (out_or_test) {
  1582. if (out_p(grntest_job[num].jobtype)) {
  1583. grntest_job[num].outputlog = fopen(tmpbuf, "wb");
  1584. if (grntest_job[num].outputlog == NULL) {
  1585. fprintf(stderr, "Cannot open %s\n", tmpbuf);
  1586. return 13;
  1587. }
  1588. } else {
  1589. char outlog[BUF_LEN];
  1590. grntest_job[num].inputlog = fopen(tmpbuf, "rb");
  1591. if (grntest_job[num].inputlog == NULL) {
  1592. fprintf(stderr, "Cannot open %s\n", tmpbuf);
  1593. return 14;
  1594. }
  1595. sprintf(outlog, "%s.diff", tmpbuf);
  1596. grntest_job[num].outputlog = fopen(outlog, "wb");
  1597. if (grntest_job[num].outputlog == NULL) {
  1598. fprintf(stderr, "Cannot open %s\n", outlog);
  1599. return 15;
  1600. }
  1601. }
  1602. strcpy(grntest_job[num].logfile, tmpbuf);
  1603. return 0;
  1604. } else {
  1605. grntest_job[num].concurrency = grntest_atoi(tmpbuf, tmpbuf + j, NULL);
  1606. if (grntest_job[num].concurrency == 0) {
  1607. return 7;
  1608. }
  1609. }
  1610. while (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1611. i++;
  1612. }
  1613. if (i == end) {
  1614. return 0;
  1615. }
  1616. j = 0;
  1617. while (i < end) {
  1618. if (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1619. break;
  1620. }
  1621. tmpbuf[j] = buf[i];
  1622. i++;
  1623. j++;
  1624. if (j > 16) {
  1625. return 8;
  1626. }
  1627. }
  1628. tmpbuf[j] ='\0';
  1629. grntest_job[num].ntimes = grntest_atoi(tmpbuf, tmpbuf + j, NULL);
  1630. if (grntest_job[num].ntimes == 0) {
  1631. return 9;
  1632. }
  1633. if (i == end) {
  1634. return 0;
  1635. }
  1636. while (i < end) {
  1637. if (grn_isspace(&buf[i], GRN_ENC_UTF8) == 1) {
  1638. i++;
  1639. continue;
  1640. }
  1641. return 10;
  1642. }
  1643. return 0;
  1644. }
  1645. static int
  1646. get_jobs(grn_ctx *ctx, char *buf, int line)
  1647. {
  1648. int i, len, start, end, ret;
  1649. int jnum = 0;
  1650. len = strlen(buf);
  1651. i = 0;
  1652. while (i < len) {
  1653. if ((buf[i] == '#') || (buf[i] == '\r') || (buf[i] == '\n')) {
  1654. buf[i] = '\0';
  1655. len = i;
  1656. break;
  1657. }
  1658. i++;
  1659. }
  1660. i = 0;
  1661. start = 0;
  1662. while (i < len) {
  1663. if (buf[i] == ';') {
  1664. end = i;
  1665. ret = parse_line(buf, start, end, jnum);
  1666. if (ret) {
  1667. if (ret > 1) {
  1668. fprintf(stderr, "Syntax error:line=%d:ret=%d:%s\n", line, ret, buf);
  1669. error_exit(ctx, 1);
  1670. }
  1671. } else {
  1672. jnum++;
  1673. }
  1674. start = end + 1;
  1675. }
  1676. i++;
  1677. }
  1678. end = len;
  1679. ret = parse_line(buf, start, end, jnum);
  1680. if (ret) {
  1681. if (ret > 1) {
  1682. fprintf(stderr, "Syntax error:line=%d:ret=%d:%s\n", line, ret, buf);
  1683. error_exit(ctx, 1);
  1684. }
  1685. } else {
  1686. jnum++;
  1687. }
  1688. return jnum;
  1689. }
  1690. static int
  1691. make_task_table(grn_ctx *ctx, int jobnum)
  1692. {
  1693. int i, j;
  1694. int tid = 0;
  1695. FILE *fp;
  1696. grn_obj *commands = NULL;
  1697. for (i = 0; i < jobnum; i++) {
  1698. if ((grntest_job[i].concurrency == 1) && (!grntest_onmemory_mode)) {
  1699. grntest_task[tid].file = grntest_job[i].commandfile;
  1700. grntest_task[tid].commands = NULL;
  1701. grntest_task[tid].ntimes = grntest_job[i].ntimes;
  1702. grntest_task[tid].jobtype = grntest_job[i].jobtype;
  1703. grntest_task[tid].job_id = i;
  1704. tid++;
  1705. continue;
  1706. }
  1707. for (j = 0; j < grntest_job[i].concurrency; j++) {
  1708. if (j == 0) {
  1709. grn_obj line;
  1710. GRN_TEXT_INIT(&line, 0);
  1711. commands = grn_obj_open(ctx, GRN_PVECTOR, 0, GRN_VOID);
  1712. if (!commands) {
  1713. fprintf(stderr, "Cannot alloc commands\n");
  1714. error_exit(ctx, 1);
  1715. }
  1716. fp = fopen(grntest_job[i].commandfile, "r");
  1717. if (!fp) {
  1718. fprintf(stderr, "Cannot alloc commandfile:%s\n",
  1719. grntest_job[i].commandfile);
  1720. error_exit(ctx, 1);
  1721. }
  1722. while (grn_text_fgets(ctx, &line, fp) == GRN_SUCCESS) {
  1723. grn_obj *command;
  1724. if (GRN_TEXT_VALUE(&line)[GRN_TEXT_LEN(&line) - 1] == '\n') {
  1725. grn_bulk_truncate(ctx, &line, GRN_TEXT_LEN(&line) - 1);
  1726. }
  1727. if (GRN_TEXT_LEN(&line) == 0) {
  1728. GRN_BULK_REWIND(&line);
  1729. continue;
  1730. }
  1731. GRN_TEXT_PUTC(ctx, &line, '\0');
  1732. if (comment_p(GRN_TEXT_VALUE(&line))) {
  1733. GRN_BULK_REWIND(&line);
  1734. continue;
  1735. }
  1736. command = grn_obj_open(ctx, GRN_BULK, 0, GRN_VOID);
  1737. if (!command) {
  1738. fprintf(stderr, "Cannot alloc command: %s: %s\n",
  1739. grntest_job[i].commandfile, GRN_TEXT_VALUE(&line));
  1740. GRN_OBJ_FIN(ctx, &line);
  1741. error_exit(ctx, 1);
  1742. }
  1743. GRN_TEXT_SET(ctx, command, GRN_TEXT_VALUE(&line), GRN_TEXT_LEN(&line));
  1744. GRN_PTR_PUT(ctx, commands, command);
  1745. GRN_BULK_REWIND(&line);
  1746. }
  1747. GRN_OBJ_FIN(ctx, &line);
  1748. }
  1749. grntest_task[tid].file = NULL;
  1750. grntest_task[tid].commands = commands;
  1751. grntest_task[tid].ntimes = grntest_job[i].ntimes;
  1752. grntest_task[tid].jobtype = grntest_job[i].jobtype;
  1753. grntest_task[tid].job_id = i;
  1754. tid++;
  1755. }
  1756. }
  1757. return tid;
  1758. }
  1759. /*
  1760. static int
  1761. print_commandlist(int task_id)
  1762. {
  1763. int i;
  1764. for (i = 0; i < GRN_TEXT_LEN(grntest_task[task_id].commands); i++) {
  1765. grn_obj *command;
  1766. command = GRN_PTR_VALUE_AT(grntest_task[task_id].commands, i);
  1767. printf("%s\n", GRN_TEXT_VALUE(command));
  1768. }
  1769. return 0;
  1770. }
  1771. */
  1772. /* return num of query */
  1773. static int
  1774. do_jobs(grn_ctx *ctx, int jobnum, int line)
  1775. {
  1776. int i, task_num, ret, qnum = 0, thread_num = 0;
  1777. for (i = 0; i < jobnum; i++) {
  1778. /*
  1779. printf("%d:type =%d:file=%s:con=…

Large files files are truncated, but you can click here to view the full file