1 /*-
2 * Copyright (c) 2015, 2020 Oracle and/or its affiliates.  All rights reserved.
3 *
4 * See the file EXAMPLES-LICENSE for license information.
5 *
6 */
7 
8 /*
9  * Firewall Example
10  *
11  * This application shows how Oracle Berkeley DB can be used to implement a
12  * simple firewall using a queue and btree databases.
13  */
14 
15 /*
16  * Destination
17  *
18  * This program handles messages that are forwarded by the Firewall.
19  * After every 10,000 messages handled it prints out a message
20  * stating how long it took to handle those messages.
21  */
22 
23 #include "firewall_common_utils.h"
24 #include "db.h"
25 
26 static int
usage()27     usage()
28 {
29     (void)fprintf(stderr,
30 	"usage: message_handler -d db_name -h env_home \n");
31     return (EXIT_FAILURE);
32 }
33 
34 #ifdef _WIN32
35 extern int getopt(int, char * const *, const char *);
36 #endif
37 
38 /*
39  * Start reading messages from the queue.  After 10,000 messages are received
40  * print out how long it took to process those messages.
41  */
process_msgs(dbenv,msg_queue)42 int process_msgs(dbenv, msg_queue)
43     DB_ENV *dbenv;
44     DB *msg_queue;
45 {
46     DBT key, data;
47 #ifdef _WIN32
48     struct timeval2 end_time, start_time;
49 #else
50     struct timeval end_time, start_time;
51 #endif
52     double time_secs;
53     unsigned char msg[MSG_LEN], key_buf[KEY_LEN];
54     int count, first, msg_count, ret;
55 
56     /*
57      * Configure the key and data fields to use a user defined memory
58      * buffer instead of having the database get function allocate one.
59      */
60     memset(msg, 0, MSG_LEN);
61     memset(&key, 0, sizeof(DBT));
62     memset(&data, 0, sizeof(DBT));
63     data.flags |= DB_DBT_USERMEM;
64     data.ulen = MSG_LEN;
65     data.data = msg;
66     key.flags |= DB_DBT_USERMEM;
67     key.ulen = KEY_LEN;
68     key.data = key_buf;
69     first = 1;
70     count = msg_count = 0;
71 
72     while(msg_count < NUM_MESSAGES) {
73 	/*
74 	 * Read and remove the message at the front of the queue.  If
75 	 * there is no message wait until one arrives.
76 	 */
77 	if ((ret = msg_queue->get(
78 	    msg_queue, NULL, &key, &data, DB_CONSUME_WAIT)) != 0)
79 	    return ret;
80 
81 	/* After getting the first message start the timer. */
82 	if (first) {
83 	    (void)gettimeofday(&start_time, NULL);
84 	    first = 0;
85 	}
86 
87 	/*
88 	 * Increment the message counter.  After 10,000 messages reset
89 	 * the counter and print out how long it took.
90 	 */
91 	count++;
92 	msg_count++;
93 	if (count == 10000) {
94 	    count = 0;
95 	    /*
96 	     * Calculate the time it took to process
97 	     * 10,000 messages.
98 	     */
99 	    (void)gettimeofday(&end_time, NULL);
100 	    time_secs =
101 		(((double)end_time.tv_sec * NS_PER_MS +
102 		end_time.tv_usec) -
103 		((double)start_time.tv_sec * NS_PER_MS +
104 		start_time.tv_usec))/NS_PER_MS;
105 	    (void)gettimeofday(&start_time, NULL);
106 	    /*
107 	     * Print out the time it took to process
108 	     * 10,000 messages.
109 	     */
110 	    printf(
111 		"10,000 messages processed in %f seconds.\n", time_secs);
112 	}
113     }
114 
115     return ret;
116 }
117 
118 /* Open the message queue and start receiving messages. */
process_messages(env_home,dbname)119 int process_messages(env_home, dbname)
120     const char *env_home;
121     const char *dbname;
122 {
123     DB_ENV *dbenv;
124     DB *msg_queue;
125     int ret;
126 
127     msg_queue = NULL;
128     dbenv = NULL;
129 
130     /* Open the environment and message queue. */
131     if ((ret = open_env(&dbenv, env_home, 1, 1, 0)) != 0) {
132 	goto err;
133     }
134     if ((ret = open_queue(dbenv, &msg_queue, dbname, 1, 1, 0)) != 0)
135 	goto err;
136 
137     /* Start receiving and processing messages. */
138     ret = process_msgs(dbenv, msg_queue);
139 
140 err:
141     if (msg_queue != NULL)
142 	(void)msg_queue->close(msg_queue, 0);
143     if (dbenv != NULL)
144 	(void)dbenv->close(dbenv, 0);
145 
146     return ret;
147 }
148 
149 /* Receive and process messages. */
main(argc,argv)150 int main(argc, argv)
151     int argc;
152     char *argv[];
153 {
154     extern char *optarg;
155     extern int optind;
156     const char *dbname, *env_home;
157     char ch;
158 
159     /*
160      * Get the name of the message queue and the path to the BDB
161      * environment.
162      */
163     while ((ch = getopt(argc, argv, "d:h:")) != EOF) {
164 	switch (ch) {
165 	case 'd':
166 	    dbname = optarg;
167 	    break;
168 	case 'h':
169 	    env_home = optarg;
170 	    break;
171 	case '?':
172 	default:
173 	    return (usage());
174 	}
175     }
176 
177     return process_messages(env_home, dbname);
178 }
179