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