static void write_metadata_for_file (GString *out, MetaFile *file, GList **stringvs, GHashTable *strings, GHashTable *key_hash) { GList *l; MetaData *data; guint32 key; g_assert (file->metadata_pointer != 0); set_uint32 (out, file->metadata_pointer, out->len); append_uint32 (out, g_list_length (file->data), NULL); for (l = file->data; l != NULL; l = l->next) { data = l->data; key = GPOINTER_TO_UINT (g_hash_table_lookup (key_hash, data->key)); if (data->is_list) key |= KEY_IS_LIST_MASK; append_uint32 (out, key, NULL); if (data->is_list) append_stringv (out, data->values, stringvs); else append_string (out, data->value, strings); } }
static void write_children (GString *out, MetaBuilder *builder) { GHashTable *strings; MetaFile *child, *file; GList *l; GList *files; files = g_list_prepend (NULL, builder->root); while (files != NULL) { file = files->data; files = g_list_remove_link (files, files); if (file->children == NULL) continue; /* No children, skip file */ strings = string_block_begin (); if (file->children_pointer != 0) set_uint32 (out, file->children_pointer, out->len); append_uint32 (out, g_list_length (file->children), NULL); for (l = file->children; l != NULL; l = l->next) { child = l->data; /* No mtime, children or metadata, no need for this to be in the file */ if (child->last_changed == 0 && child->children == NULL && child->data == NULL) continue; append_string (out, child->name, strings); append_uint32 (out, 0, &child->children_pointer); append_uint32 (out, 0, &child->metadata_pointer); append_time_t (out, child->last_changed, builder); if (file->children) files = g_list_append (files, child); } string_block_end (out, strings); } }
void hstcpcli::request_buf_open_index(size_t pst_id, const char *dbn, const char *tbl, const char *idx, const char *retflds, const char *filflds) { if (num_req_sent > 0 || num_req_rcvd > 0) { close(); set_error(-1, "request_buf_open_index: protocol out of sync"); return; } const string_ref dbn_ref(dbn, strlen(dbn)); const string_ref tbl_ref(tbl, strlen(tbl)); const string_ref idx_ref(idx, strlen(idx)); const string_ref rfs_ref(retflds, strlen(retflds)); writebuf.append_literal("P\t"); append_uint32(writebuf, pst_id); // FIXME size_t ? writebuf.append_literal("\t"); writebuf.append(dbn_ref.begin(), dbn_ref.end()); writebuf.append_literal("\t"); writebuf.append(tbl_ref.begin(), tbl_ref.end()); writebuf.append_literal("\t"); writebuf.append(idx_ref.begin(), idx_ref.end()); writebuf.append_literal("\t"); writebuf.append(rfs_ref.begin(), rfs_ref.end()); if (filflds != 0) { const string_ref fls_ref(filflds, strlen(filflds)); writebuf.append_literal("\t"); writebuf.append(fls_ref.begin(), fls_ref.end()); } writebuf.append_literal("\n"); ++num_req_bufd; }
static void stringv_block_end (GString *out, GHashTable *string_block, GList *stringv_block) { guint32 table_offset; StringvInfo *info; GList *l, *s; for (l = stringv_block; l != NULL; l = l->next) { info = l->data; table_offset = out->len; append_uint32 (out, g_list_length (info->strings), NULL); for (s = info->strings; s != NULL; s = s->next) append_string (out, s->data, string_block); set_uint32 (out, info->offset, table_offset); g_free (info); } g_list_free (stringv_block); /* Pad to 32bit */ while (out->len % 4 != 0) g_string_append_c (out, 0); }
static gboolean create_new_journal (const char *filename, guint32 random_tag) { char *journal_name; guint32 size_offset; GString *out; gsize pos; gboolean res; journal_name = get_journal_filename (filename, random_tag); out = g_string_new (NULL); /* HEADER */ g_string_append_c (out, 0xda); g_string_append_c (out, 0x1a); g_string_append_c (out, 'j'); g_string_append_c (out, 'o'); g_string_append_c (out, 'u'); g_string_append_c (out, 'r'); /* VERSION */ g_string_append_c (out, MAJOR_JOURNAL_VERSION); g_string_append_c (out, MINOR_JOURNAL_VERSION); append_uint32 (out, random_tag, NULL); append_uint32 (out, 0, &size_offset); append_uint32 (out, 0, NULL); /* Num entries, none so far */ pos = out->len; g_string_set_size (out, NEW_JOURNAL_SIZE); memset (out->str + pos, 0, out->len - pos); set_uint32 (out, size_offset, out->len); res = g_file_set_contents (journal_name, out->str, out->len, NULL); g_free (journal_name); g_string_free (out, TRUE); return res; }
static GString * append_time_t (GString *s, gint64 val, MetaBuilder *builder) { guint32 offset; if (val == 0) offset = 0; else if (val <= builder->time_t_base) offset = 1; else offset = val - builder->time_t_base; return append_uint32 (s, offset, NULL); }
static void append_stringv (GString *out, GList *strings, GList **stringv_block) { guint32 offset; StringvInfo *info; append_uint32 (out, 0xdeaddead, &offset); info = g_new (StringvInfo, 1); info->offset = offset; info->strings = strings; *stringv_block = g_list_prepend (*stringv_block, info); }
static void append_string (GString *out, const char *string, GHashTable *string_block) { guint32 offset; GList *offsets; append_uint32 (out, 0xdeaddead, &offset); if (g_hash_table_lookup_extended (string_block, string, NULL, (gpointer *)&offsets)) { offsets = g_list_append (offsets, GUINT_TO_POINTER (offset)); } else { g_hash_table_insert (string_block, (char *)string, g_list_prepend (NULL, GUINT_TO_POINTER (offset))); } }
void hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op, const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip, const string_ref& mod_op, const string_ref *mvs, size_t mvslen, const hstcpcli_filter *fils, size_t filslen, int invalues_keypart, const string_ref *invalues, size_t invalueslen) { if (num_req_sent > 0 || num_req_rcvd > 0) { close(); set_error(-1, "request_buf_exec_generic: protocol out of sync"); return; } append_uint32(writebuf, pst_id); // FIXME size_t ? writebuf.append_literal("\t"); writebuf.append(op.begin(), op.end()); writebuf.append_literal("\t"); append_uint32(writebuf, kvslen); // FIXME size_t ? for (size_t i = 0; i < kvslen; ++i) { const string_ref& kv = kvs[i]; append_delim_value(writebuf, kv.begin(), kv.end()); } if (limit != 0 || skip != 0 || invalues_keypart >= 0 || mod_op.size() != 0 || filslen != 0) { /* has more option */ writebuf.append_literal("\t"); append_uint32(writebuf, limit); // FIXME size_t ? if (skip != 0 || invalues_keypart >= 0 || mod_op.size() != 0 || filslen != 0) { writebuf.append_literal("\t"); append_uint32(writebuf, skip); // FIXME size_t ? } if (invalues_keypart >= 0) { writebuf.append_literal("\t@\t"); append_uint32(writebuf, invalues_keypart); writebuf.append_literal("\t"); append_uint32(writebuf, invalueslen); for (size_t i = 0; i < invalueslen; ++i) { const string_ref& s = invalues[i]; append_delim_value(writebuf, s.begin(), s.end()); } } for (size_t i = 0; i < filslen; ++i) { const hstcpcli_filter& f = fils[i]; writebuf.append_literal("\t"); writebuf.append(f.filter_type.begin(), f.filter_type.end()); writebuf.append_literal("\t"); writebuf.append(f.op.begin(), f.op.end()); writebuf.append_literal("\t"); append_uint32(writebuf, f.ff_offset); append_delim_value(writebuf, f.val.begin(), f.val.end()); } if (mod_op.size() != 0) { writebuf.append_literal("\t"); writebuf.append(mod_op.begin(), mod_op.end()); for (size_t i = 0; i < mvslen; ++i) { const string_ref& mv = mvs[i]; append_delim_value(writebuf, mv.begin(), mv.end()); } } } writebuf.append_literal("\n"); ++num_req_bufd; }
static GString * metadata_create_static (MetaBuilder *builder, guint32 *random_tag_out) { GString *out; GHashTable *hash, *key_hash; GHashTableIter iter; char *key; GList *keys, *l; GHashTable *strings; guint32 index; guint32 attributes_pointer; gint64 time_t_min; gint64 time_t_max; guint32 random_tag, root_name; out = g_string_new (NULL); /* HEADER */ g_string_append_c (out, 0xda); g_string_append_c (out, 0x1a); g_string_append_c (out, 'm'); g_string_append_c (out, 'e'); g_string_append_c (out, 't'); g_string_append_c (out, 'a'); /* VERSION */ g_string_append_c (out, MAJOR_VERSION); g_string_append_c (out, MINOR_VERSION); append_uint32 (out, 0, NULL); /* Rotated */ random_tag = g_random_int (); *random_tag_out = random_tag; append_uint32 (out, random_tag, NULL); append_uint32 (out, 0, &builder->root_pointer); append_uint32 (out, 0, &attributes_pointer); time_t_min = 0; time_t_max = 0; metafile_collect_times (builder->root, &time_t_min, &time_t_max); /* Store the base as the min value in use minus one so that 0 is free to mean "not defined" */ time_t_min = time_t_min - 1; /* Pick the base as the minimum, unless that leads to a 32bit overflow */ if (time_t_max - time_t_min > G_MAXUINT32) time_t_min = time_t_max - G_MAXUINT32; builder->time_t_base = time_t_min; append_int64 (out, builder->time_t_base); /* Collect and sort all used keys */ hash = g_hash_table_new (g_str_hash, g_str_equal); metafile_collect_keywords (builder->root, hash); g_hash_table_iter_init (&iter, hash); keys = NULL; while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL)) keys = g_list_prepend (keys, key); g_hash_table_destroy (hash); keys = g_list_sort (keys, (GCompareFunc)strcmp); /* Write keys to file and collect mapping for keys */ set_uint32 (out, attributes_pointer, out->len); key_hash = g_hash_table_new (g_str_hash, g_str_equal); strings = string_block_begin (); append_uint32 (out, g_list_length (keys), NULL); for (l = keys, index = 0; l != NULL; l = l->next, index++) { key = l->data; append_string (out, key, strings); g_hash_table_insert (key_hash, key, GUINT_TO_POINTER (index)); } string_block_end (out, strings); /* update root pointer */ set_uint32 (out, builder->root_pointer, out->len); /* Root name */ append_uint32 (out, 0, &root_name); /* Root child pointer */ append_uint32 (out, 0, &builder->root->children_pointer); /* Root metadata pointer */ append_uint32 (out, 0, &builder->root->metadata_pointer); /* Root last changed */ append_uint32 (out, builder->root->last_changed, NULL); /* Root name */ set_uint32 (out, root_name, out->len); g_string_append_len (out, "/", 2); /* Pad to 32bit */ while (out->len % 4 != 0) g_string_append_c (out, 0); write_children (out, builder); write_metadata (out, builder, key_hash); g_hash_table_destroy (key_hash); g_list_free (keys); return out; }