root / tags / 1.0.8 / xapian-core / backends / flint / flint_values.cc

Revision 10955, 4.1 kB (checked in by olly, 6 months ago)

Backport change from trunk:
backends/flint/flint_database.cc,backends/flint/flint_values.cc,
backends/flint/flint_values.h: Fix WritableDatabase::add_document()
and replace_document() not to be O(n*n) in the number of values in
the new document.
tests/api_wrdb.cc: Add testcase bigoaddvalue to make sure we don't
regress to O(n*n) (or worse!)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* flint_values.cc: Values in flint databases
2 *
3 * ----START-LICENCE----
4 * Copyright 1999,2000,2001 BrightStation PLC
5 * Copyright 2002 Ananova Ltd
6 * Copyright 2002,2003,2004,2005 Olly Betts
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 * -----END-LICENCE-----
23 */
24
25#include <config.h>
26#include "flint_values.h"
27#include "flint_utils.h"
28#include "utils.h"
29#include <xapian/error.h>
30using std::string;
31using std::make_pair;
32
33#include "omdebug.h"
34
35/** Generate key for document @a docid's values. */
36inline void
37make_key(string & key, Xapian::docid did)
38{
39    DEBUGCALL_STATIC(DB, void, "make_key", key << ", " << did);
40    key = flint_docid_to_key(did);
41}
42
43void
44FlintValueTable::unpack_entry(const char ** pos,
45                                 const char * end,
46                                 Xapian::valueno * this_value_no,
47                                 string & this_value)
48{
49    DEBUGCALL_STATIC(DB, void, "FlintValueTable::unpack_entry",
50                     "[pos], [end], " << this_value_no << ", " << this_value);
51    if (!unpack_uint(pos, end, this_value_no)) {
52        if (*pos == 0) throw Xapian::DatabaseCorruptError("Incomplete item in value table");
53        else throw Xapian::RangeError("Value number in value table is too large");
54    }
55
56    if (!unpack_string(pos, end, this_value)) {
57        if (*pos == 0) throw Xapian::DatabaseCorruptError("Incomplete item in value table");
58        else throw Xapian::RangeError("Item in value table is too large");
59    }
60
61    DEBUGLINE(DB, "FlintValueTable::unpack_entry(): value no " <<
62              this_value_no << " is `" << this_value << "'");
63}
64
65void
66FlintValueTable::encode_values(string & s,
67                               Xapian::ValueIterator it,
68                               const Xapian::ValueIterator & end)
69{
70    DEBUGCALL(DB, void, "FlintValueTable::encode_values", "[&s], " << it << ", " << end);
71    while (it != end) {
72        s += pack_uint(it.get_valueno());
73        s += pack_string(*it);
74        ++it;
75    }
76}
77 
78void
79FlintValueTable::set_encoded_values(Xapian::docid did, const string & enc)
80{
81    DEBUGCALL(DB, void, "FlintValueTable::set_encoded_values", did << ", " << enc);
82    string key;
83    make_key(key, did);
84    add(key, enc);
85}
86
87void
88FlintValueTable::get_value(string & value,
89                              Xapian::docid did,
90                              Xapian::valueno valueno) const
91{
92    DEBUGCALL(DB, void, "FlintValueTable::get_value", value << ", " << did << ", " << valueno);
93    string key;
94    make_key(key, did);
95    string tag;
96    bool found = get_exact_entry(key, tag);
97
98    if (found) {
99        const char * pos = tag.data();
100        const char * end = pos + tag.size();
101
102        while (pos && pos != end) {
103            Xapian::valueno this_value_no;
104            string this_value;
105
106            unpack_entry(&pos, end, &this_value_no, this_value);
107
108            if (this_value_no == valueno) {
109                value = this_value;
110                return;
111            }
112
113            // Values are stored in sorted order.
114            if (this_value_no > valueno) break;
115        }
116    }
117    value = "";
118}
119
120void
121FlintValueTable::get_all_values(map<Xapian::valueno, string> & values,
122                                   Xapian::docid did) const
123{
124    DEBUGCALL(DB, void, "FlintValueTable::get_all_values", "[values], " << did);
125    string key;
126    make_key(key, did);
127    string tag;
128    bool found = get_exact_entry(key, tag);
129
130    values.clear();
131    if (!found) return;
132
133    const char * pos = tag.data();
134    const char * end = pos + tag.size();
135
136    while (pos && pos != end) {
137        Xapian::valueno this_value_no;
138        string this_value;
139
140        unpack_entry(&pos, end, &this_value_no, this_value);
141        values.insert(make_pair(this_value_no, this_value));
142    }
143}
144
145void
146FlintValueTable::delete_all_values(Xapian::docid did)
147{
148    DEBUGCALL(DB, void, "FlintValueTable::delete_all_values", did);
149    string key;
150    make_key(key, did);
151    del(key);
152}
Note: See TracBrowser for help on using the browser.