3 * Copyright (c) 2002-2004 MontaVista Software, Inc.
4 * Copyright (c) 2006 Sun Microsystems, Inc.
8 * Author: Steven Dake (sdake@mvista.com)
10 * This software licensed under BSD license, the text of which follows:
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
15 * - Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 * - Neither the name of the MontaVista Software, Inc. nor the names of its
21 * contributors may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGE.
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <sys/select.h>
56 #ifdef OPENAIS_SOLARIS
57 #define timersub(a, b, result) \
59 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
60 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
61 if ((result)->tv_usec < 0) { \
63 (result)->tv_usec += 1000000; \
70 void fail_on_error(SaAisErrorT error
, char* opName
) {
71 if (error
!= SA_AIS_OK
) {
72 printf ("%s: result %s\n", opName
, get_sa_error_b(error
));
77 void printSaNameT (SaNameT
*name
)
81 for (i
= 0; i
< name
->length
; i
++) {
82 printf ("%c", name
->value
[i
]);
86 SaVersionT version
= { 'B', 1, 1 };
88 SaCkptCallbacksT callbacks
= {
93 SaCkptCheckpointCreationAttributesT checkpointCreationAttributes
= {
94 .creationFlags
= SA_CKPT_WR_ALL_REPLICAS
,
95 .checkpointSize
= 100000,
96 .retentionDuration
= 0,
98 .maxSectionSize
= 150000,
99 .maxSectionIdSize
= 15
102 SaCkptSectionIdT sectionId1
= {
104 (SaUint8T
*) "section ID #1"
107 SaCkptSectionIdT sectionId2
= {
109 (SaUint8T
*) "section ID #2"
111 SaCkptSectionCreationAttributesT sectionCreationAttributes1
= {
116 SaCkptSectionCreationAttributesT sectionCreationAttributes2
= {
121 char readBuffer1
[1025];
123 char readBuffer2
[1025];
125 SaCkptIOVectorElementT ReadVectorElements
[] = {
129 (SaUint8T
*) "section ID #1"
132 sizeof (readBuffer1
),
139 (SaUint8T
*) "section ID #2"
142 sizeof (readBuffer2
),
148 #define DATASIZE 1000
152 SaCkptIOVectorElementT WriteVectorElements
[] = {
156 (SaUint8T
*) "section ID #1"
158 data
, /*"written data #1, this should extend past end of old section data", */
159 DATASIZE
, /*sizeof ("data #1, this should extend past end of old section data") + 1, */
167 (SaUint8T
*) "section ID #2"
169 data
, /*"written data #2, this should extend past end of old section data" */
170 DATASIZE
, /*sizeof ("written data #2, this should extend past end of old section data") + 1, */
180 SaCkptHandleT ckpt_handle
;
181 SaCkptCheckpointHandleT checkpoint_handle
;
184 pthread_attr_t thread_attr
;
189 extern void pthread_exit(void *) __attribute__((noreturn
));
191 void *benchmark_thread (void *arg
)
194 SaCkptCheckpointHandleT checkpoint_handle
;
195 SaCkptHandleT ckpt_handle
;
198 SaUint32T erroroneousVectorIndex
= 0;
199 struct threaddata
*td
= (struct threaddata
*)arg
;
201 checkpoint_handle
= td
->checkpoint_handle
;
202 ckpt_handle
= td
->ckpt_handle
;
203 write_size
= td
->write_size
;
205 WriteVectorElements
[0].dataSize
= write_size
;
209 * Test checkpoint write
212 error
= saCkptCheckpointWrite (checkpoint_handle
,
215 &erroroneousVectorIndex
);
216 } while (error
== SA_AIS_ERR_TRY_AGAIN
);
217 fail_on_error(error
, "saCkptCheckpointWrite");
219 } while (alarm_notice
== 0);
224 void threaded_bench (
225 SaCkptHandleT
*ckpt_handles
,
226 SaCkptCheckpointHandleT
*checkpoint_handles
,
230 struct timeval tv1
, tv2
, tv_elapsed
;
231 struct threaddata td
[100];
237 gettimeofday (&tv1
, NULL
);
239 for (i
= 0; i
< threads
; i
++) {
240 td
[i
].ckpt_handle
= ckpt_handles
[i
];
241 td
[i
].checkpoint_handle
= checkpoint_handles
[i
];
242 td
[i
].write_size
= write_size
;
245 pthread_attr_init (&td
[i
].thread_attr
);
246 pthread_attr_setstacksize (&td
[i
].thread_attr
, 16384);
247 pthread_attr_setdetachstate (&td
[i
].thread_attr
, PTHREAD_CREATE_JOINABLE
);
249 res
= pthread_create (&td
[i
].thread_id
, &td
[i
].thread_attr
,
250 benchmark_thread
, (void *)&td
[i
]);
253 for (i
= 0; i
< threads
; i
++) {
254 pthread_join (td
[i
].thread_id
, NULL
);
255 written
+= td
[i
].written
;
259 gettimeofday (&tv2
, NULL
);
260 timersub (&tv2
, &tv1
, &tv_elapsed
);
262 printf ("%5d Writes ", written
);
263 printf ("%5d bytes per write ", write_size
);
264 printf ("%7.3f Seconds runtime ",
265 (tv_elapsed
.tv_sec
+ (tv_elapsed
.tv_usec
/ 1000000.0)));
266 printf ("%9.3f TP/s ",
267 ((float)written
) / (tv_elapsed
.tv_sec
+ (tv_elapsed
.tv_usec
/ 1000000.0)));
268 printf ("%7.3f MB/s.\n",
269 ((float)written
) * ((float)write_size
) / ((tv_elapsed
.tv_sec
+ (tv_elapsed
.tv_usec
/ 1000000.0)) * 1000000.0));
272 SaNameT checkpointName
;
274 #define CHECKPOINT_THREADS_START 25
275 #define CHECKPOINT_THREADS_MAX 500
277 void sigalrm_handler (int num
)
284 SaCkptHandleT ckpt_handles
[CHECKPOINT_THREADS_MAX
];
285 SaCkptCheckpointHandleT checkpoint_handles
[CHECKPOINT_THREADS_MAX
];
290 signal (SIGALRM
, sigalrm_handler
);
292 printf ("Creating (%d) checkpoints.\n", CHECKPOINT_THREADS_MAX
);
294 * Create CHECPOINT_THREADS_MAX checkpoints
296 for (i
= 0; i
< CHECKPOINT_THREADS_MAX
; i
++) {
297 sprintf ((char *)checkpointName
.value
, "checkpoint (%d)", i
);
298 checkpointName
.length
= strlen ((char *)checkpointName
.value
);
300 error
= saCkptInitialize (&ckpt_handles
[i
], &callbacks
, &version
);
301 } while (error
== SA_AIS_ERR_TRY_AGAIN
);
302 assert (error
== SA_AIS_OK
);
305 error
= saCkptCheckpointOpen (ckpt_handles
[i
],
307 &checkpointCreationAttributes
,
308 SA_CKPT_CHECKPOINT_CREATE
|SA_CKPT_CHECKPOINT_READ
|SA_CKPT_CHECKPOINT_WRITE
,
310 &checkpoint_handles
[i
]);
311 } while (error
== SA_AIS_ERR_TRY_AGAIN
);
312 assert (error
== SA_AIS_OK
);
315 error
= saCkptSectionCreate (checkpoint_handles
[i
],
316 §ionCreationAttributes1
,
318 strlen ("Initial Data #0") + 1);
319 } while (error
== SA_AIS_ERR_TRY_AGAIN
);
320 assert (error
== SA_AIS_OK
);
323 error
= saCkptSectionCreate (checkpoint_handles
[i
],
324 §ionCreationAttributes2
,
326 strlen ("Initial Data #0") + 1);
327 } while (error
== SA_AIS_ERR_TRY_AGAIN
);
328 assert (error
== SA_AIS_OK
);
331 for (i
= CHECKPOINT_THREADS_START
; i
< CHECKPOINT_THREADS_MAX
; i
++) { /* i threads */
332 printf ("Starting benchmark with (%d) threads.\n", i
);
333 size
= 10000; /* initial size */
334 for (j
= 0; j
< 5; j
++) { /* number of runs with i threads */
336 threaded_bench (ckpt_handles
, checkpoint_handles
, i
, size
);