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 8000 : test(DBPROCESS *dbproc)
37 : {
38 : int i;
39 : char teststr[1024];
40 : DBINT testint;
41 :
42 :
43 : /* printf("select\n"); */
44 8000 : dbcmd(dbproc, "select * from dblib_thread order by i");
45 8000 : dbsqlexec(dbproc);
46 :
47 8000 : if (dbresults(dbproc) != SUCCEED) {
48 0 : printf("Was expecting a result set.\n");
49 : set_failed();
50 0 : return 1;
51 : }
52 :
53 8000 : if (SUCCEED != dbbind(dbproc, 1, INTBIND, 0, (BYTE *) & testint)) {
54 0 : fprintf(stderr, "Had problem with bind\n");
55 0 : abort();
56 : }
57 8000 : if (SUCCEED != dbbind(dbproc, 2, STRINGBIND, 0, (BYTE *) teststr)) {
58 0 : fprintf(stderr, "Had problem with bind\n");
59 0 : abort();
60 : }
61 :
62 160000 : for (i = 0; i < ROWS; i++) {
63 : char expected[64];
64 :
65 160000 : sprintf(expected, "row %d", i);
66 :
67 160000 : memset(teststr, 'x', sizeof(teststr));
68 160000 : teststr[0] = 0;
69 160000 : teststr[sizeof(teststr) - 1] = 0;
70 160000 : if (REG_ROW != dbnextrow(dbproc)) {
71 0 : fprintf(stderr, "Failed. Expected a row\n");
72 : set_failed();
73 0 : return 1;
74 : }
75 160000 : if (testint != i) {
76 0 : fprintf(stderr, "Failed. Expected i to be %d, was %d\n", i, (int) testint);
77 0 : abort();
78 : }
79 160000 : 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 8000 : 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 8000 : dbcancel(dbproc);
94 :
95 8000 : return 0;
96 : }
97 :
98 80 : static TDS_THREAD_PROC_DECLARE(thread_test, arg)
99 : {
100 : int i;
101 80 : int num = TDS_PTR2INT(arg);
102 : DBPROCESS *dbproc;
103 : LOGINREC *login;
104 :
105 80 : login = dblogin();
106 80 : DBSETLPWD(login, PASSWORD);
107 80 : DBSETLUSER(login, USER);
108 80 : DBSETLAPP(login, "thread");
109 :
110 80 : dbproc = dbopen(login, SERVER);
111 80 : 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 80 : dbloginfree(login);
118 :
119 80 : if (strlen(DATABASE))
120 80 : dbuse(dbproc, DATABASE);
121 :
122 80 : tds_mutex_lock(&mutex);
123 80 : ++thread_count;
124 80 : tds_mutex_unlock(&mutex);
125 :
126 80 : printf("thread %2d waiting for all threads to start\n", num+1);
127 80 : tds_mutex_lock(&mutex);
128 7431 : while (thread_count < NUM_THREAD) {
129 7271 : tds_mutex_unlock(&mutex);
130 7271 : tds_sleep_ms(50);
131 7271 : tds_mutex_lock(&mutex);
132 : }
133 80 : tds_mutex_unlock(&mutex);
134 :
135 8080 : for (i = 1; i <= NUM_LOOP; ++i) {
136 8000 : printf("thread %2d of %2d loop %d\n", num+1, NUM_THREAD, i);
137 8000 : if (test(dbproc) || result != 0)
138 : break;
139 : }
140 :
141 80 : dbclose(dbproc);
142 80 : return TDS_THREAD_RESULT(0);
143 : }
144 :
145 : int
146 8 : main(int argc, char **argv)
147 : {
148 : int i;
149 : tds_thread th[NUM_THREAD];
150 : DBPROCESS *dbproc;
151 : LOGINREC *login;
152 :
153 8 : read_login_info(argc, argv);
154 :
155 8 : printf("Starting %s\n", argv[0]);
156 :
157 8 : dbinit();
158 :
159 8 : dberrhandle(syb_err_handler);
160 8 : dbmsghandle(syb_msg_handler);
161 :
162 8 : printf("About to logon\n");
163 :
164 8 : login = dblogin();
165 8 : DBSETLPWD(login, PASSWORD);
166 8 : DBSETLUSER(login, USER);
167 8 : DBSETLAPP(login, "thread");
168 :
169 8 : printf("About to open \"%s\"\n", SERVER);
170 :
171 8 : dbproc = dbopen(login, SERVER);
172 8 : if (!dbproc) {
173 0 : fprintf(stderr, "Unable to connect to %s\n", SERVER);
174 0 : return 1;
175 : }
176 :
177 8 : dbloginfree(login);
178 :
179 8 : if (strlen(DATABASE))
180 8 : dbuse(dbproc, DATABASE);
181 :
182 8 : printf("Dropping table\n");
183 8 : dbcmd(dbproc, "if object_id('dblib_thread') is not null drop table dblib_thread");
184 8 : dbsqlexec(dbproc);
185 8 : while (dbresults(dbproc) == SUCCEED) {
186 : /* nop */
187 : }
188 :
189 8 : printf("creating table\n");
190 8 : dbcmd(dbproc, "create table dblib_thread (i int not null, s char(10) not null)");
191 8 : dbsqlexec(dbproc);
192 8 : while (dbresults(dbproc) == SUCCEED) {
193 : /* nop */
194 : }
195 :
196 8 : printf("insert\n");
197 168 : for (i = 0; i < ROWS; i++) {
198 : char cmd[128];
199 :
200 160 : sprintf(cmd, "insert into dblib_thread values (%d, 'row %d')", i, i);
201 160 : dbcmd(dbproc, cmd);
202 160 : dbsqlexec(dbproc);
203 160 : while (dbresults(dbproc) == SUCCEED) {
204 : /* nop */
205 : }
206 : }
207 :
208 80 : for (i = 0; i < NUM_THREAD; ++i) {
209 160 : int err = tds_thread_create(&th[i], thread_test, TDS_INT2PTR(i));
210 80 : 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 80 : tds_sleep_s(1);
217 : }
218 :
219 80 : for (i = 0; i < NUM_THREAD; ++i) {
220 160 : tds_thread_join(th[i], NULL);
221 80 : printf("thread: %d exited\n", i + 1);
222 : }
223 :
224 8 : printf("Dropping table\n");
225 8 : dbcmd(dbproc, "drop table dblib_thread");
226 8 : dbsqlexec(dbproc);
227 8 : while (dbresults(dbproc) == SUCCEED) {
228 : /* nop */
229 : }
230 :
231 8 : dbexit();
232 :
233 8 : 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
|