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