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