Line data Source code
1 : /*
2 : * Purpose: Test dblib thread safety
3 : */
4 :
5 : #include "common.h"
6 : #include <freetds/thread.h>
7 : #include <freetds/utils.h>
8 : #include <freetds/macros.h>
9 :
10 : #ifdef HAVE_UNISTD_H
11 : #include <unistd.h>
12 : #endif
13 :
14 : #include <freetds/replacements.h>
15 :
16 : #ifdef TDS_HAVE_MUTEX
17 :
18 : static tds_mutex mutex = TDS_MUTEX_INITIALIZER;
19 :
20 : static int result = 0;
21 : static int thread_count = 0;
22 :
23 : #define ROWS 20
24 : #define NUM_THREAD 10
25 : #define NUM_LOOP 100
26 :
27 : static void
28 : set_failed(void)
29 : {
30 0 : tds_mutex_lock(&mutex);
31 0 : result = 1;
32 0 : tds_mutex_unlock(&mutex);
33 : }
34 :
35 : static int
36 10000 : test(DBPROCESS *dbproc)
37 : {
38 : int i;
39 : char teststr[1024];
40 : DBINT testint;
41 :
42 :
43 : /* printf("select\n"); */
44 10000 : dbcmd(dbproc, "select * from dblib_thread order by i");
45 10000 : dbsqlexec(dbproc);
46 :
47 10000 : if (dbresults(dbproc) != SUCCEED) {
48 0 : printf("Was expecting a result set.\n");
49 : set_failed();
50 0 : return 1;
51 : }
52 :
53 10000 : if (SUCCEED != dbbind(dbproc, 1, INTBIND, 0, (BYTE *) & testint)) {
54 0 : fprintf(stderr, "Had problem with bind\n");
55 0 : abort();
56 : }
57 10000 : if (SUCCEED != dbbind(dbproc, 2, STRINGBIND, 0, (BYTE *) teststr)) {
58 0 : fprintf(stderr, "Had problem with bind\n");
59 0 : abort();
60 : }
61 :
62 200000 : for (i = 0; i < ROWS; i++) {
63 : char expected[64];
64 :
65 200000 : sprintf(expected, "row %d", i);
66 :
67 200000 : memset(teststr, 'x', sizeof(teststr));
68 200000 : teststr[0] = 0;
69 200000 : teststr[sizeof(teststr) - 1] = 0;
70 200000 : if (REG_ROW != dbnextrow(dbproc)) {
71 0 : fprintf(stderr, "Failed. Expected a row\n");
72 : set_failed();
73 0 : return 1;
74 : }
75 200000 : if (testint != i) {
76 0 : fprintf(stderr, "Failed. Expected i to be %d, was %d\n", i, (int) testint);
77 0 : abort();
78 : }
79 200000 : if (0 != strncmp(teststr, expected, strlen(expected))) {
80 0 : printf("Failed. Expected s to be |%s|, was |%s|\n", expected, teststr);
81 0 : abort();
82 : }
83 : /* printf("Read a row of data -> %d |%s|\n", (int) testint, teststr); */
84 : }
85 :
86 :
87 10000 : if (dbnextrow(dbproc) != NO_MORE_ROWS) {
88 0 : fprintf(stderr, "Was expecting no more rows\n");
89 : set_failed();
90 0 : return 1;
91 : }
92 :
93 10000 : dbcancel(dbproc);
94 :
95 10000 : return 0;
96 : }
97 :
98 100 : static TDS_THREAD_PROC_DECLARE(thread_test, arg)
99 : {
100 : int i;
101 100 : int num = TDS_PTR2INT(arg);
102 : DBPROCESS *dbproc;
103 : LOGINREC *login;
104 :
105 100 : login = dblogin();
106 100 : DBSETLPWD(login, PASSWORD);
107 100 : DBSETLUSER(login, USER);
108 100 : DBSETLAPP(login, "thread");
109 :
110 100 : dbproc = dbopen(login, SERVER);
111 100 : if (!dbproc) {
112 0 : dbloginfree(login);
113 0 : fprintf(stderr, "Unable to connect to %s\n", SERVER);
114 : set_failed();
115 0 : return TDS_THREAD_RESULT(0);
116 : }
117 100 : dbloginfree(login);
118 :
119 100 : if (strlen(DATABASE))
120 100 : dbuse(dbproc, DATABASE);
121 :
122 100 : tds_mutex_lock(&mutex);
123 100 : ++thread_count;
124 100 : tds_mutex_unlock(&mutex);
125 :
126 100 : printf("thread %2d waiting for all threads to start\n", num+1);
127 100 : tds_mutex_lock(&mutex);
128 9295 : while (thread_count < NUM_THREAD) {
129 9095 : tds_mutex_unlock(&mutex);
130 9095 : tds_sleep_ms(50);
131 9095 : tds_mutex_lock(&mutex);
132 : }
133 100 : tds_mutex_unlock(&mutex);
134 :
135 10100 : for (i = 1; i <= NUM_LOOP; ++i) {
136 10000 : printf("thread %2d of %2d loop %d\n", num+1, NUM_THREAD, i);
137 10000 : if (test(dbproc) || result != 0)
138 : break;
139 : }
140 :
141 100 : dbclose(dbproc);
142 100 : return TDS_THREAD_RESULT(0);
143 : }
144 :
145 : int
146 10 : main(int argc, char **argv)
147 : {
148 : int i;
149 : tds_thread th[NUM_THREAD];
150 : DBPROCESS *dbproc;
151 : LOGINREC *login;
152 :
153 10 : read_login_info(argc, argv);
154 :
155 10 : printf("Starting %s\n", argv[0]);
156 :
157 10 : dbinit();
158 :
159 10 : dberrhandle(syb_err_handler);
160 10 : dbmsghandle(syb_msg_handler);
161 :
162 10 : printf("About to logon\n");
163 :
164 10 : login = dblogin();
165 10 : DBSETLPWD(login, PASSWORD);
166 10 : DBSETLUSER(login, USER);
167 10 : DBSETLAPP(login, "thread");
168 :
169 10 : printf("About to open \"%s\"\n", SERVER);
170 :
171 10 : dbproc = dbopen(login, SERVER);
172 10 : if (!dbproc) {
173 0 : fprintf(stderr, "Unable to connect to %s\n", SERVER);
174 0 : return 1;
175 : }
176 :
177 10 : dbloginfree(login);
178 :
179 10 : if (strlen(DATABASE))
180 10 : dbuse(dbproc, DATABASE);
181 :
182 10 : printf("Dropping table\n");
183 10 : dbcmd(dbproc, "if object_id('dblib_thread') is not null drop table dblib_thread");
184 10 : dbsqlexec(dbproc);
185 10 : while (dbresults(dbproc) == SUCCEED) {
186 : /* nop */
187 : }
188 :
189 10 : printf("creating table\n");
190 10 : dbcmd(dbproc, "create table dblib_thread (i int not null, s char(10) not null)");
191 10 : dbsqlexec(dbproc);
192 10 : while (dbresults(dbproc) == SUCCEED) {
193 : /* nop */
194 : }
195 :
196 10 : printf("insert\n");
197 210 : for (i = 0; i < ROWS; i++) {
198 : char cmd[128];
199 :
200 200 : sprintf(cmd, "insert into dblib_thread values (%d, 'row %d')", i, i);
201 200 : dbcmd(dbproc, cmd);
202 200 : dbsqlexec(dbproc);
203 200 : while (dbresults(dbproc) == SUCCEED) {
204 : /* nop */
205 : }
206 : }
207 :
208 100 : for (i = 0; i < NUM_THREAD; ++i) {
209 200 : int err = tds_thread_create(&th[i], thread_test, TDS_INT2PTR(i));
210 100 : if (err != 0)
211 : {
212 0 : fprintf(stderr, "Error %d (%s) creating thread\n", err, strerror(err));
213 0 : return 1;
214 : }
215 : /* MSSQL rejects the connections if they come in too fast */
216 100 : tds_sleep_s(1);
217 : }
218 :
219 100 : for (i = 0; i < NUM_THREAD; ++i) {
220 200 : tds_thread_join(th[i], NULL);
221 100 : printf("thread: %d exited\n", i + 1);
222 : }
223 :
224 10 : printf("Dropping table\n");
225 10 : dbcmd(dbproc, "drop table dblib_thread");
226 10 : dbsqlexec(dbproc);
227 10 : while (dbresults(dbproc) == SUCCEED) {
228 : /* nop */
229 : }
230 :
231 10 : dbexit();
232 :
233 10 : return result;
234 : }
235 :
236 : #else /* !TDS_HAVE_PTHREAD_MUTEX */
237 :
238 : int
239 : main(int argc, char **argv)
240 : {
241 : printf("Not possible for this platform.\n");
242 : return 0;
243 : }
244 : #endif
|