[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug-recutils] [PATCH 06/13] utils,doc: make re cfix --build-index add i
From: |
Michał Masłowski |
Subject: |
[bug-recutils] [PATCH 06/13] utils,doc: make re cfix --build-index add index trees. |
Date: |
Mon, 20 Aug 2012 18:21:27 +0200 |
The index file build APIs should be probably changed to make the use
of a temporary file not so integrated with adding indexes.
---
ChangeLog | 10 +++
doc/recutils.texi | 5 +-
utils/recfix.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 233 insertions(+), 28 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 2a61ffe..9de0115 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2012-08-18 Michał Masłowski <address@hidden>
+ utils,doc: make recfix --build-index add index trees.
+
+ * utils/recfix.c (recfix_do_build_index): Add indexes from %key or
+ index file.
+
+ * doc/recutils.texi (recfix Invocation): Document recfix
+ --build-index regarding indexes.
+
+2012-08-18 Michał Masłowski <address@hidden>
+
src: fix index file builder.
* src/rec-idx-file.c (rec_idx_build_file): Add padding after rset
names.
diff --git a/doc/recutils.texi b/doc/recutils.texi
index 6523a61..72bd12c 100644
--- a/doc/recutils.texi
+++ b/doc/recutils.texi
@@ -2820,7 +2820,10 @@ Note that this is a destructive operation.
@itemx @address@hidden
Build the index file for this recfile. The file argument is required to
-determine the index file name and get recfile filesystem metadata.
+determine the index file name and get recfile filesystem metadata. If
+an index file is found, it will be regenerated with the same (supported)
+indexes. Otherwise the new file will contain only indexes for record
+set primary keys.
@end table
Some operations make use of certain specific options, which are
diff --git a/utils/recfix.c b/utils/recfix.c
index 75c0d5e..840a52d 100644
--- a/utils/recfix.c
+++ b/utils/recfix.c
@@ -31,6 +31,7 @@
#include <getpass.h>
#include <gettext.h>
#define _(str) gettext (str)
+#include <sys/stat.h>
#include <rec.h>
#include <recutl.h>
@@ -537,11 +538,21 @@ recfix_do_auto ()
static int
recfix_do_build_index (void)
{
- FILE *recfile, *idx = NULL;
+ FILE *recfile, *idx = NULL, *idx_read = NULL;
rec_db_t db;
- int64_t time;
- size_t size;
+ int64_t time, index_type;
+ size_t size, num_indexes = 0, index_size, n_fields, n, rset_number;
char *index_name;
+ rec_idx_file_t idx_file = NULL;
+ bool res = true;
+ uint8_t *index_data = NULL, *old_index = NULL;
+ rec_idx_tree_t old_tree;
+ rec_rset_t rset;
+ const char **field_names;
+ rec_idx_tree_key_t *field_types;
+ char tmp_file_name[100];
+ int stat_result, des;
+ struct stat st1;
if (!recfix_file)
{
@@ -554,48 +565,229 @@ recfix_do_build_index (void)
{
return EXIT_FAILURE;
}
+
recfile = fopen (recfix_file, "r");
- if (!recfile)
+ if (!recfile || !recutl_parse_db_from_file (recfile, recfix_file, db))
{
- rec_db_destroy (db);
- return EXIT_FAILURE;
+ res = false;
}
- if (!recutl_parse_db_from_file (recfile, recfix_file, db))
+
+ /* Get its metadata. */
+ if (res && !rec_idx_get_time_size (recfile, &time, &size))
{
- rec_db_destroy (db);
- fclose (recfile);
- return EXIT_FAILURE;
+ res = false;
}
- /* Get its metadata. */
- if (!rec_idx_get_time_size (recfile, &time, &size))
+ if (recfile)
{
- rec_db_destroy (db);
fclose (recfile);
- return EXIT_FAILURE;
}
- fclose (recfile);
- /* Open the index file for write. When indices will be supported,
- it will be opened for read first to know what indices to
- regenerate. */
- index_name = rec_idx_get_file_name (recfix_file);
- if (index_name)
+ /* Get the index file name. */
+ if (res)
+ {
+ index_name = rec_idx_get_file_name (recfix_file);
+ if (!index_name)
+ {
+ res = false;
+ }
+ }
+
+ /* Open the index file for read if it exists. Intentionally no
+ verification of the file is done, since this operation is not
+ useful with valid index files (although they should be
+ parsable). */
+ if (res)
{
- idx = fopen (index_name, "wb");
+ idx_read = fopen (index_name, "rb");
+ if (idx_read)
+ {
+ idx_file = rec_idx_file_new (idx_read);
+ }
}
- if (idx)
+
+ /* Record the original index file attributes. */
+ stat_result = stat (index_name, &st1);
+
+ /* Use a temporary file for writing the index. */
+ if (res)
+ {
+ strcpy (tmp_file_name, "recXXXXXX");
+ des = mkstemp (tmp_file_name);
+ if (des == -1)
+ {
+ recutl_fatal (_("cannot create a unique name.\n"));
+ }
+ idx = fdopen (des, "wb");
+ }
+
+ if (!idx)
+ {
+ res = false;
+ }
+
+ /* Build the index file. Indexes will be added later. */
+ if (res && !rec_idx_build_file (db, idx, time, size, 0))
+ {
+ res = false;
+ }
+
+ /* Add indexes from the index file if available or from rset %keys
+ (in future choosing appropriate types). */
+ if (res && idx_file)
+ {
+ while (res && ((old_index = (uint8_t *)
+ rec_idx_file_index (idx_file,
+ (char *) old_index,
+ &index_type,
+ &index_size)) != NULL))
+ {
+ /* Read the old index. */
+ old_tree = rec_idx_tree_new (old_index, index_type, index_size);
+ if (old_tree == NULL)
+ {
+ /* Unsupported index, won't be added. */
+ continue;
+ }
+
+ /* Construct key type data. */
+ rset_number = rec_idx_tree_get_rset_number (old_tree);
+ n_fields = rec_idx_tree_get_num_fields (old_tree);
+ rset = rec_db_get_rset (db, rset_number);
+ if (!rset)
+ {
+ res = false;
+ }
+
+ if (res)
+ {
+ field_names = malloc (sizeof (*field_names) * n_fields);
+ field_types = malloc (sizeof (*field_types) * n_fields);
+
+ if (!field_names || !field_types)
+ {
+ res = false;
+ }
+ }
+
+ if (res)
+ {
+ for (n = 0; n < n_fields; n++)
+ {
+ field_names[n] = rec_idx_tree_get_field_name (old_tree, n);
+ field_types[n] = rec_idx_tree_get_field_type (old_tree, n);
+ }
+ }
+
+ /* Build the new index. */
+ if (res)
+ {
+ res = rec_idx_tree_build (rset, rset_number, n_fields,
+ field_names, field_types,
+ &index_data, &index_size, &index_type);
+ }
+
+ if (res)
+ {
+ res = rec_idx_build_add_index (idx, index_type, index_size,
+ (char *) index_data);
+ free (index_data);
+ }
+
+ if (field_names)
+ {
+ free (field_names);
+ }
+
+ if (field_types)
+ {
+ free (field_types);
+ }
+
+ rec_idx_tree_destroy (old_tree);
+
+ if (res)
+ {
+ num_indexes++;
+ }
+ }
+ }
+ else if (res)
{
- /* Build the index file without indices. */
- if (rec_idx_build_file (db, idx, time, size, 0))
+ /* Add indexes for rset primary keys. */
+ for (rset_number = 0; rset_number < rec_db_size (db); rset_number++)
{
- fclose (idx);
- return EXIT_SUCCESS;
+ /* A record has only one primary key (i.e. not a tuple). In
+ future other types should be used depending on the key
+ field type. */
+ const char *field_names[1];
+ const rec_idx_tree_key_t field_types[1] = {REC_IDX_KEY_STRING};
+
+ rset = rec_db_get_rset (db, rset_number);
+ field_names[0] = rec_rset_key (rset);
+
+ if (field_names[0] == NULL)
+ {
+ continue; /* no key */
+ }
+
+ res = rec_idx_tree_build (rset, rset_number, 1,
+ field_names, field_types,
+ &index_data, &index_size, &index_type);
+
+ if (res)
+ {
+ res = rec_idx_build_add_index (idx, index_type, index_size,
+ (char *) index_data);
+ free (index_data);
+ }
+
+ if (res)
+ {
+ num_indexes++;
+ }
}
+ }
+
+ if (res)
+ {
+ rec_idx_build_num_indices (idx, num_indexes);
+ }
+
+ if (db)
+ {
+ rec_db_destroy (db);
+ }
+
+ if (idx)
+ {
fclose (idx);
}
- return EXIT_FAILURE;
+ if (idx_file)
+ {
+ rec_idx_file_destroy (idx_file);
+ }
+
+ /* Rename the temporary file to file_name. */
+ if (rename (tmp_file_name, index_name) == -1)
+ {
+ remove (tmp_file_name);
+ recutl_fatal (_("renaming file %s to %s\n"), tmp_file_name, index_name);
+ }
+
+ /* Restore the attributes of the original file. */
+ if (stat_result != -1)
+ {
+ chmod (index_name, st1.st_mode);
+ }
+
+ if (idx_read)
+ {
+ fclose (idx_read);
+ }
+
+ return res ? EXIT_SUCCESS : EXIT_FAILURE;
}
int
--
1.7.11.4
- [bug-recutils] Index trees, Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 01/13] src,torture: imple ment abstract record iterators., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 02/13] src,torture: imple ment initial index tree support without nodes., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 06/13] utils,doc: make re cfix --build-index add index trees.,
Michał Masłowski <=
- [bug-recutils] [PATCH 05/13] src: fix index file builder., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 04/13] src,torture: imple ment index builder., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 12/13] src: implement a tri vial query planner., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 09/13] src,torture: suppo rt duplicating index tree objects., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 10/13] src: keep indexes in rsets., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 11/13] src: support index t rees that point to a leaf too left of the key searched f or., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 08/13] utils: add recfix -- add-index command., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 13/13] torture: use index t rees for performance tests., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 07/13] src: fix index range checks., Michał Masłowski, 2012/08/20
- [bug-recutils] [PATCH 03/13] src,torture: imple ment index tree scans., Michał Masłowski, 2012/08/20