1 /** @file glass_version.h
2 * @brief GlassVersion class
4 /* Copyright (C) 2006,2007,2008,2009,2010,2013,2014,2015,2016 Olly Betts
5 * Copyright (C) 2011 Dan Colish
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #ifndef XAPIAN_INCLUDED_GLASS_VERSION_H
23 #define XAPIAN_INCLUDED_GLASS_VERSION_H
25 #include "glass_changes.h"
26 #include "glass_defs.h"
33 #include "common/safeuuid.h"
34 #include "internaltypes.h"
35 #include "xapian/types.h"
42 glass_tablesize_t num_entries
;
46 /// Should be >= 4 or 0 for no compression.
48 std::string fl_serialised
;
51 void init(unsigned blocksize_
, uint4 compress_min_
);
53 void serialise(std::string
&s
) const;
55 bool unserialise(const char ** p
, const char * end
);
57 glass_block_t
get_root() const { return root
; }
58 int get_level() const { return int(level
); }
59 glass_tablesize_t
get_num_entries() const { return num_entries
; }
60 bool get_root_is_fake() const { return root_is_fake
; }
61 bool get_sequential() const { return sequential
; }
62 unsigned get_blocksize() const {
63 AssertRel(blocksize
,>=,GLASS_MIN_BLOCKSIZE
);
64 AssertRel(blocksize
,<=,GLASS_MAX_BLOCKSIZE
);
67 uint4
get_compress_min() const { return compress_min
; }
68 const std::string
& get_free_list() const { return fl_serialised
; }
70 void set_level(int level_
) { level
= unsigned(level_
); }
71 void set_num_entries(glass_tablesize_t n
) { num_entries
= n
; }
72 void set_root_is_fake(bool f
) { root_is_fake
= f
; }
73 void set_sequential(bool f
) { sequential
= f
; }
74 void set_root(glass_block_t root_
) { root
= root_
; }
75 void set_blocksize(unsigned b
) {
76 AssertRel(b
,>=,GLASS_MIN_BLOCKSIZE
);
77 AssertRel(b
,<=,GLASS_MAX_BLOCKSIZE
);
80 void set_free_list(const std::string
& s
) { fl_serialised
= s
; }
85 using Glass::RootInfo
;
87 /** The GlassVersion class manages the revision files.
89 * The "iamglass" file (currently) contains a "magic" string identifying
90 * that this is a glass database, a database format version number, the UUID
91 * of the database, the revision of the database, and the root block info for
95 glass_revision_number_t rev
;
97 RootInfo root
[Glass::MAX_
];
98 RootInfo old_root
[Glass::MAX_
];
100 /** The UUID of this database.
102 * This is mutable for older uuid libraries which take non-const uuid_t.
108 * When committing, this hold the file descriptor of the new changes file
109 * between the call to the write() and sync() methods.
111 * For a single-file database (when db_dir.empty()), this holds the fd of
112 * that file for use in read().
116 /** Offset into the file at which the version data starts.
118 * Will be 0, except for an embedded multi-file database.
122 /// The database directory.
125 GlassChanges
* changes
;
127 /// The number of documents in the database.
128 Xapian::doccount doccount
;
130 /// The total of the lengths of all documents in the database.
131 Xapian::totallength total_doclen
;
133 /// Greatest document id ever used in this database.
134 Xapian::docid last_docid
;
136 /// A lower bound on the smallest document length in this database.
137 Xapian::termcount doclen_lbound
;
139 /// An upper bound on the greatest document length in this database.
140 Xapian::termcount doclen_ubound
;
142 /// An upper bound on the greatest wdf in this database.
143 Xapian::termcount wdf_ubound
;
145 /// An upper bound on the spelling wordfreq in this database.
146 Xapian::termcount spelling_wordfreq_ubound
;
148 /// Oldest changeset removed when max_changesets is set
149 mutable glass_revision_number_t oldest_changeset
;
151 /// The serialised database stats.
152 std::string serialised_stats
;
154 // Serialise the database stats.
155 void serialise_stats();
157 // Unserialise the database stats.
158 void unserialise_stats();
161 explicit GlassVersion(const std::string
& db_dir_
= std::string())
162 : rev(0), fd(-1), offset(0), db_dir(db_dir_
), changes(NULL
),
163 doccount(0), total_doclen(0), last_docid(0),
164 doclen_lbound(0), doclen_ubound(0),
165 wdf_ubound(0), spelling_wordfreq_ubound(0),
166 oldest_changeset(0) { }
168 explicit GlassVersion(int fd_
);
172 /** Create the version file. */
173 void create(unsigned blocksize
);
175 void set_changes(GlassChanges
* changes_
) { changes
= changes_
; }
177 /** Read the version file and check it's a version we understand.
179 * On failure, an exception is thrown.
185 const std::string
write(glass_revision_number_t new_rev
, int flags
);
187 bool sync(const std::string
& tmpfile
,
188 glass_revision_number_t new_rev
, int flags
);
190 glass_revision_number_t
get_revision() const { return rev
; }
192 const RootInfo
& get_root(Glass::table_type tbl
) const {
196 RootInfo
* root_to_set(Glass::table_type tbl
) {
200 /// Return pointer to 16 byte UUID.
201 const char * get_uuid() const {
202 // uuid is unsigned char[].
203 return reinterpret_cast<const char *>(uuid
);
206 /// Return UUID in the standard 36 character string format.
207 std::string
get_uuid_string() const {
209 uuid_unparse_lower(uuid
, buf
);
210 return std::string(buf
, 36);
213 #if 0 // Unused currently.
214 /// Set the UUID from 16 byte binary value @a data.
215 void set_uuid(const void * data
) {
216 std::memcpy(uuid
, data
, 16);
219 /** Set the UUID from the standard 36 character string format.
221 * @return true if @a s was successfully parsed; false otherwise.
223 bool set_uuid_string(const std::string
& s
) {
224 return uuid_parse(s
.c_str(), uuid
);
228 Xapian::doccount
get_doccount() const { return doccount
; }
230 Xapian::totallength
get_total_doclen() const { return total_doclen
; }
232 Xapian::docid
get_last_docid() const { return last_docid
; }
234 Xapian::termcount
get_doclength_lower_bound() const {
235 return doclen_lbound
;
238 Xapian::termcount
get_doclength_upper_bound() const {
239 return doclen_ubound
;
242 Xapian::termcount
get_wdf_upper_bound() const { return wdf_ubound
; }
244 Xapian::termcount
get_spelling_wordfreq_upper_bound() const {
245 return spelling_wordfreq_ubound
;
248 glass_revision_number_t
get_oldest_changeset() const {
249 return oldest_changeset
;
252 void set_last_docid(Xapian::docid did
) { last_docid
= did
; }
254 void set_oldest_changeset(glass_revision_number_t changeset
) const {
255 oldest_changeset
= changeset
;
258 void set_spelling_wordfreq_upper_bound(Xapian::termcount ub
) {
259 spelling_wordfreq_ubound
= ub
;
262 void add_document(Xapian::termcount doclen
) {
264 if (total_doclen
== 0 || (doclen
&& doclen
< doclen_lbound
))
265 doclen_lbound
= doclen
;
266 if (doclen
> doclen_ubound
)
267 doclen_ubound
= doclen
;
268 total_doclen
+= doclen
;
271 void delete_document(Xapian::termcount doclen
) {
273 total_doclen
-= doclen
;
274 // If the database no longer contains any postings, we can reset
275 // doclen_lbound, doclen_ubound and wdf_ubound.
276 if (total_doclen
== 0) {
283 void check_wdf(Xapian::termcount wdf
) {
284 if (wdf
> wdf_ubound
) wdf_ubound
= wdf
;
287 Xapian::docid
get_next_docid() { return ++last_docid
; }
289 /** Merge the database stats.
291 * Used by compaction.
293 void merge_stats(const GlassVersion
& o
);
295 bool single_file() const { return db_dir
.empty(); }
297 off_t
get_offset() const { return offset
; }
300 #endif // XAPIAN_INCLUDED_GLASS_VERSION_H