Ticket #143: xapian-metadata.patch

File xapian-metadata.patch, 32.8 KB (added by Richard Boulton, 17 years ago)

Implementation of database metadata

  • xapian-core/tests/api_wrdb.cc

     
    12471247    return true;
    12481248}
    12491249
     1250/** Test basic metadata access methods. */
     1251static bool test_metadata1()
     1252{
     1253    Xapian::WritableDatabase db = get_writable_database("");
     1254
     1255    try {
     1256        TEST_EXCEPTION(Xapian::MetadataNotFoundError, db.get_metadata("foo"));
     1257    } catch (Xapian::UnimplementedError &e) {
     1258        SKIP_TEST("Metadata not supported by this backend");
     1259    }
     1260    db.set_metadata("foo", "bar");
     1261    TEST_EQUAL(db.get_metadata("foo"), "bar");
     1262    db.set_metadata("foo", "baz");
     1263    TEST_EQUAL(db.get_doccount(), 0);
     1264    TEST_EQUAL(db.get_metadata("foo"), "baz");
     1265    db.delete_metadata("foo");
     1266    TEST_EXCEPTION(Xapian::MetadataNotFoundError, db.get_metadata("foo"));
     1267
     1268    TEST_EQUAL(db.get_doccount(), 0);
     1269
     1270    return true;
     1271}
     1272
     1273/** Test the metadata gets applied at same time as transactions happen. */
     1274static bool test_metadata2()
     1275{
     1276    string path;
     1277    const string & dbtype = get_dbtype();
     1278    if (dbtype == "flint") {
     1279        path = ".flint/dbw";
     1280    } else {
     1281        /* This test only works for backends which we can get a reader for as
     1282         * well as a writer. */
     1283        SKIP_TEST("Test only supported for flint backend");
     1284    }
     1285    Xapian::WritableDatabase db = get_writable_database("");
     1286    Xapian::Database dbr = Xapian::Database(path);
     1287
     1288    TEST_EXCEPTION(Xapian::MetadataNotFoundError, db.get_metadata("foo"));
     1289    db.set_metadata("foo", "bar");
     1290    TEST_EQUAL(db.get_metadata("foo"), "bar");
     1291    TEST_EXCEPTION(Xapian::MetadataNotFoundError, dbr.get_metadata("foo"));
     1292    db.flush();
     1293    TEST_EXCEPTION(Xapian::MetadataNotFoundError, dbr.get_metadata("foo"));
     1294    dbr.reopen();
     1295    TEST_EQUAL(db.get_metadata("foo"), "bar");
     1296    TEST_EQUAL(dbr.get_metadata("foo"), "bar");
     1297    TEST_EQUAL(dbr.get_doccount(), 0);
     1298
     1299    db.add_document(Xapian::Document());
     1300    db.set_metadata("foo", "baz");
     1301    TEST_EQUAL(db.get_doccount(), 1);
     1302    TEST_EQUAL(db.get_metadata("foo"), "baz");
     1303    db.flush();
     1304
     1305    TEST_EQUAL(dbr.get_metadata("foo"), "bar");
     1306    dbr.reopen();
     1307    TEST_EQUAL(dbr.get_metadata("foo"), "baz");
     1308
     1309    db.delete_metadata("foo");
     1310    TEST_EXCEPTION(Xapian::MetadataNotFoundError, db.get_metadata("foo"));
     1311    db.flush();
     1312    TEST_EQUAL(dbr.get_metadata("foo"), "baz");
     1313    dbr.reopen();
     1314    TEST_EXCEPTION(Xapian::MetadataNotFoundError, dbr.get_metadata("foo"));
     1315
     1316    TEST_EQUAL(db.get_doccount(), 1);
     1317
     1318    return true;
     1319}
     1320
    12501321// #######################################################################
    12511322// # End of test cases: now we list the tests to run.
    12521323
     
    12741345    {"allpostlist2",       test_allpostlist2},
    12751346    {"consistency2",       test_consistency2},
    12761347    {"crashrecovery1",     test_crashrecovery1},
     1348    {"metadata1",          test_metadata1},
     1349    {"metadata2",          test_metadata2},
    12771350    {0, 0}
    12781351};
  • xapian-core/include/xapian/database.h

     
    212212         *              could not be found in the database.
    213213         */
    214214        Xapian::Document get_document(Xapian::docid did) const;
     215
     216        /** Get a piece of metadata associated with a given key.
     217         *
     218         *  Metadata is used to hold information about the database as a whole,
     219         *  not about a specific term or document.
     220         *
     221         *  This method returns a piece of user-specified metadata.
     222         *
     223         *  If there is no piece of metadata stored with the given key, an
     224         *  exception will be thrown.
     225         *
     226         *  @param key The key of the metadata item to access.  May be the
     227         *             empty string.
     228         *
     229         *  @return    A string holding the retrieved metadata item.
     230         *
     231         *  @exception Xapian::MetadataNotFoundError There was no metadata with the
     232         *             specified key in the database.
     233         */
     234        std::string get_metadata(const std::string & key) const;
    215235};
    216236
    217237/** This class provides read/write access to a database.
     
    524544        Xapian::docid replace_document(const std::string & unique_term,
    525545                                       const Xapian::Document & document);
    526546
     547        /** Set a piece of metadata associated with a given key.
     548         *
     549         *  Metadata is used to hold information about the database as a whole,
     550         *  not about a specific term or document.
     551         *
     552         *  This sets the metadata value associated with a given key.  If there
     553         *  is already a metadata value stored in the database with the same
     554         *  key, the old value is replaced.
     555         *
     556         *  The modification is committed to disk in the same way as
     557         *  modifications to the documents in the database are: ie,
     558         *  modifications are atomic, and won't be committed to disk
     559         *  immediately; see flush() for more details.
     560         *
     561         *  Because modifications to the metadata are included in transactions,
     562         *  metadata can be used to link databases with external resources
     563         *  which have version numbers, by storing the appropriate version
     564         *  number to link to the current content of the database in a metadata
     565         *  item.
     566         *
     567         *  There may be limits on the size of metadata items, or the number of
     568         *  items stored, depending on the backend in use.  Additionally,
     569         *  implementations are not currently optimised for storing large
     570         *  amounts of metadata.  It is recommended that only a few small
     571         *  pieces of metadata, totalling no more than a few kilobytes, is
     572         *  stored in the metadata.  If more information than this is needed,
     573         *  the metadata should be used to point to external resources holding
     574         *  the information.
     575         *
     576         *  @param key   The key of the metadata item to set.  May be the
     577         *               empty string.  There may be a limit on the length of
     578         *               the key imposed by the database backend in use (but
     579         *               anything up to 100 characters is likely to be fine).
     580         *
     581         *  @param value The value of the metadata item to set.
     582         *
     583         *  @exception Xapian::DatabaseError will be thrown if a problem occurs
     584         *             while writing to the database.
     585         *
     586         *  @exception Xapian::DatabaseCorruptError will be thrown if the
     587         *             database is in a corrupt state.
     588         */
     589        void set_metadata(const std::string & key, const std::string & value);
     590
     591        /** Delete a piece of metadata associated with a given key.
     592         *
     593         *  If no piece of metadata is present in the database with the given
     594         *  key, no change is made, and no error is reported.
     595         *
     596         *  @param key   The key of the metadata item to remove.  May be the
     597         *               empty string.
     598         */
     599        void delete_metadata(const std::string & key);
     600
    527601        /** Introspection method.
    528602         *
    529603         *  @return A string describing this object.
  • xapian-core/common/remote-database.h

     
    157157    /// Iterate all terms.
    158158    TermList * open_allterms() const;
    159159
     160    std::string get_metadata(const std::string & key) const;
     161
    160162    bool has_positions() const;
    161163
    162164    void reopen();
     
    202204    void replace_document(Xapian::docid did, const Xapian::Document & doc);
    203205    Xapian::docid replace_document(const std::string & unique_term,
    204206                                   const Xapian::Document & document);
     207
     208    void set_metadata(const std::string & key,
     209                      const std::string & value);
     210    void delete_metadata(const std::string & key);
    205211};
    206212
    207213#endif // XAPIAN_INCLUDED_REMOTE_DATABASE_H
  • xapian-core/common/database.h

     
    236236        virtual Xapian::Document::Internal *
    237237        open_document(Xapian::docid did, bool lazy = false) const = 0;
    238238
     239        /** Get a piece of metadata associated with a given key.
     240         *
     241         *  See Database::get_metadata() for more information.
     242         */
     243        virtual std::string get_metadata(const std::string & key) const = 0;
     244
    239245        /** Reopen the database to the latest available revision.
    240246         *
    241247         *  Database backends which don't support simultaneous update and
     
    306312        virtual Xapian::docid replace_document(const std::string & unique_term,
    307313                                               const Xapian::Document & document);
    308314
     315        /** Set a piece of metadata associated with a given key.
     316         *
     317         *  See WritableDatabase::set_metadata() for more information.
     318         */
     319        virtual void set_metadata(const std::string & key, const std::string & value);
     320
     321        /** Delete a piece of metadata associated with a given key.
     322         *
     323         *  See WritableDatabase::delete_metadata() for more information.
     324         */
     325        virtual void delete_metadata(const std::string & key);
     326
    309327        /** Request and later collect a document from the database.
    310328         *  Multiple documents can be requested with request_document(),
    311329         *  and then collected with collect_document().  Allows the backend
  • xapian-core/exception_data.pm

     
    132132/** Indicates an attempt to access a document not present in the database. */
    133133DOC
    134134
     135errorclass('MetadataNotFoundError', 'RuntimeError', <<'DOC');
     136/** Indicates an attempt to access a metadata key not present in the database. */
     137DOC
     138
    135139errorclass('FeatureUnavailableError', 'RuntimeError', <<'DOC');
    136140/** Indicates an attempt to use a feature which is unavailable.
    137141 *
  • xapian-core/api/omdatabase.cc

     
    301301    RETURN(Document(internal[n]->open_document(m)));
    302302}
    303303
     304std::string
     305Database::get_metadata(const std::string & key) const
     306{
     307    DEBUGAPICALL(void, "Database::get_metadata", key);
     308    return internal[0]->get_metadata(key);
     309}
     310
    304311bool
    305312Database::term_exists(const string & tname) const
    306313{
     
    434441    return internal[0]->replace_document(unique_term, document);
    435442}
    436443
     444void
     445WritableDatabase::set_metadata(const std::string & key,
     446                               const std::string & value)
     447{
     448    DEBUGAPICALL(void, "WritableDatabase::set_metadata",
     449                 key << ", " << value);
     450    internal[0]->set_metadata(key, value);
     451}
     452
     453void
     454WritableDatabase::delete_metadata(const std::string & key)
     455{
     456    DEBUGAPICALL(void, "WritableDatabase::delete_metadata", key);
     457    internal[0]->delete_metadata(key);
     458}
     459
    437460string
    438461WritableDatabase::get_description() const
    439462{
  • xapian-core/backends/inmemory/inmemory_database.cc

     
    712712    return new InMemoryAllTermsList(&postlists,
    713713                                    Xapian::Internal::RefCntPtr<const InMemoryDatabase>(this));
    714714}
     715
     716void
     717InMemoryDatabase::set_metadata(const std::string & key,
     718                               const std::string & value)
     719{
     720    metadata[key] = value;
     721}
     722
     723void
     724InMemoryDatabase::delete_metadata(const std::string & key)
     725{
     726    metadata.erase(key);
     727}
     728
     729std::string
     730InMemoryDatabase::get_metadata(const std::string & key) const
     731{
     732    map<string, string>::const_iterator i = metadata.find(key);
     733    if (i == metadata.end())
     734        throw Xapian::MetadataNotFoundError(string("Metadata key `") + key + "` not found.");
     735    return i->second;
     736}
  • xapian-core/backends/inmemory/inmemory_database.h

     
    234234
    235235        vector<Xapian::doclength> doclengths;
    236236
     237        std::map<string, string> metadata;
     238
    237239        Xapian::doccount totdocs;
    238240
    239241        Xapian::doclength totlen;
     
    278280#endif
    279281        void delete_document(Xapian::docid did);
    280282        void replace_document(Xapian::docid did, const Xapian::Document & document);
     283        void set_metadata(const std::string & key,
     284                          const std::string & value);
     285        void delete_metadata(const std::string & key);
    281286        //@}
    282287
    283288    public:
     
    307312        PositionList * open_position_list(Xapian::docid did,
    308313                                          const string & tname) const;
    309314        TermList * open_allterms() const;
     315        std::string get_metadata(const std::string & key) const;
    310316};
    311317
    312318#endif /* OM_HGUARD_INMEMORY_DATABASE_H */
  • xapian-core/backends/quartz/quartz_database.h

     
    216216        PositionList * open_position_list(Xapian::docid did,
    217217                                          const string & tname) const;
    218218        TermList * open_allterms() const;
     219        std::string get_metadata(const std::string & key) const;
    219220        //@}
    220221};
    221222
     
    277278        virtual void delete_document(Xapian::docid did);
    278279        virtual void replace_document(Xapian::docid did,
    279280                                      const Xapian::Document & document);
     281        virtual void set_metadata(const std::string & key,
     282                                  const std::string & value);
     283        virtual void delete_metadata(const std::string & key);
    280284        //@}
    281285
    282286    public:
     
    308312        PositionList * open_position_list(Xapian::docid did,
    309313                                          const string & tname) const;
    310314        TermList * open_allterms() const;
     315        std::string get_metadata(const std::string & key) const;
    311316        //@}
    312317};
    313318
  • xapian-core/backends/quartz/quartz_database.cc

     
    667667                                  pl_cursor, postlist_table.get_entry_count()));
    668668}
    669669
     670std::string
     671QuartzDatabase::get_metadata(const std::string &) const
     672{
     673    throw Xapian::UnimplementedError("Metadata not implemented for Quartz databases.");
     674}
     675
    670676size_t QuartzWritableDatabase::flush_threshold = 0;
    671677
    672678QuartzWritableDatabase::QuartzWritableDatabase(const string &dir, int action,
     
    10461052        do_flush_const();
    10471053}
    10481054
     1055void
     1056QuartzWritableDatabase::set_metadata(const std::string &,
     1057                                     const std::string &)
     1058{
     1059    throw Xapian::UnimplementedError("Metadata not implemented for Quartz databases.");
     1060}
     1061
     1062void
     1063QuartzWritableDatabase::delete_metadata(const std::string &)
     1064{
     1065    throw Xapian::UnimplementedError("Metadata not implemented for Quartz databases.");
     1066}
     1067
    10491068Xapian::doccount
    10501069QuartzWritableDatabase::get_doccount() const
    10511070{
     
    12041223                                  pl_cursor, t->get_entry_count()));
    12051224}
    12061225
     1226std::string
     1227QuartzWritableDatabase::get_metadata(const std::string &) const
     1228{
     1229    throw Xapian::UnimplementedError("Metadata not implemented for Quartz databases.");
     1230}
     1231
    12071232void
    12081233QuartzWritableDatabase::cancel()
    12091234{
  • xapian-core/backends/database.cc

     
    360360    return did;
    361361}
    362362
     363void
     364Database::Internal::set_metadata(const std::string &, const std::string &)
     365{
     366    // Writable databases should override this method.
     367    Assert(false);
    363368}
     369
     370void
     371Database::Internal::delete_metadata(const std::string &)
     372{
     373    // Writable databases should override this method.
     374    Assert(false);
     375}
     376
     377}
  • xapian-core/backends/remote/remote-database.cc

     
    555555    const char * p_end = p + message.size();
    556556    return decode_length(&p, p_end, false);
    557557}
     558
     559std::string
     560RemoteDatabase::get_metadata(const std::string &) const
     561{
     562    throw Xapian::UnimplementedError("Metadata not implemented for Remote databases.");
     563}
     564
     565void
     566RemoteDatabase::set_metadata(const std::string &,
     567                             const std::string &)
     568{
     569    throw Xapian::UnimplementedError("Metadata not implemented for Remote databases.");
     570}
     571
     572void
     573RemoteDatabase::delete_metadata(const std::string &)
     574{
     575    throw Xapian::UnimplementedError("Metadata not implemented for Remote databases.");
     576}
  • xapian-core/backends/flint/Makefile.mk

     
    1414        backends/flint/flint_document.h\
    1515        backends/flint/flint_io.h\
    1616        backends/flint/flint_lock.h\
     17        backends/flint/flint_metadata.h\
    1718        backends/flint/flint_modifiedpostlist.h\
    1819        backends/flint/flint_positionlist.h\
    1920        backends/flint/flint_postlist.h\
     
    3435        backends/flint/flint_document.cc\
    3536        backends/flint/flint_io.cc\
    3637        backends/flint/flint_lock.cc\
     38        backends/flint/flint_metadata.cc\
    3739        backends/flint/flint_modifiedpostlist.cc\
    3840        backends/flint/flint_positionlist.cc\
    3941        backends/flint/flint_postlist.cc\
  • xapian-core/backends/flint/flint_database.h

     
    2424#define OM_HGUARD_FLINT_DATABASE_H
    2525
    2626#include "database.h"
     27#include "flint_metadata.h"
    2728#include "flint_positionlist.h"
    2829#include "flint_postlist.h"
    2930#include "flint_record.h"
     
    102103         */
    103104        Xapian::docid lastdocid;
    104105
     106        /** The metadata for this database.
     107         */
     108        FlintMetadata metadata;
     109
    105110        /** Return true if a database exists at the path specified for this
    106111         *  database.
    107112         */
     
    217222        PositionList * open_position_list(Xapian::docid did,
    218223                                          const string & tname) const;
    219224        TermList * open_allterms() const;
     225        string get_metadata(const string & key) const;
    220226        //@}
    221227};
    222228
     
    247253         */
    248254        mutable Xapian::docid lastdocid;
    249255
     256        /** The metadata for this database.
     257         */
     258        FlintMetadata metadata;
     259
     260        /** Flag, true iff the metadata has been modified.
     261         */
     262        mutable bool metadata_modified;
     263
    250264        /** The number of documents added, deleted, or replaced since the last
    251265         *  flush.
    252266         */
     
    278292        virtual void delete_document(Xapian::docid did);
    279293        virtual void replace_document(Xapian::docid did,
    280294                                      const Xapian::Document & document);
     295        virtual void set_metadata(const string & key,
     296                                  const string & value);
     297        virtual void delete_metadata(const string & key);
    281298        //@}
    282299
    283300    public:
     
    309326        PositionList * open_position_list(Xapian::docid did,
    310327                                          const string & tname) const;
    311328        TermList * open_allterms() const;
     329        string get_metadata(const string & key) const;
    312330        //@}
    313331};
    314332
  • xapian-core/backends/flint/flint_metadata.h

     
     1/* flint_metadata.h: Metadata in flint databases
     2 *
     3 * Copyright 2007 Lemur Consulting Ltd
     4 *
     5 * This program is free software; you can redistribute it and/or
     6 * modify it under the terms of the GNU General Public License as
     7 * published by the Free Software Foundation; either version 2 of the
     8 * License, or (at your option) any later version.
     9 *
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14 *
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program; if not, write to the Free Software
     17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
     18 * USA
     19 */
     20
     21#ifndef XAPIAN_INCLUDED_FLINT_METADATA_H
     22#define XAPIAN_INCLUDED_FLINT_METADATA_H
     23
     24#include <map>
     25#include <string>
     26#include <xapian/error.h>
     27
     28using namespace std;
     29
     30/** Class holding the metadata for a flint database.
     31 *
     32 *  This class also
     33 */
     34class FlintMetadata {
     35    private:
     36        /** The serialised form of the metadata. */
     37        mutable string serialised;
     38
     39        /** Parsed form of the metadata. */
     40        mutable map<string, string> lookup;
     41
     42        /** Flag, true iff the serialised form is up-to-date. */
     43        mutable bool serialised_uptodate;
     44
     45        /** Flag, true iff the parsed form in `lookup` is up-to-date. */
     46        mutable bool parsed;
     47
     48        /** Parse the serialised metadata.
     49         *
     50         *  "lookup" is populated with the results.
     51         */
     52        void parse() const;
     53
     54        /** Serialise the serialised metadata.
     55         *
     56         *  "serialised" to set to contain the information in "lookup".
     57         */
     58        void unparse() const;
     59
     60    public:
     61        /** Create a new metadata object.
     62         *
     63         *  @param serialised_ - Serialised form of the metadata.
     64         */
     65        FlintMetadata()
     66            : serialised(),
     67              serialised_uptodate(true),
     68              parsed(false)
     69        {}
     70
     71        /** Get the metadata item with the given key.
     72         */
     73        const string & get(const string & key) const
     74        {
     75            if (!parsed) parse();
     76            map<string, string>::const_iterator i = lookup.find(key);
     77            if (i == lookup.end())
     78                throw Xapian::MetadataNotFoundError(string("Metadata key `") + key + "` not found.");
     79            return i->second;
     80        }
     81
     82        /** Set the metadata item with the given key.
     83         */
     84        void set(const string & key, const string & value)
     85        {
     86            if (!parsed) parse();
     87            lookup[key] = value;
     88            serialised_uptodate = false;
     89        }
     90
     91        /** Delete the metadata item with the given key.
     92         */
     93        void del(const string & key)
     94        {
     95            if (!parsed) parse();
     96            lookup.erase(key);
     97            serialised_uptodate = false;
     98        }
     99
     100        void clear()
     101        {
     102            serialised.clear();
     103            serialised_uptodate = true;
     104            parsed = false;
     105        }
     106
     107        /** Serialise the metadata.
     108         */
     109        const string & serialise() const
     110        {
     111            if (!serialised_uptodate) unparse();
     112            return serialised;
     113        }
     114
     115        /** Set the metadata from a serialised form.
     116         */
     117        void unserialise(string serialised_)
     118        {
     119            serialised = serialised_;
     120            serialised_uptodate = true;
     121            parsed = false;
     122        }
     123};
     124
     125#endif /* XAPIAN_INCLUDED_FLINT_METADATA_H */
  • xapian-core/backends/flint/flint_version.cc

    Property changes on: xapian-core/backends/flint/flint_metadata.h
    ___________________________________________________________________
    Name: svn:eol-style
       + native
    
     
    3636using std::string;
    3737
    3838// YYYYMMDDX where X allows multiple format revisions in a day
    39 #define FLINT_VERSION 200704230u
     39#define FLINT_VERSION 200705040u
     40// 200705040 Support user-specified metadata
    4041// 200704230 Use zlib compression of tags for record and termlist tables
    4142// 200611200 Fixed occasional, architecture-dependent surplus bits in
    4243//           interpolative coding; "flicklock" -> "flintlock".
  • xapian-core/backends/flint/flint_database.cc

     
    8787        }
    8888        // Can still allow searches even if recovery is needed
    8989        open_tables_consistent();
    90         postlist_table.get_metainfo_entry(total_length, lastdocid);
     90        postlist_table.get_metainfo_entry(total_length, lastdocid, metadata);
    9191    } else {
    9292        if (!dbexists) {
    9393            // FIXME: if we allow Xapian::DB_OVERWRITE, check it here
     
    144144            value_table.commit(new_revision);
    145145            record_table.commit(new_revision);
    146146        }
    147         postlist_table.get_metainfo_entry(total_length, lastdocid);
     147        postlist_table.get_metainfo_entry(total_length, lastdocid, metadata);
    148148    }
    149149}
    150150
     
    199199    // Set metainfo
    200200    total_length = 0;
    201201    lastdocid = 0;
    202     postlist_table.set_metainfo_entry(total_length, lastdocid);
     202    metadata.clear();
     203    postlist_table.set_metainfo_entry(total_length, lastdocid, metadata);
    203204}
    204205
    205206void
     
    309310    DEBUGCALL(DB, void, "FlintDatabase::reopen", "");
    310311    if (readonly) {
    311312        open_tables_consistent();
    312         postlist_table.get_metainfo_entry(total_length, lastdocid);
     313        postlist_table.get_metainfo_entry(total_length, lastdocid, metadata);
    313314    }
    314315}
    315316
     
    528529                                 &postlist_table));
    529530}
    530531
     532string
     533FlintDatabase::get_metadata(const string & key) const
     534{
     535    DEBUGCALL(DB, string, "FlintDatabase::get_metadata", key);
     536    RETURN(metadata.get(key));
     537}
     538
    531539size_t FlintWritableDatabase::flush_threshold = 0;
    532540
    533541FlintWritableDatabase::FlintWritableDatabase(const string &dir, int action,
     
    536544          doclens(),
    537545          mod_plists(),
    538546          database_ro(dir, action, block_size),
     547          metadata_modified(false),
    539548          changes_made(0)
    540549{
    541550    DEBUGCALL(DB, void, "FlintWritableDatabase", dir << ", " << action << ", "
    542551              << block_size);
    543     database_ro.postlist_table.get_metainfo_entry(total_length, lastdocid);
     552    database_ro.postlist_table.get_metainfo_entry(total_length, lastdocid,
     553                                                  metadata);
    544554    if (flush_threshold == 0) {
    545555        const char *p = getenv("XAPIAN_FLUSH_THRESHOLD");
    546556        if (p) flush_threshold = atoi(p);
     
    559569{
    560570    if (transaction_active())
    561571        throw Xapian::InvalidOperationError("Can't flush during a transaction");
    562     if (changes_made) do_flush_const();
     572    if (changes_made || metadata_modified) do_flush_const();
    563573}
    564574
    565575void
     
    570580    database_ro.postlist_table.merge_changes(mod_plists, doclens, freq_deltas);
    571581
    572582    // Update the total document length and last used docid.
    573     database_ro.postlist_table.set_metainfo_entry(total_length, lastdocid);
     583    database_ro.postlist_table.set_metainfo_entry(total_length, lastdocid,
     584                                                  metadata);
     585    metadata_modified = false;
    574586    database_ro.apply();
    575587    freq_deltas.clear();
    576588    doclens.clear();
     
    10691081}
    10701082
    10711083void
     1084FlintWritableDatabase::set_metadata(const std::string & key,
     1085                                    const std::string & value)
     1086{
     1087    DEBUGCALL(DB, string, "FlintWritableDatabase::set_metadata", key << ", " << value);
     1088    metadata.set(key, value);
     1089    metadata_modified = true;
     1090}
     1091
     1092void
     1093FlintWritableDatabase::delete_metadata(const std::string & key)
     1094{
     1095    DEBUGCALL(DB, string, "FlintWritableDatabase::delete_metadata", key);
     1096    metadata.del(key);
     1097    metadata_modified = true;
     1098}
     1099
     1100string
     1101FlintWritableDatabase::get_metadata(const string & key) const
     1102{
     1103    DEBUGCALL(DB, string, "FlintWritableDatabase::get_metadata", key);
     1104    RETURN(metadata.get(key));
     1105}
     1106
     1107void
    10721108FlintWritableDatabase::cancel()
    10731109{
    10741110    database_ro.cancel();
    1075     database_ro.postlist_table.get_metainfo_entry(total_length, lastdocid);
     1111    database_ro.postlist_table.get_metainfo_entry(total_length, lastdocid,
     1112                                                  metadata);
     1113    metadata_modified = false;
    10761114    freq_deltas.clear();
    10771115    doclens.clear();
    10781116    mod_plists.clear();
  • xapian-core/backends/flint/flint_metadata.cc

     
     1/* flint_metadata.cc: Metadata in flint databases
     2 *
     3 * Copyright 2007 Lemur Consulting Ltd
     4 *
     5 * This program is free software; you can redistribute it and/or
     6 * modify it under the terms of the GNU General Public License as
     7 * published by the Free Software Foundation; either version 2 of the
     8 * License, or (at your option) any later version.
     9 *
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14 *
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program; if not, write to the Free Software
     17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
     18 * USA
     19 */
     20
     21#include <config.h>
     22#include "flint_metadata.h"
     23#include "flint_utils.h"
     24#include <xapian/error.h>
     25#include "omdebug.h"
     26
     27void
     28FlintMetadata::parse() const
     29{
     30    DEBUGCALL(DB, void, "FlintMetadata::parse", "");
     31    const char * pos = serialised.data();
     32    const char * end = pos + serialised.size();
     33    lookup.clear();
     34    map<string, string>::iterator i = lookup.begin();
     35
     36    while (pos != end) {
     37        string key;
     38        string value;
     39        if (!unpack_string(&pos, end, key))
     40            throw Xapian::DatabaseCorruptError("Couldn't read key from metadata");
     41        if (pos == end)
     42            throw Xapian::DatabaseCorruptError("Couldn't read length of value from metadata");
     43        if (!unpack_string(&pos, end, value))
     44            throw Xapian::DatabaseCorruptError("Couldn't read value from metadata");
     45        i = lookup.insert(i, make_pair(key, value));
     46    }
     47
     48    parsed = true;
     49}
     50
     51void
     52FlintMetadata::unparse() const
     53{
     54    DEBUGCALL(DB, void, "FlintMetadata::unparse", "");
     55    serialised.clear();
     56
     57    map<string, string>::const_iterator i;
     58    for (i = lookup.begin(); i != lookup.end(); ++i)
     59    {
     60        serialised.append(pack_string(i->first));
     61        serialised.append(pack_string(i->second));
     62    }
     63    serialised_uptodate = true;
     64}
  • xapian-core/backends/flint/flint_postlist.cc

    Property changes on: xapian-core/backends/flint/flint_metadata.cc
    ___________________________________________________________________
    Name: svn:eol-style
       + native
    
     
    2222#include <config.h>
    2323#include "omdebug.h"
    2424#include "flint_postlist.h"
     25#include "flint_metadata.h"
    2526#include "flint_utils.h"
    2627#include "flint_cursor.h"
    2728#include "database.h"
    2829
    2930// Magic key (which corresponds to an invalid docid) is used to store the
    30 // next free docid and total length of all documents
     31// next free docid, total length of all documents, and the database metadata.
    3132static const string METAINFO_KEY("", 1);
    3233
    3334void
    3435FlintPostListTable::get_metainfo_entry(flint_totlen_t & totlen,
    35                                        Xapian::docid & did) const
     36                                       Xapian::docid & did,
     37                                       FlintMetadata & metadata) const
    3638{
    3739    DEBUGCALL(DB, void, "FlintPostListTable::get_metainfo_entry", "");
    3840
     
    4042    if (!get_exact_entry(METAINFO_KEY, tag)) {
    4143        totlen = 0;
    4244        did = 0;
     45        metadata.clear();
    4346        return;
    4447    }
    4548
     
    4851    if (!unpack_uint(&data, end, &did)) {
    4952        throw Xapian::DatabaseCorruptError("Record containing meta information is corrupt.");
    5053    }
    51     if (!unpack_uint_last(&data, end, &totlen)) {
     54    if (!unpack_uint(&data, end, &totlen)) {
    5255        throw Xapian::DatabaseCorruptError("Record containing meta information is corrupt.");
    5356    }
     57    metadata.unserialise(string(data, end));
    5458}
    5559
    5660void
    5761FlintPostListTable::set_metainfo_entry(flint_totlen_t totlen,
    58                                        Xapian::docid did)
     62                                       Xapian::docid did,
     63                                       const FlintMetadata & metadata)
    5964{
    6065    DEBUGCALL(DB, void, "FlintPostListTable::set_metainfo_entry",
    61                         totlen << ", " << did);
     66                        totlen << ", " << did << ", " << metadata.serialise());
    6267    string tag = pack_uint(did);
    63     tag += pack_uint_last(totlen);
     68    tag += pack_uint(totlen);
     69    tag += metadata.serialise();
    6470    add(METAINFO_KEY, tag);
    6571}
    6672
  • xapian-core/backends/flint/flint_postlist.h

     
    3535using namespace std;
    3636
    3737class FlintCursor;
    38 class FlintDatabase;
     38class FlintMetadata;
    3939
    4040class PostlistChunkReader;
    4141class PostlistChunkWriter;
     
    7070        /** Get the total length, last document ID used, and metadata.
    7171         */
    7272        void get_metainfo_entry(flint_totlen_t & totlen,
    73                                 Xapian::docid & lastdocid) const;
     73                                Xapian::docid & lastdocid,
     74                                FlintMetadata & metadata) const;
    7475
    7576        /** Set the total length, last document ID used, and metadata.
    7677         */
    7778        void set_metainfo_entry(flint_totlen_t totlen,
    78                                 Xapian::docid lastdocid);
     79                                Xapian::docid lastdocid,
     80                                const FlintMetadata & metadata);
    7981};
    8082
    8183/** A postlist in a flint database.
  • xapian-bindings/xapian.i

     
    666666        doclength get_doclength(docid docid) const;
    667667        void keep_alive();
    668668        Document get_document(docid did);
     669        std::string get_metadata(const std::string & key) const;
    669670};
    670671
    671672class WritableDatabase : public Database {
     
    687688        void delete_document(const std::string & unique_term);
    688689        Xapian::docid replace_document(const std::string & unique_term,
    689690                                       const Xapian::Document & document);
     691        void set_metadata(const std::string & key, const std::string & value);
     692        void delete_metadata(const std::string & key);
    690693
    691694        string get_description() const;
    692695};