monotone

monotone Mtn Source Tree

Root/database.hh

1#ifndef __DATABASE_HH__
2#define __DATABASE_HH__
3
4// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
5// all rights reserved.
6// licensed to the public under the terms of the GNU GPL (>= 2)
7// see the file COPYING for details
8
9struct sqlite;
10struct cert;
11
12#include <vector>
13#include <set>
14#include <string>
15
16#include <boost/filesystem/path.hpp>
17
18#include "manifest.hh"
19#include "numeric_vocab.hh"
20#include "vocab.hh"
21
22// this file defines a public, typed interface to the database.
23// the database class encapsulates all knowledge about sqlite,
24// the schema, and all SQL statements used to access the schema.
25//
26// one thing which is rather important to note is that this file
27// deals with two sorts of version relationships. the versions
28// stored in the database are all *backwards* from those the program
29// sees. so for example if you have two versions of a file
30//
31// file.1, file.2
32//
33// where file.2 was a modification of file.1, then as far as the rest of
34// the application is concerned -- and the ancestry graph -- file.1 is the
35// "old" version and file.2 is the "new" version. note the use of terms
36// which describe time, and the sequence of edits a user makes to a
37// file. those are ancestry terms. when the application composes a
38// patchset, for example, it'll contain the diff delta(file.1, file.2)
39//
40// from the database's perspective, however, file.1 is the derived version,
41// and file.2 is the base version. the base version is stored in the
42// "files" table, and the *reverse* diff delta(file.2, file.1) is stored in
43// the "file_deltas" table, under the id of file.1, with the id of file.2
44// listed as its base. note the use of the terms which describe
45// reconstruction; those are storage-system terms.
46//
47// the interface *to* the database, and the ancestry version graphs, use
48// the old / new metaphor of ancestry, but within the database (including
49// the private helper methods, and the storage version graphs) the
50// base/derived storage metaphor is used. the only real way to tell which
51// is which is to look at the parameter names and code. I might try to
52// express this in the type system some day, but not presently.
53//
54// the key phrase to keep repeating when working on this code is:
55//
56// "base files are new, derived files are old"
57//
58// it makes the code confusing, I know. this is possibly the worst part of
59// the program. I don't know if there's any way to make it clearer.
60
61class transaction_guard;
62class reverse_queue;
63struct posting;
64
65class database
66{
67 fs::path filename;
68 std::string const schema;
69 void check_schema();
70
71 struct sqlite * __sql;
72 struct sqlite * sql(bool init = false);
73 int transaction_level;
74
75 typedef std::vector< std::vector<std::string> > results;
76 void execute(char const * query, ...);
77 void fetch(results & res,
78 int const want_cols,
79 int const want_rows,
80 char const * query, ...);
81
82 bool exists(hexenc<id> const & ident,
83 std::string const & table);
84 bool delta_exists(hexenc<id> const & ident,
85 std::string const & table);
86 bool delta_exists(hexenc<id> const & ident,
87 hexenc<id> const & base,
88 std::string const & table);
89
90 int count(std::string const & table);
91
92 void get(hexenc<id> const & new_id,
93 base64< gzip<data> > & dat,
94 std::string const & table);
95 void get_delta(hexenc<id> const & ident,
96 hexenc<id> const & base,
97 base64< gzip<delta> > & del,
98 std::string const & table);
99 void get_version(hexenc<id> const & id,
100 base64< gzip<data> > & dat,
101 std::string const & data_table,
102 std::string const & delta_table);
103
104 void put(hexenc<id> const & new_id,
105 base64< gzip<data> > const & dat,
106 std::string const & table);
107 void drop(hexenc<id> const & base,
108 std::string const & table);
109 void put_delta(hexenc<id> const & id,
110 hexenc<id> const & base,
111 base64< gzip<delta> > const & del,
112 std::string const & table);
113 void put_version(hexenc<id> const & old_id,
114 hexenc<id> const & new_id,
115 base64< gzip<delta> > const & del,
116 std::string const & data_table,
117 std::string const & delta_table);
118
119 bool cert_exists(cert const & t,
120 std::string const & table);
121 void put_cert(cert const & t, std::string const & table);
122 void results_to_certs(results const & res,
123 std::vector<cert> & certs);
124
125 void get_certs(hexenc<id> const & id,
126std::vector< cert > & certs,
127std::string const & table);
128
129 void get_certs(cert_name const & name,
130std::vector< cert > & certs,
131std::string const & table);
132
133 void get_certs(hexenc<id> const & id,
134cert_name const & name,
135std::vector< cert > & certs,
136std::string const & table);
137
138 void get_certs(hexenc<id> const & id,
139cert_name const & name,
140base64<cert_value> const & val,
141std::vector< cert > & certs,
142std::string const & table);
143
144 void get_certs(cert_name const & name,
145base64<cert_value> const & val,
146std::vector<cert> & certs,
147std::string const & table);
148
149 void begin_transaction();
150 void commit_transaction();
151 void rollback_transaction();
152 friend class transaction_guard;
153 friend class reverse_queue;
154 friend void rcs_put_raw_file_edge(hexenc<id> const & old_id,
155 hexenc<id> const & new_id,
156 base64< gzip<delta> > const & del,
157 database & db);
158 friend void rcs_put_raw_manifest_edge(hexenc<id> const & old_id,
159hexenc<id> const & new_id,
160base64< gzip<delta> > const & del,
161database & db);
162
163public:
164
165 database(fs::path const & file);
166
167 unsigned long get_statistic(std::string const & query);
168 void set_filename(fs::path const & file);
169 void initialize();
170 void debug(std::string const & sql, std::ostream & out);
171 void dump(std::ostream &);
172 void load(std::istream &);
173 void info(std::ostream &);
174 void version(std::ostream &);
175 void migrate();
176 void rehash();
177 void ensure_open();
178
179 bool file_version_exists(file_id const & id);
180 bool manifest_version_exists(manifest_id const & id);
181
182 // get plain version if it exists, or reconstruct version
183 // from deltas (if they exist)
184 void get_file_version(file_id const & id,
185file_data & dat);
186
187 // put file w/o predecessor into db
188 void put_file(file_id const & new_id,
189file_data const & dat);
190
191 // store new version and update old version to be a delta
192 void put_file_version(file_id const & old_id,
193file_id const & new_id,
194file_delta const & del);
195
196 // get plain version if it exists, or reconstruct version
197 // from deltas (if they exist).
198 void get_manifest_version(manifest_id const & id,
199 manifest_data & dat);
200
201 // put manifest w/o predecessor into db
202 void put_manifest(manifest_id const & new_id,
203 manifest_data const & dat);
204
205 // store new version and update old version to be a delta
206 void put_manifest_version(manifest_id const & old_id,
207 manifest_id const & new_id,
208 manifest_delta const & del);
209
210 // only use these three variants if you really know what you're doing,
211 // wrt. "old" and "new". they will throw if you do something wrong.
212
213 bool manifest_delta_exists(manifest_id const & new_id,
214 manifest_id const & old_id);
215
216 void compute_older_version(manifest_id const & new_id,
217 manifest_id const & old_id,
218 data const & m_new,
219 data & m_old);
220
221 void compute_older_version(manifest_id const & new_id,
222 manifest_id const & old_id,
223 manifest_data const & m_new,
224 manifest_data & m_old);
225
226
227 // crypto key / cert operations
228
229 void get_key_ids(std::string const & pattern,
230 std::vector<rsa_keypair_id> & pubkeys,
231 std::vector<rsa_keypair_id> & privkeys);
232
233 void get_private_keys(std::vector<rsa_keypair_id> & privkeys);
234
235 bool key_exists(rsa_keypair_id const & id);
236
237 bool public_key_exists(hexenc<id> const & hash);
238 bool public_key_exists(rsa_keypair_id const & id);
239 bool private_key_exists(rsa_keypair_id const & id);
240
241 void get_pubkey(hexenc<id> const & hash,
242 rsa_keypair_id & id,
243 base64<rsa_pub_key> & pub_encoded);
244
245 void get_key(rsa_keypair_id const & id,
246 base64<rsa_pub_key> & pub_encoded);
247
248 void get_key(rsa_keypair_id const & id,
249 base64< arc4<rsa_priv_key> > & priv_encoded);
250
251 void put_key(rsa_keypair_id const & id,
252 base64<rsa_pub_key> const & pub_encoded);
253
254 void put_key(rsa_keypair_id const & id,
255 base64< arc4<rsa_priv_key> > const & priv_encoded);
256
257 void put_key_pair(rsa_keypair_id const & pub_id,
258 base64<rsa_pub_key> const & pub_encoded,
259 base64< arc4<rsa_priv_key> > const & priv_encoded);
260
261 // note: this section is ridiculous. please do something about it.
262
263 void get_head_candidates(std::string const & branch_encoded,
264 std::vector< manifest<cert> > & branch_certs,
265 std::vector< manifest<cert> > & ancestry_certs);
266
267 bool manifest_cert_exists(manifest<cert> const & cert);
268 bool manifest_cert_exists(hexenc<id> const & hash);
269
270 void put_manifest_cert(manifest<cert> const & cert);
271
272 void get_manifest_certs(cert_name const & name,
273 std::vector< manifest<cert> > & certs);
274
275 void get_manifest_certs(manifest_id const & id,
276 cert_name const & name,
277 std::vector< manifest<cert> > & certs);
278
279 void get_manifest_certs(cert_name const & name,
280 base64<cert_value> const & val,
281 std::vector< manifest<cert> > & certs);
282
283 void get_manifest_certs(manifest_id const & id,
284 cert_name const & name,
285 base64<cert_value> const & value,
286 std::vector< manifest<cert> > & certs);
287
288 void get_manifest_certs(manifest_id const & id,
289 std::vector< manifest<cert> > & certs);
290
291 void get_manifest_cert(hexenc<id> const & hash,
292 manifest<cert> & cert);
293
294
295 bool file_cert_exists(file<cert> const & cert);
296 bool file_cert_exists(hexenc<id> const & hash);
297
298 void put_file_cert(file<cert> const & cert);
299
300 void get_file_certs(file_id const & id,
301 std::vector< file<cert> > & certs);
302
303 void get_file_certs(cert_name const & name,
304 std::vector< file<cert> > & ts);
305
306 void get_file_certs(file_id const & id,
307 cert_name const & name,
308 std::vector< file<cert> > & ts);
309
310 void get_file_certs(file_id const & id,
311 cert_name const & name,
312 base64<cert_value> const & val,
313 std::vector< file<cert> > & ts);
314
315 void get_file_certs(cert_name const & name,
316 base64<cert_value> const & val,
317 std::vector< file<cert> > & certs);
318
319 void get_file_cert(hexenc<id> const & hash,
320 file<cert> & cert);
321
322 // network stuff
323
324 void get_queued_targets(std::set<url> & targets);
325
326 void get_queue_count(url const & u, size_t & num_packets);
327
328 void get_queued_content(url const & u,
329 size_t const & queue_pos,
330 std::string & content);
331
332 void get_sequences(url const & u,
333 unsigned long & maj,
334 unsigned long & min);
335
336 void get_all_known_sources(std::set<url> & sources);
337
338 void put_sequences(url const & u,
339 unsigned long maj,
340 unsigned long min);
341
342 void queue_posting(url const & u,
343 std::string const & contents);
344
345 void delete_posting(url const & u,
346 size_t const & queue_pos);
347
348
349 bool manifest_exists_on_netserver (url const & u,
350 manifest_id const & m);
351
352 void note_manifest_on_netserver (url const & u,
353 manifest_id const & m);
354
355 // merkle tree stuff
356
357 bool merkle_node_exists(std::string const & type,
358 utf8 const & collection,
359 size_t level,
360 hexenc<prefix> const & prefix);
361
362 void get_merkle_node(std::string const & type,
363 utf8 const & collection,
364 size_t level,
365 hexenc<prefix> const & prefix,
366 base64<merkle> & node);
367
368 void put_merkle_node(std::string const & type,
369 utf8 const & collection,
370 size_t level,
371 hexenc<prefix> const & prefix,
372 base64<merkle> const & node);
373
374 void erase_merkle_nodes(std::string const & type,
375 utf8 const & collection);
376
377 // completion stuff
378
379 void complete(std::string const & partial,
380std::set<manifest_id> & completions);
381
382 void complete(std::string const & partial,
383std::set<file_id> & completions);
384
385 ~database();
386
387};
388
389// transaction guards nest. acquire one in any scope you'd like
390// transaction-protected, and it'll make sure the db aborts a
391// txn if there's any exception before you call commit()
392
393class transaction_guard
394{
395 bool committed;
396 database & db;
397public:
398 transaction_guard(database & d);
399 ~transaction_guard();
400 void commit();
401};
402
403// a reverse_queue is an object which creates a temporary table for
404// postings, and then queues the postings (in reverse) to its database when
405// it is destroyed, and deletes the table.
406
407class reverse_queue
408{
409 database & db;
410public:
411 reverse_queue(database & d);
412 reverse_queue(reverse_queue const & other);
413 void reverse_queue_posting(url const & u,
414 std::string const & contents);
415 ~reverse_queue();
416};
417
418
419#endif // __DATABASE_HH__

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status