blob: 591072dfd59fc5e14186a9680b2600124c6459e7 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 *------------------------------------------------------------------
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
45typedef struct {
46 svmdb_client_t *c;
47} persist_main_t;
48
49persist_main_t persist_main;
50
51typedef struct {
52 u8 * string1;
53 u8 * string2;
54} demo_struct2_t;
55
56typedef struct {
57 demo_struct2_t * demo2;
58 u8 * name;
59} demo_struct1_t;
60
61/*
62 * Data structures in persistent shared memory, all the time
63 */
64clib_error_t * persist_malloc (persist_main_t * pm)
65{
66 demo_struct2_t *demo2;
67 demo_struct1_t *demo1;
68 time_t starttime = time(0);
69 char *datestring = ctime(&starttime);
70 void *oldheap;
71
72 /* Get back the root pointer */
73 demo1 = svmdb_local_get_variable_reference
74 (pm->c, SVMDB_NAMESPACE_VEC, "demo1_location");
75
76 /* It doesnt exist create our data structures */
77 if (demo1 == 0) {
78 /* If you want MP / thread safety, lock the region... */
79 pthread_mutex_lock(&pm->c->db_rp->mutex);
80
81 /* Switch to the shared memory region heap */
82 oldheap = svm_push_data_heap (pm->c->db_rp);
83
84 /* Allocate the top-level structure as a single element vector */
85 vec_validate (demo1, 0);
86
87 /* Allocate the next-level structure as a plain old memory obj */
88 demo2 = clib_mem_alloc (sizeof (*demo2));
89
90 demo1->demo2 = demo2;
91 demo1->name = format (0, "My name is Ishmael%c", 0);
92 demo2->string1 = format (0, "Here is string1%c", 0);
93 demo2->string2 = format (0, "Born at %s%c", datestring, 0);
94
95 /* Back to the process-private heap */
96 svm_pop_heap(oldheap);
97 pthread_mutex_unlock(&pm->c->db_rp->mutex);
98
99 /*
100 * Set the root pointer. Note: this guy switches heaps, locks, etc.
101 * We allocated demo1 as a vector to make this "just work..."
102 */
103 svmdb_local_set_vec_variable (pm->c, "demo1_location",
104 demo1, sizeof (demo1));
105
106 }
107 else {
108 /* retrieve and print data from shared memory */
109 demo2 = demo1->demo2;
110 fformat (stdout, "name: %s\n", demo1->name);
111 fformat (stdout, "demo2 location: %llx\n", demo2);
112 fformat (stdout, "string1: %s\n", demo2->string1);
113 fformat (stdout, "string2: %s\n", demo2->string2);
114 }
115 return 0;
116}
117
118void unserialize_demo1 (serialize_main_t *sm, va_list * args)
119{
120 demo_struct1_t ** result = va_arg (*args, demo_struct1_t **);
121 demo_struct1_t * demo1;
122 demo_struct2_t * demo2;
123
124 /* Allocate data structures in process private memory */
125 demo1 = clib_mem_alloc (sizeof (*demo1));
126 demo2 = clib_mem_alloc (sizeof (*demo2));
127 demo1->demo2 = demo2;
128
129 /* retrieve data from shared memory checkpoint */
130 unserialize_cstring (sm, (char **) &demo1->name);
131 unserialize_cstring (sm, (char **) &demo2->string1);
132 unserialize_cstring (sm, (char **) &demo2->string2);
133 *result = demo1;
134}
135
136void serialize_demo1 (serialize_main_t *sm, va_list * args)
137{
138 demo_struct1_t * demo1 = va_arg (*args, demo_struct1_t *);
139 demo_struct2_t * demo2 = demo1->demo2;
140
141 serialize_cstring (sm, (char *)demo1->name);
142 serialize_cstring (sm, (char *)demo2->string1);
143 serialize_cstring (sm, (char *)demo2->string2);
144}
145
146/* Serialize / unserialize variant */
147clib_error_t *
148persist_serialize (persist_main_t * pm)
149{
150 u8 * checkpoint;
151 serialize_main_t sm;
152
153 demo_struct2_t *demo2;
154 demo_struct1_t *demo1;
155 time_t starttime = time(0);
156 char *datestring = ctime(&starttime);
157
158 /* Get back the root pointer */
159 checkpoint = svmdb_local_get_vec_variable (pm->c, "demo1_checkpoint",
160 sizeof (u8));
161
162 /* It doesnt exist create our data structures */
163 if (checkpoint == 0) {
164 /* Allocate data structures in process-private memory */
165 demo1 = clib_mem_alloc (sizeof (*demo2));
166 vec_validate (demo1, 0);
167 demo2 = clib_mem_alloc (sizeof (*demo2));
168
169 demo1->demo2 = demo2;
170 demo1->name = format (0, "My name is Ishmael%c", 0);
171 demo2->string1 = format (0, "Here is string1%c", 0);
172 demo2->string2 = format (0, "Born at %s%c", datestring, 0);
173
174 /* Create checkpoint */
175 serialize_open_vector (&sm, checkpoint);
176 serialize (&sm, serialize_demo1, demo1);
177 checkpoint = serialize_close_vector (&sm);
178
179 /* Copy checkpoint into shared memory */
180 svmdb_local_set_vec_variable (pm->c, "demo1_checkpoint",
181 checkpoint, sizeof (u8));
182 /* Toss the process-private-memory original.. */
183 vec_free (checkpoint);
184 }
185 else {
186 /* Open the checkpoint */
187 unserialize_open_data (&sm, checkpoint, vec_len (checkpoint));
188 unserialize (&sm, unserialize_demo1, &demo1);
189
190 /* Toss the process-private-memory checkpoint copy */
191 vec_free (checkpoint);
192
193 /* Off we go... */
194 demo2 = demo1->demo2;
195 fformat (stdout, "name: %s\n", demo1->name);
196 fformat (stdout, "demo2 location: %llx\n", demo2);
197 fformat (stdout, "string1: %s\n", demo2->string1);
198 fformat (stdout, "string2: %s\n", demo2->string2);
199 }
200 return 0;
201}
202
203
204int main (int argc, char **argv)
205{
206 unformat_input_t _input, *input=&_input;
207 persist_main_t * pm = &persist_main;
208 clib_error_t * error = 0;
209
210 /* Make a 4mb database arena, chroot so it's truly private */
211 pm->c = svmdb_map_chroot_size ("/ptest", 4<<20);
212
213 ASSERT(pm->c);
214
215 unformat_init_command_line (input, argv);
216
217 while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) {
218 if (unformat (input, "malloc"))
219 error = persist_malloc (pm);
220 else if (unformat (input, "serialize"))
221 error = persist_serialize (pm);
222 else {
223 error = clib_error_return (0, "Unknown flavor '%U'",
224 format_unformat_error, input);
225 break;
226 }
227 }
228
229 svmdb_unmap (pm->c);
230
231 if (error) {
232 clib_error_report (error);
233 exit (1);
234 }
235 return 0;
236}