Line data Source code
1 : #include <config.h>
2 :
3 : #include <stdio.h>
4 :
5 : #include <freetds/time.h>
6 :
7 : #include <sys/types.h>
8 :
9 : #if HAVE_UNISTD_H
10 : #include <unistd.h>
11 : #endif /* HAVE_UNISTD_H */
12 :
13 : #include <signal.h>
14 : #include <ctpublic.h>
15 : #include "common.h"
16 :
17 : #if defined(HAVE_ALARM) && defined(HAVE_SETITIMER)
18 :
19 : /* protos */
20 : int do_fetch(CS_COMMAND * cmd, int *cnt);
21 : void catch_alrm(int);
22 :
23 : /* Globals */
24 : static volatile CS_COMMAND *g_cmd = NULL;
25 :
26 : void
27 52 : catch_alrm(int sig_num)
28 : {
29 52 : signal(SIGALRM, catch_alrm);
30 :
31 52 : printf("- SIGALRM\n");
32 :
33 : /* Cancel current command */
34 52 : if (g_cmd)
35 52 : ct_cancel(NULL, (CS_COMMAND *) g_cmd, CS_CANCEL_ATTN);
36 :
37 52 : fflush(stdout);
38 52 : }
39 :
40 : /* Testing: Test asynchronous ct_cancel() */
41 : int
42 8 : main(int argc, char **argv)
43 : {
44 : CS_CONTEXT *ctx;
45 : CS_CONNECTION *conn;
46 : CS_COMMAND *cmd;
47 8 : int i, verbose = 0, cnt = 0;
48 :
49 : CS_RETCODE ret;
50 : CS_INT result_type;
51 :
52 : struct itimerval timer;
53 : char query[1024];
54 :
55 8 : unsigned clock = 200000;
56 :
57 8 : printf("%s: Check asynchronous called ct_cancel()\n", __FILE__);
58 : if (verbose) {
59 : printf("Trying login\n");
60 : }
61 8 : ret = try_ctlogin(&ctx, &conn, &cmd, verbose);
62 8 : if (ret != CS_SUCCEED) {
63 0 : fprintf(stderr, "Login failed\n");
64 0 : return 1;
65 : }
66 :
67 : /* Create needed tables */
68 8 : ret = run_command(cmd, "CREATE TABLE #t0010 (id int, col1 varchar(255))");
69 8 : if (ret != CS_SUCCEED)
70 : return 1;
71 :
72 80 : for (i = 0; i < 10; i++) {
73 80 : sprintf(query, "INSERT #t0010 (id, col1) values (%d, 'This is field no %d')", i, i);
74 :
75 80 : ret = run_command(cmd, query);
76 80 : if (ret != CS_SUCCEED)
77 : return 1;
78 : }
79 :
80 : /* Set SIGALRM signal handler */
81 8 : signal(SIGALRM, catch_alrm);
82 :
83 : for (;;) {
84 : /* TODO better to use alarm AFTER ct_send ?? */
85 : /* Set timer */
86 8 : timer.it_interval.tv_sec = 0;
87 8 : timer.it_interval.tv_usec = clock;
88 8 : timer.it_value.tv_sec = 0;
89 8 : timer.it_value.tv_usec = clock;
90 8 : if (0 != setitimer(ITIMER_REAL, &timer, NULL)) {
91 0 : fprintf(stderr, "Could not set realtime timer.\n");
92 0 : return 1;
93 : }
94 :
95 : /* Issue a command returning many rows */
96 8 : ret = ct_command(cmd, CS_LANG_CMD, "SELECT * FROM #t0010 t1, #t0010 t2, #t0010 t3, #t0010 t4", CS_NULLTERM, CS_UNUSED);
97 8 : if (ret != CS_SUCCEED) {
98 0 : fprintf(stderr, "ct_command() failed.\n");
99 0 : return 1;
100 : }
101 :
102 8 : ret = ct_send(cmd);
103 8 : if (ret != CS_SUCCEED) {
104 0 : fprintf(stderr, "first ct_send() failed.\n");
105 0 : return 1;
106 : }
107 :
108 : /* Save a global reference for the interrupt handler */
109 8 : g_cmd = cmd;
110 :
111 24 : while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
112 8 : printf("More results?...\n");
113 8 : if (result_type == CS_STATUS_RESULT)
114 0 : continue;
115 :
116 8 : switch ((int) result_type) {
117 8 : case CS_ROW_RESULT:
118 8 : printf("do_fetch() returned: %d\n", do_fetch(cmd, &cnt));
119 8 : break;
120 : }
121 : }
122 :
123 : /* We should not have received all rows, as the alarm signal cancelled it... */
124 8 : if (cnt < 10000)
125 : break;
126 :
127 0 : if (clock <= 5000) {
128 0 : fprintf(stderr, "All rows read, this may not occur.\n");
129 0 : return 1;
130 : }
131 0 : g_cmd = NULL;
132 0 : clock /= 2;
133 : }
134 :
135 : /* Remove timer */
136 8 : timer.it_interval.tv_sec = 0;
137 8 : timer.it_interval.tv_usec = 0;
138 8 : timer.it_value.tv_sec = 0;
139 8 : timer.it_value.tv_usec = 0;
140 8 : if (0 != setitimer(ITIMER_REAL, &timer, NULL)) {
141 0 : fprintf(stderr, "Could not remove realtime timer.\n");
142 0 : return 1;
143 : }
144 :
145 : /*
146 : * Issue another command, this will be executed after a ct_cancel,
147 : * to test if wire state is consistent
148 : */
149 8 : ret = ct_command(cmd, CS_LANG_CMD, "SELECT * FROM #t0010 t1, #t0010 t2, #t0010 t3", CS_NULLTERM, CS_UNUSED);
150 8 : if (ret != CS_SUCCEED) {
151 0 : fprintf(stderr, "ct_command() failed.\n");
152 0 : return 1;
153 : }
154 :
155 8 : ret = ct_send(cmd);
156 8 : if (ret != CS_SUCCEED) {
157 0 : fprintf(stderr, "second ct_send() failed.\n");
158 0 : return 1;
159 : }
160 :
161 24 : while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
162 16 : printf("More results?...\n");
163 16 : if (result_type == CS_STATUS_RESULT)
164 0 : continue;
165 :
166 16 : switch ((int) result_type) {
167 8 : case CS_ROW_RESULT:
168 8 : printf("do_fetch() returned: %d\n", do_fetch(cmd, &cnt));
169 8 : break;
170 : }
171 : }
172 :
173 8 : if (1000 != cnt) {
174 : /* This time, all rows must have been received */
175 0 : fprintf(stderr, "Incorrect number of rows read.\n");
176 0 : return 1;
177 : }
178 :
179 : if (verbose) {
180 : printf("Trying logout\n");
181 : }
182 8 : ret = try_ctlogout(ctx, conn, cmd, verbose);
183 8 : if (ret != CS_SUCCEED) {
184 0 : fprintf(stderr, "Logout failed\n");
185 0 : return 1;
186 : }
187 :
188 8 : printf("%s: asynchronous cancel test: PASSED\n", __FILE__);
189 :
190 8 : return 0;
191 : }
192 :
193 : int
194 16 : do_fetch(CS_COMMAND * cmd, int *cnt)
195 : {
196 16 : CS_INT count, row_count = 0;
197 : CS_RETCODE ret;
198 :
199 13297 : while ((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED) {
200 : /* printf ("ct_fetch() == CS_SUCCEED\n"); */
201 13265 : row_count += count;
202 : }
203 :
204 16 : (*cnt) = row_count;
205 16 : if (ret == CS_ROW_FAIL) {
206 0 : fprintf(stderr, "ct_fetch() CS_ROW_FAIL on row %d.\n", row_count);
207 0 : return 1;
208 16 : } else if (ret == CS_END_DATA) {
209 8 : printf("do_fetch retrieved %d rows\n", row_count);
210 8 : return 0;
211 8 : } else if (ret == CS_CMD_FAIL) {
212 0 : printf("do_fetch(): command aborted after receiving %d rows\n", row_count);
213 0 : return 0;
214 : } else {
215 8 : fprintf(stderr, "ct_fetch() unexpected return %d on row %d.\n", ret, row_count);
216 8 : return 1;
217 : }
218 : }
219 :
220 : #else
221 :
222 : int
223 : main(void)
224 : {
225 : return 0;
226 : }
227 : #endif
228 :
|