blob: 023c596b9cf4d52bf055b7b402a500b8b66d1a2d [file] [log] [blame]
Dave Barach8a7fb0c2016-07-08 14:44:23 -04001/*
Ed Warnickecb9cada2015-12-08 15:45:58 -07002 *------------------------------------------------------------------
3 * persist.c - persistent data structure storage test / demo code
4 *
5 * Copyright (c) 2013 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <sys/types.h>
23#include <sys/mman.h>
24#include <sys/stat.h>
25#include <netinet/in.h>
26#include <signal.h>
27#include <pthread.h>
28#include <unistd.h>
29#include <time.h>
30#include <fcntl.h>
31#include <string.h>
32#include <vppinfra/clib.h>
33#include <vppinfra/vec.h>
34#include <vppinfra/hash.h>
35#include <vppinfra/bitmap.h>
36#include <vppinfra/fifo.h>
37#include <vppinfra/time.h>
38#include <vppinfra/mheap.h>
39#include <vppinfra/heap.h>
40#include <vppinfra/pool.h>
41#include <vppinfra/format.h>
42#include <vppinfra/serialize.h>
43#include <svmdb.h>
44
Dave Barach8a7fb0c2016-07-08 14:44:23 -040045typedef struct
46{
47 svmdb_client_t *c;
Ed Warnickecb9cada2015-12-08 15:45:58 -070048} persist_main_t;
49
50persist_main_t persist_main;
51
Dave Barach8a7fb0c2016-07-08 14:44:23 -040052typedef struct
53{
54 u8 *string1;
55 u8 *string2;
Ed Warnickecb9cada2015-12-08 15:45:58 -070056} demo_struct2_t;
57
Dave Barach8a7fb0c2016-07-08 14:44:23 -040058typedef struct
59{
60 demo_struct2_t *demo2;
61 u8 *name;
Ed Warnickecb9cada2015-12-08 15:45:58 -070062} demo_struct1_t;
63
Dave Barach8a7fb0c2016-07-08 14:44:23 -040064/*
Ed Warnickecb9cada2015-12-08 15:45:58 -070065 * Data structures in persistent shared memory, all the time
66 */
Dave Barach8a7fb0c2016-07-08 14:44:23 -040067clib_error_t *
68persist_malloc (persist_main_t * pm)
Ed Warnickecb9cada2015-12-08 15:45:58 -070069{
Dave Barach8a7fb0c2016-07-08 14:44:23 -040070 demo_struct2_t *demo2;
71 demo_struct1_t *demo1;
72 time_t starttime = time (0);
73 char *datestring = ctime (&starttime);
74 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -070075
Dave Barach8a7fb0c2016-07-08 14:44:23 -040076 /* Get back the root pointer */
77 demo1 = svmdb_local_get_variable_reference
78 (pm->c, SVMDB_NAMESPACE_VEC, "demo1_location");
Ed Warnickecb9cada2015-12-08 15:45:58 -070079
Dave Barach8a7fb0c2016-07-08 14:44:23 -040080 /* It doesnt exist create our data structures */
81 if (demo1 == 0)
82 {
83 /* If you want MP / thread safety, lock the region... */
84 pthread_mutex_lock (&pm->c->db_rp->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -070085
Dave Barach8a7fb0c2016-07-08 14:44:23 -040086 /* Switch to the shared memory region heap */
87 oldheap = svm_push_data_heap (pm->c->db_rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -070088
Dave Barach8a7fb0c2016-07-08 14:44:23 -040089 /* Allocate the top-level structure as a single element vector */
90 vec_validate (demo1, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -070091
Dave Barach8a7fb0c2016-07-08 14:44:23 -040092 /* Allocate the next-level structure as a plain old memory obj */
93 demo2 = clib_mem_alloc (sizeof (*demo2));
Ed Warnickecb9cada2015-12-08 15:45:58 -070094
Dave Barach8a7fb0c2016-07-08 14:44:23 -040095 demo1->demo2 = demo2;
96 demo1->name = format (0, "My name is Ishmael%c", 0);
97 demo2->string1 = format (0, "Here is string1%c", 0);
98 demo2->string2 = format (0, "Born at %s%c", datestring, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -070099
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400100 /* Back to the process-private heap */
101 svm_pop_heap (oldheap);
102 pthread_mutex_unlock (&pm->c->db_rp->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400104 /*
105 * Set the root pointer. Note: this guy switches heaps, locks, etc.
106 * We allocated demo1 as a vector to make this "just work..."
107 */
108 svmdb_local_set_vec_variable (pm->c, "demo1_location",
109 demo1, sizeof (demo1));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700110
111 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400112 else
113 {
114 /* retrieve and print data from shared memory */
115 demo2 = demo1->demo2;
116 fformat (stdout, "name: %s\n", demo1->name);
117 fformat (stdout, "demo2 location: %llx\n", demo2);
118 fformat (stdout, "string1: %s\n", demo2->string1);
119 fformat (stdout, "string2: %s\n", demo2->string2);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400121 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122}
123
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400124void
125unserialize_demo1 (serialize_main_t * sm, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400127 demo_struct1_t **result = va_arg (*args, demo_struct1_t **);
128 demo_struct1_t *demo1;
129 demo_struct2_t *demo2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400131 /* Allocate data structures in process private memory */
132 demo1 = clib_mem_alloc (sizeof (*demo1));
133 demo2 = clib_mem_alloc (sizeof (*demo2));
134 demo1->demo2 = demo2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700135
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400136 /* retrieve data from shared memory checkpoint */
137 unserialize_cstring (sm, (char **) &demo1->name);
138 unserialize_cstring (sm, (char **) &demo2->string1);
139 unserialize_cstring (sm, (char **) &demo2->string2);
140 *result = demo1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141}
142
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400143void
144serialize_demo1 (serialize_main_t * sm, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700145{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400146 demo_struct1_t *demo1 = va_arg (*args, demo_struct1_t *);
147 demo_struct2_t *demo2 = demo1->demo2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400149 serialize_cstring (sm, (char *) demo1->name);
150 serialize_cstring (sm, (char *) demo2->string1);
151 serialize_cstring (sm, (char *) demo2->string2);
152}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700153
154/* Serialize / unserialize variant */
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400155clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -0700156persist_serialize (persist_main_t * pm)
157{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400158 u8 *checkpoint;
159 serialize_main_t sm;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700160
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400161 demo_struct2_t *demo2;
162 demo_struct1_t *demo1;
163 time_t starttime = time (0);
164 char *datestring = ctime (&starttime);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700165
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400166 /* Get back the root pointer */
167 checkpoint = svmdb_local_get_vec_variable (pm->c, "demo1_checkpoint",
168 sizeof (u8));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400170 /* It doesnt exist create our data structures */
171 if (checkpoint == 0)
172 {
173 /* Allocate data structures in process-private memory */
174 demo1 = clib_mem_alloc (sizeof (*demo2));
175 vec_validate (demo1, 0);
176 demo2 = clib_mem_alloc (sizeof (*demo2));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400178 demo1->demo2 = demo2;
179 demo1->name = format (0, "My name is Ishmael%c", 0);
180 demo2->string1 = format (0, "Here is string1%c", 0);
181 demo2->string2 = format (0, "Born at %s%c", datestring, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700182
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400183 /* Create checkpoint */
184 serialize_open_vector (&sm, checkpoint);
185 serialize (&sm, serialize_demo1, demo1);
186 checkpoint = serialize_close_vector (&sm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400188 /* Copy checkpoint into shared memory */
189 svmdb_local_set_vec_variable (pm->c, "demo1_checkpoint",
190 checkpoint, sizeof (u8));
191 /* Toss the process-private-memory original.. */
192 vec_free (checkpoint);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400194 else
195 {
196 /* Open the checkpoint */
197 unserialize_open_data (&sm, checkpoint, vec_len (checkpoint));
198 unserialize (&sm, unserialize_demo1, &demo1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700199
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400200 /* Toss the process-private-memory checkpoint copy */
201 vec_free (checkpoint);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700202
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400203 /* Off we go... */
204 demo2 = demo1->demo2;
205 fformat (stdout, "name: %s\n", demo1->name);
206 fformat (stdout, "demo2 location: %llx\n", demo2);
207 fformat (stdout, "string1: %s\n", demo2->string1);
208 fformat (stdout, "string2: %s\n", demo2->string2);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400210 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700211}
212
213
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400214int
215main (int argc, char **argv)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400217 unformat_input_t _input, *input = &_input;
218 persist_main_t *pm = &persist_main;
219 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700220
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400221 /* Make a 4mb database arena, chroot so it's truly private */
222 pm->c = svmdb_map_chroot_size ("/ptest", 4 << 20);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400224 ASSERT (pm->c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400226 unformat_init_command_line (input, argv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400228 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
229 {
230 if (unformat (input, "malloc"))
231 error = persist_malloc (pm);
232 else if (unformat (input, "serialize"))
233 error = persist_serialize (pm);
234 else
235 {
236 error = clib_error_return (0, "Unknown flavor '%U'",
237 format_unformat_error, input);
238 break;
239 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240 }
241
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400242 svmdb_unmap (pm->c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700243
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400244 if (error)
245 {
246 clib_error_report (error);
247 exit (1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400249 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700250}
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400251
252/*
253 * fd.io coding-style-patch-verification: ON
254 *
255 * Local Variables:
256 * eval: (c-set-style "gnu")
257 * End:
258 */