Пример #1
0
static gpointer
file_builder_allocate (FileBuilder         *fb,
                       guint                alignment,
                       gsize                size,
                       struct gvdb_pointer *pointer)
{
  FileChunk *chunk;

  if (size == 0)
    return NULL;

  fb->offset += (-fb->offset) & (alignment - 1);
  chunk = g_slice_new (FileChunk);
  chunk->offset = fb->offset;
  chunk->size = size;
  chunk->data = g_malloc (size);

  pointer->start = guint32_to_le (fb->offset);
  fb->offset += size;
  pointer->end = guint32_to_le (fb->offset);

  g_queue_push_tail (fb->chunks, chunk);

  return chunk->data;
}
Пример #2
0
static void
file_builder_allocate_for_hash (FileBuilder            *fb,
                                gsize                   n_buckets,
                                gsize                   n_items,
                                guint                   bloom_shift,
                                gsize                   n_bloom_words,
                                guint32_le            **bloom_filter,
                                guint32_le            **hash_buckets,
                                struct gvdb_hash_item **hash_items,
                                struct gvdb_pointer    *pointer)
{
  guint32_le bloom_hdr, table_hdr;
  guchar *data;
  gsize size;

  g_assert (n_bloom_words < (1u << 27));

  bloom_hdr = guint32_to_le (bloom_shift << 27 | n_bloom_words);
  table_hdr = guint32_to_le (n_buckets);

  size = sizeof bloom_hdr + sizeof table_hdr +
         n_bloom_words * sizeof (guint32_le) +
         n_buckets     * sizeof (guint32_le) +
         n_items       * sizeof (struct gvdb_hash_item);

  data = file_builder_allocate (fb, 4, size, pointer);

#define chunk(s) (size -= (s), data += (s), data - (s))
  memcpy (chunk (sizeof bloom_hdr), &bloom_hdr, sizeof bloom_hdr);
  memcpy (chunk (sizeof table_hdr), &table_hdr, sizeof table_hdr);
  *bloom_filter = (guint32_le *) chunk (n_bloom_words * sizeof (guint32_le));
  *hash_buckets = (guint32_le *) chunk (n_buckets * sizeof (guint32_le));
  *hash_items = (struct gvdb_hash_item *) chunk (n_items *
                  sizeof (struct gvdb_hash_item));
  g_assert (size == 0);
#undef chunk

  memset (*bloom_filter, 0, n_bloom_words * sizeof (guint32_le));

  /* NOTE - the code to actually fill in the bloom filter here is missing.
   * Patches welcome! 
   *
   * http://en.wikipedia.org/wiki/Bloom_filter
   * http://0pointer.de/blog/projects/bloom.html
   */
}
Пример #3
0
static guint32_le
item_to_index (GvdbItem *item)
{
  if (item != NULL)
    return item->assigned_index;

  return guint32_to_le (-1u);
}
Пример #4
0
static void
file_builder_allocate_for_hash (FileBuilder            *fb,
                                gsize                   n_buckets,
                                gsize                   n_items,
                                guint                   bloom_shift,
                                gsize                   n_bloom_words,
                                guint32_le            **bloom_filter,
                                guint32_le            **hash_buckets,
                                struct gvdb_hash_item **hash_items,
                                struct gvdb_pointer    *pointer)
{
  guint32_le bloom_hdr, table_hdr;
  guchar *data;
  gsize size;

  g_assert (n_bloom_words < (1u << 27));

  bloom_hdr = guint32_to_le (bloom_shift << 27 | n_bloom_words);
  table_hdr = guint32_to_le (n_buckets);

  size = sizeof bloom_hdr + sizeof table_hdr +
         n_bloom_words * sizeof (guint32_le) +
         n_buckets     * sizeof (guint32_le) +
         n_items       * sizeof (struct gvdb_hash_item);

  data = file_builder_allocate (fb, 4, size, pointer);

#define chunk(s) (size -= (s), data += (s), data - (s))
  memcpy (chunk (sizeof bloom_hdr), &bloom_hdr, sizeof bloom_hdr);
  memcpy (chunk (sizeof table_hdr), &table_hdr, sizeof table_hdr);
  *bloom_filter = (guint32_le *) chunk (n_bloom_words * sizeof (guint32_le));
  *hash_buckets = (guint32_le *) chunk (n_buckets * sizeof (guint32_le));
  *hash_items = (struct gvdb_hash_item *) chunk (n_items *
                  sizeof (struct gvdb_hash_item));
  g_assert (size == 0);
#undef chunk

  memset (*bloom_filter, 0, n_bloom_words * sizeof (guint32_le));
}
Пример #5
0
static void
file_builder_add_string (FileBuilder *fb,
                         const gchar *string,
                         guint32_le  *start,
                         guint16_le  *size)
{
  FileChunk *chunk;
  gsize length;

  length = strlen (string);

  chunk = g_slice_new (FileChunk);
  chunk->offset = fb->offset;
  chunk->size = length;
  chunk->data = g_malloc (length);
  memcpy (chunk->data, string, length);

  *start = guint32_to_le (fb->offset);
  *size = guint16_to_le (length);
  fb->offset += length;

  g_queue_push_tail (fb->chunks, chunk);
}
Пример #6
0
static void
file_builder_add_hash (FileBuilder         *fb,
                       GHashTable          *table,
                       struct gvdb_pointer *pointer)
{
  guint32_le *buckets, *bloom_filter;
  struct gvdb_hash_item *items;
  HashTable *mytable;
  GvdbItem *item;
  guint32 index;
  gint bucket;

  mytable = hash_table_new (g_hash_table_size (table));
  g_hash_table_foreach (table, hash_table_insert, mytable);
  index = 0;

  for (bucket = 0; bucket < mytable->n_buckets; bucket++)
    for (item = mytable->buckets[bucket]; item; item = item->next)
      item->assigned_index = guint32_to_le (index++);

  file_builder_allocate_for_hash (fb, mytable->n_buckets, index, 5, 0,
                                  &bloom_filter, &buckets, &items, pointer);

  index = 0;
  for (bucket = 0; bucket < mytable->n_buckets; bucket++)
    {
      buckets[bucket] = guint32_to_le (index);

      for (item = mytable->buckets[bucket]; item; item = item->next)
        {
          struct gvdb_hash_item *entry = items++;
          const gchar *basename;

          g_assert (index == guint32_from_le (item->assigned_index));
          entry->hash_value = guint32_to_le (item->hash_value);
          entry->parent = item_to_index (item->parent);
          entry->unused = 0;

          if (item->parent != NULL)
            basename = item->key + strlen (item->parent->key);
          else
            basename = item->key;

          file_builder_add_string (fb, basename,
                                   &entry->key_start,
                                   &entry->key_size);

          if (item->value != NULL)
            {
              g_assert (item->child == NULL && item->table == NULL);

              file_builder_add_value (fb, item->value, &entry->value.pointer);
              entry->type = 'v';
            }

          if (item->child != NULL)
            {
              guint32 children = 0, i = 0;
              guint32_le *offsets;
              GvdbItem *child;

              g_assert (item->table == NULL);

              for (child = item->child; child; child = child->sibling)
                children++;

              offsets = file_builder_allocate (fb, 4, 4 * children,
                                               &entry->value.pointer);
              entry->type = 'L';

              for (child = item->child; child; child = child->sibling)
                offsets[i++] = child->assigned_index;

              g_assert (children == i);
            }

          if (item->table != NULL)
            {
              entry->type = 'H';
              file_builder_add_hash (fb, item->table, &entry->value.pointer);
            }

          index++;
        }
    }

  hash_table_free (mytable);
}