FD.io VPP  v16.06
Vector Packet Processing
persist.c
Go to the documentation of this file.
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 {
48 
50 
51 typedef struct {
55 
56 typedef struct {
58  u8 * name;
60 
61 /*
62  * Data structures in persistent shared memory, all the time
63  */
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 */
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 
118 void 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 
136 void 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 */
147 clib_error_t *
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 
204 int main (int argc, char **argv)
205 {
206  unformat_input_t _input, *input=&_input;
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 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
u8 * string2
Definition: persist.c:53
static void svm_pop_heap(void *oldheap)
Definition: svm.h:179
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
void * svmdb_local_get_variable_reference(svmdb_client_t *client, svmdb_namespace_t namespace, char *var)
Definition: svmdb.c:362
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
svmdb_client_t * svmdb_map_chroot_size(char *root_path, uword size)
Definition: svmdb.c:140
void unserialize_demo1(serialize_main_t *sm, va_list *args)
Definition: persist.c:118
clib_error_t * persist_malloc(persist_main_t *pm)
Definition: persist.c:64
#define clib_error_report(e)
Definition: error.h:126
void svmdb_unmap(svmdb_client_t *client)
Definition: svmdb.c:145
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
void unserialize_open_data(serialize_main_t *m, u8 *data, uword n_data_bytes)
Definition: serialize.c:835
static void * svm_push_data_heap(svm_region_t *rp)
Definition: svm.h:172
u8 * string1
Definition: persist.c:52
void unformat_init_command_line(unformat_input_t *input, char *argv[])
Definition: unformat.c:975
void unserialize_cstring(serialize_main_t *m, char **s)
Definition: serialize.c:148
svm_region_t * db_rp
Definition: svmdb.h:63
clib_error_t * serialize(serialize_main_t *m,...)
Definition: serialize.c:627
always_inline void * clib_mem_alloc(uword size)
Definition: mem.h:109
void serialize_open_vector(serialize_main_t *m, u8 *vector)
Definition: serialize.c:849
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
svmdb_client_t * c
Definition: persist.c:46
void svmdb_local_set_vec_variable(svmdb_client_t *client, char *var, void *val_arg, u32 elsize)
Definition: svmdb.c:421
#define ASSERT(truth)
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
clib_error_t * persist_serialize(persist_main_t *pm)
Definition: persist.c:148
clib_error_t * unserialize(serialize_main_t *m,...)
Definition: serialize.c:639
void serialize_cstring(serialize_main_t *m, char *s)
Definition: serialize.c:135
void serialize_demo1(serialize_main_t *sm, va_list *args)
Definition: persist.c:136
int main(int argc, char **argv)
Definition: persist.c:204
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
persist_main_t persist_main
Definition: persist.c:49
word fformat(FILE *f, char *fmt,...)
Definition: format.c:437
void * svmdb_local_get_vec_variable(svmdb_client_t *client, char *var, u32 elsize)
Definition: svmdb.c:438
demo_struct2_t * demo2
Definition: persist.c:57
void * serialize_close_vector(serialize_main_t *m)
Definition: serialize.c:858
#define clib_error_return(e, args...)
Definition: error.h:112
struct _unformat_input_t unformat_input_t
pthread_mutex_t mutex
Definition: svm.h:41
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".