[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug-recutils] [PATCH 01/13] src,torture: imple ment abstract record ite
From: |
Michał Masłowski |
Subject: |
[bug-recutils] [PATCH 01/13] src,torture: imple ment abstract record iterators. |
Date: |
Mon, 20 Aug 2012 18:21:22 +0200 |
The query planner will provide an iterator of a superset of records to
be returned by the query. Simpler solutions would use a different API
for iterating msets (from the database) or records found in an index
search.
---
ChangeLog | 14 ++++
src/Makefile.am | 3 +-
src/rec-iter.c | 140 +++++++++++++++++++++++++++++++++++++
src/rec.h | 43 ++++++++++++
torture/Makefile.am | 6 +-
torture/rec-iter/rec-iter-mset.c | 87 +++++++++++++++++++++++
torture/rec-iter/tsuite-rec-iter.c | 42 +++++++++++
torture/runtests.c | 2 +
8 files changed, 335 insertions(+), 2 deletions(-)
create mode 100644 src/rec-iter.c
create mode 100644 torture/rec-iter/rec-iter-mset.c
create mode 100644 torture/rec-iter/tsuite-rec-iter.c
diff --git a/ChangeLog b/ChangeLog
index 019829e..8946498 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2012-07-18 Michał Masłowski <address@hidden>
+
+ src,torture: implement abstract record iterators.
+ * src/Makefile.am (librec_la_SOURCES): Add rec-iter.c
+ * src/rec-iter.c: New file.
+ * src/rec.h: Add prototypes and documentation for record
+ iterators.
+
+ * torture/Makefile.am (REC_ITER_TSUITE): New variable.
+ (runtests_SOURCES): Add $(REC_ITER_TSUITE).
+ * torture/rec-iter/rec-iter-mset.c: New file.
+ * torture/rec-iter/tsuite-rec-iter.c: Likewise.
+ * torture/runtests.c (main): Add the tsuite_rec_iter test suite.
+
2012-07-11 Michał Masłowski <address@hidden>
doc: mention index files and their building.
diff --git a/src/Makefile.am b/src/Makefile.am
index 26dedd1..9a30fa1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -44,7 +44,8 @@ librec_la_SOURCES = rec.c \
rec-types.c \
rec-buf.c \
rec-aggregate.c \
- rec-idx-file.c
+ rec-idx-file.c \
+ rec-iter.c
if CRYPT
librec_la_SOURCES += rec-crypt.c
diff --git a/src/rec-iter.c b/src/rec-iter.c
new file mode 100644
index 0000000..3088d27
--- /dev/null
+++ b/src/rec-iter.c
@@ -0,0 +1,140 @@
+/* -*- mode: C -*-
+ *
+ * File: rec-iter.c
+ * Date: Wed Jul 18 14:35:05 2012
+ *
+ * GNU recutils - Record iterators.
+ *
+ */
+
+/* Copyright (C) 2012 Michał Masłowski */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <rec.h>
+
+/*
+ * Data structures.
+ */
+
+/* An iterator. */
+struct rec_iter_s
+{
+ void *data;
+ rec_iter_next_fn_t next;
+ rec_iter_dispose_fn_t dispose;
+};
+
+/* Static functions defined in this file. */
+
+static bool rec_iter_next_mset (void *data, rec_record_t *record);
+static void rec_iter_dispose_mset (void *data);
+
+/*
+ * Public functions.
+ */
+
+rec_iter_t
+rec_iter_new (void *data,
+ rec_iter_next_fn_t next,
+ rec_iter_dispose_fn_t dispose)
+{
+ rec_iter_t res;
+
+ res = malloc (sizeof (struct rec_iter_s));
+ if (!res)
+ {
+ return NULL;
+ }
+
+ res->data = data;
+ res->next = next;
+ res->dispose = dispose;
+
+ return res;
+}
+
+rec_iter_t
+rec_iter_for_mset (rec_mset_t mset)
+{
+ rec_mset_iterator_t iterator;
+ rec_mset_iterator_t *iter;
+ rec_iter_t res;
+
+ /* More complex due to mset iterators being passed by value. */
+ iter = malloc (sizeof (rec_mset_iterator_t));
+ if (!iter)
+ {
+ return NULL;
+ }
+
+ iterator = rec_mset_iterator (mset);
+ memcpy (iter, &iterator, sizeof (rec_mset_iterator_t));
+
+ res = rec_iter_new (iter, rec_iter_next_mset, rec_iter_dispose_mset);
+ if (!res)
+ {
+ rec_iter_dispose_mset (iter);
+ }
+ return res;
+}
+
+bool
+rec_iter_next (rec_iter_t iterator, rec_record_t *record)
+{
+ if (iterator->next)
+ {
+ return iterator->next (iterator->data, record);
+ }
+ return false;
+}
+
+void
+rec_iter_destroy (rec_iter_t iterator)
+{
+ if (iterator->dispose)
+ {
+ iterator->dispose (iterator->data);
+ }
+
+ free (iterator);
+}
+
+/*
+ * Private functions.
+ */
+
+static bool
+rec_iter_next_mset (void *data, rec_record_t *record)
+{
+ return rec_mset_iterator_next ((rec_mset_iterator_t *) data,
+ MSET_RECORD, (const void **) record, NULL);
+}
+
+static void
+rec_iter_dispose_mset (void *data)
+{
+ /* Other implementations would also free the record, this doesn't
+ since it doesn't copy it. */
+ rec_mset_iterator_free ((rec_mset_iterator_t *) data);
+ free (data);
+}
+
+/* End of rec-iter.c */
diff --git a/src/rec.h b/src/rec.h
index dd652ec..3ee12e2 100644
--- a/src/rec.h
+++ b/src/rec.h
@@ -2399,6 +2399,49 @@ bool rec_idx_get_time_size (FILE *recfile, int64_t
*time, size_t *size);
char *rec_idx_get_file_name (const char *recfile_name);
+/*
+ * RECORD ITERATORS
+ *
+ * The following datatype and routines provide abstract record
+ * iterators that can be used to access records from an mset or an
+ * index search.
+ */
+
+/* Opaque data type representing a record iterator. */
+
+typedef struct rec_iter_s *rec_iter_t;
+
+/* Types of arguments for rec_iter_new. */
+
+typedef bool (*rec_iter_next_fn_t) (void *data, rec_record_t *record);
+typedef void (*rec_iter_dispose_fn_t) (void *data);
+
+/* Create and return an iterator using a custom rec_iter_next
+ implementation. DATA is passed to NEXT and DISPOSE as first
+ argument. NEXT implements rec_iter_next. DISPOSE is called when
+ freeing the iterator. Passing NULL as one of the function pointers
+ makes it a no-op, in case of NEXT not iterating any records. */
+
+rec_iter_t rec_iter_new (void *data, rec_iter_next_fn_t next,
rec_iter_dispose_fn_t dispose);
+
+/* Create and return an iterator traversing records in an mset. The
+ mset contents must not be modified while the iterator is in
+ use. */
+
+rec_iter_t rec_iter_for_mset (rec_mset_t mset);
+
+/* Advance the iterator to the next record which is stored in *RECORD.
+ The function returns true if there is a next element to which
+ iterate to, and false otherwise. If a new record is allocated, it
+ will be deallocated by the next call to rec_iter_next or
+ rec_iter_destroy. */
+
+bool rec_iter_next (rec_iter_t iterator, rec_record_t *record);
+
+/* Destroy an iterator and free resources it uses. */
+
+void rec_iter_destroy (rec_iter_t iterator);
+
#endif /* !GNU_REC_H */
/* End of rec.h */
diff --git a/torture/Makefile.am b/torture/Makefile.am
index 87a84f8..6b3fa3e 100644
--- a/torture/Makefile.am
+++ b/torture/Makefile.am
@@ -144,6 +144,9 @@ REC_IDX_FILE_TSUITE = rec-idx-file/rec-idx-file-new-mem.c \
rec-idx-file/rec-idx-get-file-name.c \
rec-idx-file/tsuite-rec-idx-file.c
+REC_ITER_TSUITE = rec-iter/rec-iter-mset.c \
+ rec-iter/tsuite-rec-iter.c
+
runtests_SOURCES = runtests.c \
$(REC_MSET_TSUITE) \
$(REC_COMMENT_TSUITE) \
@@ -156,7 +159,8 @@ runtests_SOURCES = runtests.c \
$(REC_PARSER_TSUITE) \
$(REC_WRITER_TSUITE) \
$(REC_SEX_TSUITE) \
- $(REC_IDX_FILE_TSUITE)
+ $(REC_IDX_FILE_TSUITE) \
+ $(REC_ITER_TSUITE)
AM_CPPFLAGS = -I$(top_srcdir)/src \
-I$(top_srcdir)/torture
diff --git a/torture/rec-iter/rec-iter-mset.c b/torture/rec-iter/rec-iter-mset.c
new file mode 100644
index 0000000..d2c2f56
--- /dev/null
+++ b/torture/rec-iter/rec-iter-mset.c
@@ -0,0 +1,87 @@
+/* -*- mode: C -*-
+ *
+ * File: rec-iter-mset.c
+ * Date: Wed Jul 18 16:48:38 2012
+ *
+ * GNU recutils - rec_iter unit tests using mset iterators.
+ *
+ */
+
+/* Copyright (C) 2012 Michał Masłowski */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <check.h>
+
+#include <rec.h>
+
+/*-
+ * Test: rec_iter_mset_nominal
+ * Unit: rec_ter
+ * Description:
+ * + Check that an iterator for an mset can be used.
+ */
+START_TEST(rec_iter_mset_nominal)
+{
+ const char string[] = "id: foo\n\nid: bar\n\nid: baz\n\n";
+ rec_parser_t parser;
+ rec_rset_t rset;
+ rec_iter_t iter;
+ rec_record_t record;
+
+ /* Make an rset. */
+ parser = rec_parser_new_str (string, "dummy");
+ fail_if (!parser);
+ fail_if (!rec_parse_rset (parser, &rset));
+ rec_parser_destroy (parser);
+
+ /* Make an iterator. */
+ iter = rec_iter_for_mset (rec_rset_mset (rset));
+ fail_if (!iter);
+
+ /* Check that records with correct ids are returned. */
+ fail_if (!rec_iter_next (iter, &record));
+ fail_if (!rec_record_contains_field (record, "id", "foo"));
+ fail_if (!rec_iter_next (iter, &record));
+ fail_if (!rec_record_contains_field (record, "id", "bar"));
+ fail_if (!rec_iter_next (iter, &record));
+ fail_if (!rec_record_contains_field (record, "id", "baz"));
+
+ /* Check that no more records are iterated. */
+ fail_if (rec_iter_next (iter, &record));
+
+ rec_iter_destroy (iter);
+ rec_rset_destroy (rset);
+}
+END_TEST
+
+/*
+ * Test creation function
+ */
+TCase *
+test_rec_iter_mset (void)
+{
+ TCase *tc = tcase_create ("rec_iter_mset");
+ tcase_add_test (tc, rec_iter_mset_nominal);
+
+ return tc;
+}
+
+/* End of rec-iter-mset.c */
diff --git a/torture/rec-iter/tsuite-rec-iter.c
b/torture/rec-iter/tsuite-rec-iter.c
new file mode 100644
index 0000000..09a1fb7
--- /dev/null
+++ b/torture/rec-iter/tsuite-rec-iter.c
@@ -0,0 +1,42 @@
+/* -*- mode: C -*-
+ *
+ * File: tsuite-rec-iter.c
+ * Date: Wed Jul 18 16:47:19 2012
+ *
+ * GNU recutils - rec_iter test suite
+ *
+ */
+
+/* Copyright (C) 2012 Michał Masłowski */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <check.h>
+
+extern TCase *test_rec_iter_mset (void);
+
+Suite *
+tsuite_rec_iter ()
+{
+ Suite *s;
+
+ s = suite_create ("rec-iter");
+ suite_add_tcase (s, test_rec_iter_mset ());
+
+ return s;
+}
+
+/* End of tsuite-rec-iter.c */
diff --git a/torture/runtests.c b/torture/runtests.c
index de97979..35c81b1 100644
--- a/torture/runtests.c
+++ b/torture/runtests.c
@@ -40,6 +40,7 @@ extern Suite *tsuite_rec_parser (void);
extern Suite *tsuite_rec_writer (void);
extern Suite *tsuite_rec_sex (void);
extern Suite *tsuite_rec_idx_file (void);
+extern Suite *tsuite_rec_iter (void);
int
main (int argc, char **argv)
@@ -61,6 +62,7 @@ main (int argc, char **argv)
srunner_add_suite (sr, tsuite_rec_writer ());
srunner_add_suite (sr, tsuite_rec_sex ());
srunner_add_suite (sr, tsuite_rec_idx_file ());
+ srunner_add_suite (sr, tsuite_rec_iter ());
srunner_set_log (sr, "tests.log");
--
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 <=
- [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, 2012/08/20
- [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