1    	/*
2    	 * Copyright (c) 2009 Red Hat, Inc.
3    	 *
4    	 * All rights reserved.
5    	 *
6    	 * Author: Steven Dake (sdake@redhat.com)
7    	 *
8    	 * libqb is free software: you can redistribute it and/or modify
9    	 * it under the terms of the GNU Lesser General Public License as published by
10   	 * the Free Software Foundation, either version 2.1 of the License, or
11   	 * (at your option) any later version.
12   	 *
13   	 * libqb is distributed in the hope that it will be useful,
14   	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   	 * GNU Lesser General Public License for more details.
17   	 *
18   	 * You should have received a copy of the GNU Lesser General Public License
19   	 * along with libqb.  If not, see <http://www.gnu.org/licenses/>.
20   	 */
21   	#include "os_base.h"
22   	#include <signal.h>
23   	
24   	#include <qb/qblog.h>
25   	#include <qb/qbutil.h>
26   	#include <qb/qbipcc.h>
27   	
28   	#define ITERATIONS 10000
29   	pid_t mypid;
30   	int32_t blocking = QB_TRUE;
31   	int32_t events = QB_FALSE;
32   	int32_t verbose = 0;
33   	static qb_ipcc_connection_t *conn;
34   	#define MAX_MSG_SIZE (8192*128)
35   	static qb_util_stopwatch_t *sw;
36   	
37   	static void bm_finish(const char *operation, int32_t size)
38   	{
39   		float ops_per_sec;
40   		float mbs_per_sec;
41   		float elapsed;
42   	
43   		qb_util_stopwatch_stop(sw);
(1) Event zero_return: Function call "qb_util_stopwatch_sec_elapsed_get(sw)" returns 0.0. [details]
(2) Event assign: Assigning: "elapsed" = "qb_util_stopwatch_sec_elapsed_get(sw)".
Also see events: [divide_by_zero]
44   		elapsed = qb_util_stopwatch_sec_elapsed_get(sw);
45   		ops_per_sec = ((float)ITERATIONS) / elapsed;
(3) Event divide_by_zero: In expression "10000f * size / elapsed", division by expression "elapsed" which may be zero results in either +infinity, -infinity, or NaN.
Also see events: [zero_return][assign]
46   		mbs_per_sec = ((((float)ITERATIONS) * size) / elapsed) / (1024.0 * 1024.0);
47   	
48   		qb_log(LOG_INFO, "write size, %d, OPs/sec, %9.3f, MB/sec, %9.3f",
49   		       size, ops_per_sec, mbs_per_sec);
50   	}
51   	
52   	struct my_req {
53   		struct qb_ipc_request_header hdr;
54   		char message[1024 * 1024];
55   	};
56   	
57   	static struct my_req request;
58   	
59   	static int32_t bmc_send_nozc(uint32_t size)
60   	{
61   		struct qb_ipc_response_header res_header;
62   		int32_t res;
63   	
64   		request.hdr.id = QB_IPC_MSG_USER_START + 3;
65   		request.hdr.size = sizeof(struct qb_ipc_request_header) + size;
66   	
67   	repeat_send:
68   		res = qb_ipcc_send(conn, &request, request.hdr.size);
69   		if (res < 0) {
70   			if (res == -EAGAIN) {
71   				goto repeat_send;
72   			} else if (res == -EINVAL || res == -EINTR || res == -ENOTCONN) {
73   				qb_perror(LOG_ERR, "qb_ipcc_send");
74   				return -1;
75   			} else {
76   				errno = -res;
77   				qb_perror(LOG_ERR, "qb_ipcc_send");
78   				goto repeat_send;
79   			}
80   		}
81   	
82   		if (blocking) {
83   			res = qb_ipcc_recv(conn,
84   					&res_header,
85   					sizeof(struct qb_ipc_response_header), -1);
86   			if (res == -EINTR) {
87   				return -1;
88   			}
89   			if (res < 0) {
90   				qb_perror(LOG_ERR, "qb_ipcc_recv");
91   			}
92   			assert(res == sizeof(struct qb_ipc_response_header));
93   			assert(res_header.id == 13);
94   			assert(res_header.size == sizeof(struct qb_ipc_response_header));
95   		}
96   		if (events) {
97   			res = qb_ipcc_event_recv(conn,
98   					&res_header,
99   					sizeof(struct qb_ipc_response_header), -1);
100  			if (res == -EINTR) {
101  				return -1;
102  			}
103  			if (res < 0) {
104  				qb_perror(LOG_ERR, "qb_ipcc_event_recv");
105  			}
106  			assert(res == sizeof(struct qb_ipc_response_header));
107  			assert(res_header.id == 13);
108  			assert(res_header.size == sizeof(struct qb_ipc_response_header));
109  		}
110  		return 0;
111  	}
112  	
113  	struct qb_ipc_request_header *global_zcb_buffer;
114  	
115  	static void show_usage(const char *name)
116  	{
117  		qb_log(LOG_INFO, "usage: \n");
118  		qb_log(LOG_INFO, "%s <options>\n", name);
119  		qb_log(LOG_INFO, "\n");
120  		qb_log(LOG_INFO, "  options:\n");
121  		qb_log(LOG_INFO, "\n");
122  		qb_log(LOG_INFO, "  -n             non-blocking ipc (default blocking)\n");
123  		qb_log(LOG_INFO, "  -e             receive events\n");
124  		qb_log(LOG_INFO, "  -v             verbose\n");
125  		qb_log(LOG_INFO, "  -h             show this help text\n");
126  		qb_log(LOG_INFO, "\n");
127  	}
128  	
129  	static void sigterm_handler(int32_t num)
130  	{
131  		qb_log(LOG_INFO, "bmc: %s(%d)\n", __func__, num);
132  		qb_ipcc_disconnect(conn);
133  		exit(0);
134  	}
135  	
136  	int32_t
137  	main(int32_t argc, char *argv[])
138  	{
139  		const char *options = "nevh";
140  		int32_t opt;
141  		int32_t i, j;
142  		size_t size;
143  	
144  		mypid = getpid();
145  	
146  		qb_log_init("bmc", LOG_USER, LOG_EMERG);
147  		qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
148  		qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
149  				  QB_LOG_FILTER_FILE, "*", LOG_INFO);
150  		qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
151  	
152  		while ((opt = getopt(argc, argv, options)) != -1) {
153  			switch (opt) {
154  			case 'n':
155  				blocking = QB_FALSE;
156  				break;
157  			case 'e':
158  				events = QB_TRUE;
159  				break;
160  			case 'v':
161  				verbose++;
162  				break;
163  			case 'h':
164  			default:
165  				show_usage(argv[0]);
166  				exit(0);
167  				break;
168  			}
169  		}
170  	
171  		signal(SIGINT, sigterm_handler);
172  		signal(SIGILL, sigterm_handler);
173  		signal(SIGTERM, sigterm_handler);
174  		conn = qb_ipcc_connect("bm1", MAX_MSG_SIZE);
175  		if (conn == NULL) {
176  			qb_perror(LOG_ERR, "qb_ipcc_connect");
177  			exit(1);
178  		}
179  	
180  		sw =  qb_util_stopwatch_create();
181  		size = QB_MAX(sizeof(struct qb_ipc_request_header), 64);
182  		for (j = 0; j < 20; j++) {
183  			if (size >= MAX_MSG_SIZE)
184  				break;
185  			qb_util_stopwatch_start(sw);
186  			for (i = 0; i < ITERATIONS; i++) {
187  				if (bmc_send_nozc(size) == -1) {
188  					break;
189  				}
190  			}
191  			bm_finish("send_nozc", size);
192  			size *= 2;
193  		}
194  	
195  		qb_ipcc_disconnect(conn);
196  		return EXIT_SUCCESS;
197  	}
198  	
199