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