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