/* easier to use string based interface */ gchar * persist_state_lookup_string(PersistState *self, const gchar *key, gsize *length, guint8 *version) { PersistEntryHandle handle; gpointer block; SerializeArchive *sa; gchar *result; gsize result_len, size; guint8 result_version; gboolean success; if (!(handle = persist_state_lookup_entry(self, key, &size, &result_version))) return NULL; block = persist_state_map_entry(self, handle); sa = serialize_buffer_archive_new(block, size); success = serialize_read_cstring(sa, &result, &result_len); serialize_archive_free(sa); persist_state_unmap_entry(self, handle); if (!success) return NULL; if (length) *length = result_len; if (version) *version = result_version; return result; }
static gboolean _load_state(JournalReader *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super); gsize state_size; guint8 persist_version; self->persist_state = cfg->state; self->persist_handle = persist_state_lookup_entry(self->persist_state, self->persist_name, &state_size, &persist_version); return !!(self->persist_handle); }
void test_persist_state_remove_entry(void) { guint8 version; gsize size; PersistState *state = clean_and_create_persist_state_for_test("test_persist_state_remove_entry.persist"); PersistEntryHandle handle = persist_state_alloc_entry(state, "test", sizeof(TestState)); handle = persist_state_lookup_entry(state, "test", &size, &version); assert_true(handle != 0, "lookup failed before removing entry"); persist_state_remove_entry(state, "test"); state = restart_persist_state(state); handle = persist_state_lookup_entry(state, "test", &size, &version); assert_true(handle == 0, "lookup succeeded after removing entry"); cancel_and_destroy_persist_state(state); }
int main(int argc, char** argv) { struct arguments args; set_default_args(&args); if (parse_args(argc, argv, &args)) { return 1; } PersistEntryHandle handle; struct journald_state* journald_state = NULL; msg_init(TRUE); PersistState* state = persist_state_new(args.filename); gsize state_size; guint8 persist_version; persist_state_start_dump(state); switch (args.action) { case LIST: persist_state_foreach_entry(state, &handle_entry, NULL); break; case SHOW_JOURNALD_CURSOR: handle = persist_state_lookup_entry(state, systemd_journal, &state_size, &persist_version); if (handle == 0) break; journald_state = persist_state_map_entry(state, handle); printf("journald cursor: %s\n", journald_state->cursor); persist_state_unmap_entry(state, handle); break; case SAVE_JOURNALD_CURSOR: handle = persist_state_alloc_entry(state, systemd_journal, sizeof(struct journald_state)); if (handle == 0) break; journald_state = persist_state_map_entry(state, handle); journald_state->header.version = 0; journald_state->header.big_endian = (G_BYTE_ORDER == G_BIG_ENDIAN); strncpy(journald_state->cursor, args.action_arg.journald_cursor, MAX_CURSOR_LENGTH); persist_state_unmap_entry(state, handle); persist_state_commit(state); break; default:; } persist_state_free(state); msg_deinit(); return 0; }
static guint32 load_hostid_from_persist(const gchar *persist_file) { PersistState *state; PersistEntryHandle handle; HostIdState *host_id_state; gsize size; guint8 version; guint32 result; state = create_persist_state(persist_file); handle = persist_state_lookup_entry(state, HOST_ID_PERSIST_KEY, &size, &version); assert_true(handle != 0, "cannot find hostid in persist file"); host_id_state = persist_state_map_entry(state, handle); result = host_id_state->host_id; persist_state_unmap_entry(state, handle); persist_state_free(state); return result; }
void test_persist_state_not_in_use_handle_is_not_loaded(void) { PersistState *state; guint8 version; gsize size; PersistEntryHandle handle; unlink("test_in_use.persist"); write_test_file_for_test_in_use_handle(FALSE); state = create_persist_state_for_test("test_in_use.persist"); handle = persist_state_lookup_entry(state, "alma", &size, &version); assert_true(handle == 0, "lookup succeeded when looking for simple entry with in_use = FALSE!"); cancel_and_destroy_persist_state(state); }
void test_persist_state_not_in_use_handle_is_loaded_in_dump_mode(void) { PersistState *state; guint8 version; gsize size; PersistEntryHandle handle; unlink("test_in_use.persist"); write_test_file_for_test_in_use_handle(FALSE); state = persist_state_new("test_in_use.persist"); persist_state_start_dump(state); handle = persist_state_lookup_entry(state, "alma", &size, &version); assert_false(handle == 0, "lookup failed in dump mode when looking for simple entry with in_use = FALSE!"); cancel_and_destroy_persist_state(state); }
gboolean log_proto_buffered_server_restart_with_state(LogProtoServer *s, PersistState *persist_state, const gchar *persist_name) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; guint8 persist_version; PersistEntryHandle old_state_handle; gpointer old_state; gsize old_state_size; PersistEntryHandle new_state_handle = 0; gpointer new_state = NULL; gboolean success; self->pos_tracking = TRUE; self->persist_state = persist_state; old_state_handle = persist_state_lookup_entry(persist_state, persist_name, &old_state_size, &persist_version); if (!old_state_handle) { new_state_handle = log_proto_buffered_server_alloc_state(self, persist_state, persist_name); if (!new_state_handle) goto fallback_non_persistent; log_proto_buffered_server_apply_state(self, new_state_handle, persist_name); return TRUE; } if (persist_version < 4) { new_state_handle = log_proto_buffered_server_alloc_state(self, persist_state, persist_name); if (!new_state_handle) goto fallback_non_persistent; old_state = persist_state_map_entry(persist_state, old_state_handle); new_state = persist_state_map_entry(persist_state, new_state_handle); success = log_proto_buffered_server_convert_state(self, persist_version, old_state, old_state_size, new_state); persist_state_unmap_entry(persist_state, old_state_handle); persist_state_unmap_entry(persist_state, new_state_handle); /* we're using the newly allocated state structure regardless if * conversion succeeded. If the conversion went wrong then * new_state is still in its freshly initialized form since the * convert function will not touch the state in the error * branches. */ log_proto_buffered_server_apply_state(self, new_state_handle, persist_name); return success; } else if (persist_version == 4) { LogProtoBufferedServerState *state; old_state = persist_state_map_entry(persist_state, old_state_handle); state = old_state; if ((state->header.big_endian && G_BYTE_ORDER == G_LITTLE_ENDIAN) || (!state->header.big_endian && G_BYTE_ORDER == G_BIG_ENDIAN)) { /* byte order conversion in order to avoid the hassle with scattered byte order conversions in the code */ state->header.big_endian = !state->header.big_endian; state->buffer_pos = GUINT32_SWAP_LE_BE(state->buffer_pos); state->pending_buffer_pos = GUINT32_SWAP_LE_BE(state->pending_buffer_pos); state->pending_buffer_end = GUINT32_SWAP_LE_BE(state->pending_buffer_end); state->buffer_size = GUINT32_SWAP_LE_BE(state->buffer_size); state->raw_stream_pos = GUINT64_SWAP_LE_BE(state->raw_stream_pos); state->raw_buffer_size = GUINT32_SWAP_LE_BE(state->raw_buffer_size); state->pending_raw_stream_pos = GUINT64_SWAP_LE_BE(state->pending_raw_stream_pos); state->pending_raw_buffer_size = GUINT32_SWAP_LE_BE(state->pending_raw_buffer_size); state->file_size = GUINT64_SWAP_LE_BE(state->file_size); state->file_inode = GUINT64_SWAP_LE_BE(state->file_inode); } if (state->header.version > 0) { msg_error("Internal error restoring log reader state, stored data is too new", evt_tag_int("version", state->header.version)); goto error; } persist_state_unmap_entry(persist_state, old_state_handle); log_proto_buffered_server_apply_state(self, old_state_handle, persist_name); return TRUE; } else { msg_error("Internal error restoring log reader state, stored data is too new", evt_tag_int("version", persist_version)); goto error; } return TRUE; fallback_non_persistent: new_state = g_new0(LogProtoBufferedServerState, 1); error: if (!new_state) { new_state_handle = log_proto_buffered_server_alloc_state(self, persist_state, persist_name); if (!new_state_handle) goto fallback_non_persistent; new_state = persist_state_map_entry(persist_state, new_state_handle); } if (new_state) { LogProtoBufferedServerState *state = new_state; /* error happened, restart the file from the beginning */ state->raw_stream_pos = 0; state->file_inode = 0; state->file_size = 0; if (new_state_handle) log_proto_buffered_server_apply_state(self, new_state_handle, persist_name); else self->state1 = new_state; } if (new_state_handle) { persist_state_unmap_entry(persist_state, new_state_handle); } return FALSE; }
void test_values(void) { PersistState *state; gint i, j; gchar *data; state = clean_and_create_persist_state_for_test("test_values.persist"); for (i = 0; i < 1000; i++) { gchar buf[16]; PersistEntryHandle handle; g_snprintf(buf, sizeof(buf), "testkey%d", i); if (!(handle = persist_state_alloc_entry(state, buf, 128))) { fprintf(stderr, "Error allocating value in the persist file: %s\n", buf); exit(1); } data = persist_state_map_entry(state, handle); for (j = 0; j < 128; j++) { data[j] = (i % 26) + 'A'; } persist_state_unmap_entry(state, handle); } for (i = 0; i < 1000; i++) { gchar buf[16]; PersistEntryHandle handle; gsize size; guint8 version; g_snprintf(buf, sizeof(buf), "testkey%d", i); if (!(handle = persist_state_lookup_entry(state, buf, &size, &version))) { fprintf(stderr, "Error retrieving value from the persist file: %s\n", buf); exit(1); } data = persist_state_map_entry(state, handle); for (j = 0; j < 128; j++) { if (data[j] != (i % 26) + 'A') { fprintf(stderr, "Invalid data in persistent entry\n"); exit(1); } } persist_state_unmap_entry(state, handle); } state = restart_persist_state(state); for (i = 0; i < 1000; i++) { gchar buf[16]; PersistEntryHandle handle; gsize size; guint8 version; g_snprintf(buf, sizeof(buf), "testkey%d", i); if (!(handle = persist_state_lookup_entry(state, buf, &size, &version))) { fprintf(stderr, "Error retrieving value from the persist file: %s\n", buf); exit(1); } if (size != 128 || version != 4) { fprintf(stderr, "Error retrieving value from the persist file: %s, invalid size (%d) or version (%d)\n", buf, (gint) size, version); exit(1); } data = persist_state_map_entry(state, handle); for (j = 0; j < 128; j++) { if (data[j] != (i % 26) + 'A') { fprintf(stderr, "Invalid data in persistent entry\n"); exit(1); } } persist_state_unmap_entry(state, handle); } cancel_and_destroy_persist_state(state); }