dpdk: Add support for Mellanox ConnectX-4 devices
[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/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
45 typedef struct
46 {
47   svmdb_client_t *c;
48 } persist_main_t;
49
50 persist_main_t persist_main;
51
52 typedef struct
53 {
54   u8 *string1;
55   u8 *string2;
56 } demo_struct2_t;
57
58 typedef struct
59 {
60   demo_struct2_t *demo2;
61   u8 *name;
62 } demo_struct1_t;
63
64 /*
65  * Data structures in persistent shared memory, all the time
66  */
67 clib_error_t *
68 persist_malloc (persist_main_t * pm)
69 {
70   demo_struct2_t *demo2;
71   demo_struct1_t *demo1;
72   time_t starttime = time (0);
73   char *datestring = ctime (&starttime);
74   void *oldheap;
75
76   /* Get back the root pointer */
77   demo1 = svmdb_local_get_variable_reference
78     (pm->c, SVMDB_NAMESPACE_VEC, "demo1_location");
79
80   /* 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);
85
86       /* Switch to the shared memory region heap */
87       oldheap = svm_push_data_heap (pm->c->db_rp);
88
89       /* Allocate the top-level structure as a single element vector */
90       vec_validate (demo1, 0);
91
92       /* Allocate the next-level structure as a plain old memory obj */
93       demo2 = clib_mem_alloc (sizeof (*demo2));
94
95       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);
99
100       /* Back to the process-private heap */
101       svm_pop_heap (oldheap);
102       pthread_mutex_unlock (&pm->c->db_rp->mutex);
103
104       /*
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));
110
111     }
112   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);
120     }
121   return 0;
122 }
123
124 void
125 unserialize_demo1 (serialize_main_t * sm, va_list * args)
126 {
127   demo_struct1_t **result = va_arg (*args, demo_struct1_t **);
128   demo_struct1_t *demo1;
129   demo_struct2_t *demo2;
130
131   /* 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;
135
136   /* 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;
141 }
142
143 void
144 serialize_demo1 (serialize_main_t * sm, va_list * args)
145 {
146   demo_struct1_t *demo1 = va_arg (*args, demo_struct1_t *);
147   demo_struct2_t *demo2 = demo1->demo2;
148
149   serialize_cstring (sm, (char *) demo1->name);
150   serialize_cstring (sm, (char *) demo2->string1);
151   serialize_cstring (sm, (char *) demo2->string2);
152 }
153
154 /* Serialize / unserialize variant */
155 clib_error_t *
156 persist_serialize (persist_main_t * pm)
157 {
158   u8 *checkpoint;
159   serialize_main_t sm;
160
161   demo_struct2_t *demo2;
162   demo_struct1_t *demo1;
163   time_t starttime = time (0);
164   char *datestring = ctime (&starttime);
165
166   /* Get back the root pointer */
167   checkpoint = svmdb_local_get_vec_variable (pm->c, "demo1_checkpoint",
168                                              sizeof (u8));
169
170   /* 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));
177
178       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);
182
183       /* Create checkpoint */
184       serialize_open_vector (&sm, checkpoint);
185       serialize (&sm, serialize_demo1, demo1);
186       checkpoint = serialize_close_vector (&sm);
187
188       /* 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);
193     }
194   else
195     {
196       /* Open the checkpoint */
197       unserialize_open_data (&sm, checkpoint, vec_len (checkpoint));
198       unserialize (&sm, unserialize_demo1, &demo1);
199
200       /* Toss the process-private-memory checkpoint copy */
201       vec_free (checkpoint);
202
203       /* 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);
209     }
210   return 0;
211 }
212
213
214 int
215 main (int argc, char **argv)
216 {
217   unformat_input_t _input, *input = &_input;
218   persist_main_t *pm = &persist_main;
219   clib_error_t *error = 0;
220
221   /* Make a 4mb database arena, chroot so it's truly private */
222   pm->c = svmdb_map_chroot_size ("/ptest", 4 << 20);
223
224   ASSERT (pm->c);
225
226   unformat_init_command_line (input, argv);
227
228   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         }
240     }
241
242   svmdb_unmap (pm->c);
243
244   if (error)
245     {
246       clib_error_report (error);
247       exit (1);
248     }
249   return 0;
250 }
251
252 /*
253  * fd.io coding-style-patch-verification: ON
254  *
255  * Local Variables:
256  * eval: (c-set-style "gnu")
257  * End:
258  */