1 : /* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
2 :
3 : This program is free software; you can redistribute it and/or modify
4 : it under the terms of the GNU General Public License as published by
5 : the Free Software Foundation; version 2 of the License.
6 :
7 : This program is distributed in the hope that it will be useful,
8 : but WITHOUT ANY WARRANTY; without even the implied warranty of
9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 : GNU General Public License for more details.
11 :
12 : You should have received a copy of the GNU General Public License
13 : along with this program; if not, write to the Free Software
14 : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15 :
16 : #include <tap.h>
17 :
18 : #include <my_global.h>
19 : #include <my_sys.h>
20 : #include <my_atomic.h>
21 : #include <lf.h>
22 : #include <m_string.h>
23 : #include "../trnman.h"
24 :
25 : pthread_mutex_t rt_mutex;
26 : pthread_attr_t attr;
27 : size_t stacksize= 0;
28 : #define STACK_SIZE (((int)stacksize-2048)*STACK_DIRECTION)
29 :
30 : int rt_num_threads;
31 : int litmus;
32 :
33 : /*
34 : create and end (commit or rollback) transactions randomly
35 : */
36 : #define MAX_ITER 100
37 : pthread_handler_t test_trnman(void *arg)
38 10 : {
39 : uint x, y, i, n;
40 : TRN *trn[MAX_ITER];
41 10 : int m= (*(int *)arg);
42 :
43 10 : if (my_thread_init())
44 0 : BAIL_OUT("my_thread_init failed!");
45 :
46 2060 : for (x= ((int)(intptr)(&m)); m > 0; )
47 : {
48 2040 : y= x= (x*LL(3628273133) + LL(1500450271)) % LL(9576890767); /* three prime numbers */
49 2040 : m-= n= x % MAX_ITER;
50 102402 : for (i= 0; i < n; i++)
51 : {
52 100362 : trn[i]= trnman_new_trn(0);
53 100362 : if (!trn[i])
54 : {
55 0 : diag("trnman_new_trn() failed");
56 0 : litmus++;
57 : }
58 : }
59 102402 : for (i= 0; i < n; i++)
60 : {
61 100362 : y= (y*19 + 7) % 31;
62 100362 : trnman_end_trn(trn[i], y & 1);
63 : }
64 : }
65 10 : pthread_mutex_lock(&rt_mutex);
66 10 : rt_num_threads--;
67 10 : pthread_mutex_unlock(&rt_mutex);
68 :
69 10 : my_thread_end();
70 :
71 10 : return 0;
72 : }
73 : #undef MAX_ITER
74 :
75 : void run_test(const char *test, pthread_handler handler, int n, int m)
76 1 : {
77 : pthread_t *threads;
78 1 : ulonglong now= my_getsystime();
79 : int i;
80 :
81 1 : litmus= 0;
82 :
83 1 : threads= (pthread_t *)my_malloc(sizeof(void *)*n, MYF(0));
84 1 : if (!threads)
85 : {
86 0 : diag("Out of memory");
87 0 : abort();
88 : }
89 :
90 1 : diag("Testing %s with %d threads, %d iterations... ", test, n, m);
91 1 : rt_num_threads= n;
92 11 : for (i= 0; i < n ; i++)
93 10 : if (pthread_create(threads+i, &attr, handler, &m))
94 : {
95 0 : diag("Could not create thread");
96 0 : abort();
97 : }
98 11 : for (i= 0 ; i < n ; i++)
99 10 : pthread_join(threads[i], 0);
100 1 : now= my_getsystime()-now;
101 1 : ok(litmus == 0, "Tested %s in %g secs (%d)", test, ((double)now)/1e7, litmus);
102 1 : my_free((void*)threads, MYF(0));
103 : }
104 :
105 : #define ok_read_from(T1, T2, RES) \
106 : i= trnman_can_read_from(trn[T1], trid[T2]); \
107 : ok(i == RES, "trn" #T1 " %s read from trn" #T2, i ? "can" : "cannot")
108 : #define start_transaction(T) \
109 : trn[T]= trnman_new_trn(0); \
110 : trid[T]= trn[T]->trid
111 : #define commit(T) trnman_commit_trn(trn[T])
112 : #define abort(T) trnman_abort_trn(trn[T])
113 :
114 : #define Ntrns 4
115 : void test_trnman_read_from()
116 1 : {
117 : TRN *trn[Ntrns];
118 : TrID trid[Ntrns];
119 : int i;
120 :
121 1 : start_transaction(0); /* start trn1 */
122 1 : start_transaction(1); /* start trn2 */
123 1 : ok_read_from(1, 0, 0);
124 1 : commit(0); /* commit trn1 */
125 1 : start_transaction(2); /* start trn4 */
126 1 : abort(2); /* abort trn4 */
127 1 : start_transaction(3); /* start trn5 */
128 1 : ok_read_from(3, 0, 1);
129 1 : ok_read_from(3, 1, 0);
130 1 : ok_read_from(3, 2, 0);
131 1 : ok_read_from(3, 3, 1);
132 1 : commit(1); /* commit trn2 */
133 1 : ok_read_from(3, 1, 0);
134 1 : commit(3); /* commit trn5 */
135 :
136 : }
137 :
138 : int main(int argc __attribute__((unused)), char **argv)
139 1 : {
140 1 : MY_INIT(argv[0]);
141 :
142 1 : plan(7);
143 :
144 1 : if (my_atomic_initialize())
145 0 : return exit_status();
146 :
147 1 : pthread_mutex_init(&rt_mutex, 0);
148 1 : pthread_attr_init(&attr);
149 : #ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
150 1 : pthread_attr_getstacksize(&attr, &stacksize);
151 1 : if (stacksize == 0)
152 : #endif
153 0 : stacksize= PTHREAD_STACK_MIN;
154 :
155 : #define CYCLES 10000
156 : #define THREADS 10
157 :
158 1 : trnman_init(0);
159 :
160 1 : test_trnman_read_from();
161 1 : run_test("trnman", test_trnman, THREADS, CYCLES);
162 :
163 1 : diag("mallocs: %d", trnman_allocated_transactions);
164 : {
165 1 : ulonglong now= my_getsystime();
166 1 : trnman_destroy();
167 1 : now= my_getsystime()-now;
168 1 : diag("trnman_destroy: %g", ((double)now)/1e7);
169 : }
170 :
171 1 : pthread_mutex_destroy(&rt_mutex);
172 1 : my_end(0);
173 1 : return exit_status();
174 : }
175 :
|