1 /** @file brass_metadata.cc
2  * @brief Access to metadata for a brass database.
3  */
4 /* Copyright (C) 2004,2005,2006,2007,2008,2009,2010 Olly Betts
5  * Copyright (C) 2008 Lemur Consulting Ltd
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #include <config.h>
23 
24 #include "brass_metadata.h"
25 
26 #include "brass_cursor.h"
27 
28 #include "database.h"
29 #include "debuglog.h"
30 #include "omassert.h"
31 #include "stringutils.h"
32 
33 #include "xapian/error.h"
34 
35 using namespace std;
36 
BrassMetadataTermList(Xapian::Internal::RefCntPtr<const Xapian::Database::Internal> database_,BrassCursor * cursor_,const string & prefix_)37 BrassMetadataTermList::BrassMetadataTermList(
38 	Xapian::Internal::RefCntPtr<const Xapian::Database::Internal> database_,
39 	BrassCursor * cursor_,
40 	const string &prefix_)
41 	: database(database_), cursor(cursor_), prefix(string("\x00\xc0", 2) + prefix_)
42 {
43     LOGCALL_CTOR(DB, "BrassMetadataTermList", database_ | cursor_ | prefix_);
44     Assert(cursor);
45     // Seek to the first key before the first metadata key.
46     cursor->find_entry_lt(prefix);
47 }
48 
~BrassMetadataTermList()49 BrassMetadataTermList::~BrassMetadataTermList()
50 {
51     LOGCALL_DTOR(DB, "BrassMetadataTermList");
52     delete cursor;
53 }
54 
55 string
get_termname() const56 BrassMetadataTermList::get_termname() const
57 {
58     LOGCALL(DB, string, "BrassMetadataTermList::get_termname", NO_ARGS);
59     Assert(!at_end());
60     Assert(!cursor->current_key.empty());
61     Assert(startswith(cursor->current_key, prefix));
62     RETURN(cursor->current_key.substr(2));
63 }
64 
65 Xapian::doccount
get_termfreq() const66 BrassMetadataTermList::get_termfreq() const
67 {
68     throw Xapian::InvalidOperationError("BrassMetadataTermList::get_termfreq() not meaningful");
69 }
70 
71 Xapian::termcount
get_collection_freq() const72 BrassMetadataTermList::get_collection_freq() const
73 {
74     throw Xapian::InvalidOperationError("BrassMetadataTermList::get_collection_freq() not meaningful");
75 }
76 
77 TermList *
next()78 BrassMetadataTermList::next()
79 {
80     LOGCALL(DB, TermList *, "BrassMetadataTermList::next", NO_ARGS);
81     Assert(!at_end());
82 
83     cursor->next();
84     if (!cursor->after_end() && !startswith(cursor->current_key, prefix)) {
85 	// We've reached the end of the end of the prefixed terms.
86 	cursor->to_end();
87     }
88 
89     RETURN(NULL);
90 }
91 
92 TermList *
skip_to(const string & key)93 BrassMetadataTermList::skip_to(const string &key)
94 {
95     LOGCALL(DB, TermList *, "BrassMetadataTermList::skip_to", key);
96     Assert(!at_end());
97 
98     if (!cursor->find_entry_ge(string("\x00\xc0", 2) + key)) {
99 	// The exact term we asked for isn't there, so check if the next
100 	// term after it also has the right prefix.
101 	if (!cursor->after_end() && !startswith(cursor->current_key, prefix)) {
102 	    // We've reached the end of the prefixed terms.
103 	    cursor->to_end();
104 	}
105     }
106     RETURN(NULL);
107 }
108 
109 bool
at_end() const110 BrassMetadataTermList::at_end() const
111 {
112     LOGCALL(DB, bool, "BrassMetadataTermList::at_end", NO_ARGS);
113     RETURN(cursor->after_end());
114 }
115