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 sqlite3;
10struct sqlite3_stmt;
11struct cert;
12int sqlite3_finalize(sqlite3_stmt *);
13
14#include <stdarg.h>
15
16#include <vector>
17#include <set>
18#include <map>
19#include <string>
20
21#include "selectors.hh"
22#include "manifest.hh"
23#include "numeric_vocab.hh"
24#include "vocab.hh"
25#include "paths.hh"
26#include "cleanup.hh"
27
28struct revision_set;
29
30// this file defines a public, typed interface to the database.
31// the database class encapsulates all knowledge about sqlite,
32// the schema, and all SQL statements used to access the schema.
33//
34// one thing which is rather important to note is that this file
35// deals with two sorts of version relationships. the versions
36// stored in the database are all *backwards* from those the program
37// sees. so for example if you have two versions of a file
38//
39// file.1, file.2
40//
41// where file.2 was a modification of file.1, then as far as the rest of
42// the application is concerned -- and the ancestry graph -- file.1 is the
43// "old" version and file.2 is the "new" version. note the use of terms
44// which describe time, and the sequence of edits a user makes to a
45// file. those are ancestry terms. when the application composes a
46// patchset, for example, it'll contain the diff delta(file.1, file.2)
47//
48// from the database's perspective, however, file.1 is the derived version,
49// and file.2 is the base version. the base version is stored in the
50// "files" table, and the *reverse* diff delta(file.2, file.1) is stored in
51// the "file_deltas" table, under the id of file.1, with the id of file.2
52// listed as its base. note the use of the terms which describe
53// reconstruction; those are storage-system terms.
54//
55// the interface *to* the database, and the ancestry version graphs, use
56// the old / new metaphor of ancestry, but within the database (including
57// the private helper methods, and the storage version graphs) the
58// base/derived storage metaphor is used. the only real way to tell which
59// is which is to look at the parameter names and code. I might try to
60// express this in the type system some day, but not presently.
61//
62// the key phrase to keep repeating when working on this code is:
63//
64// "base files are new, derived files are old"
65//
66// it makes the code confusing, I know. this is possibly the worst part of
67// the program. I don't know if there's any way to make it clearer.
68
69class transaction_guard;
70struct posting;
71struct app_state;
72
73class database
74{
75 system_path filename;
76 std::string const schema;
77 void check_schema();
78
79 struct statement {
80 statement() : count(0), stmt(0, sqlite3_finalize) {}
81 int count;
82 cleanup_ptr<sqlite3_stmt*, int> stmt;
83 };
84
85 std::map<std::string, statement> statement_cache;
86
87 struct app_state * __app;
88 struct sqlite3 * __sql;
89 struct sqlite3 * sql(bool init = false);
90 int transaction_level;
91 bool transaction_exclusive;
92
93 void install_functions(app_state * app);
94 void install_views();
95
96 typedef std::vector< std::vector<std::string> > results;
97
98 void execute(char const * query, ...);
99
100 void fetch(results & res,
101 int const want_cols,
102 int const want_rows,
103 char const * query, ...);
104
105 void fetch(results & res,
106 int const want_cols,
107 int const want_rows,
108 char const * query,
109 va_list args);
110
111 bool exists(hexenc<id> const & ident,
112 std::string const & table);
113 bool delta_exists(hexenc<id> const & ident,
114 std::string const & table);
115 bool delta_exists(hexenc<id> const & ident,
116 hexenc<id> const & base,
117 std::string const & table);
118
119 unsigned long count(std::string const & table);
120 unsigned long space_usage(std::string const & table,
121 std::string const & concatenated_columns);
122
123 void get_ids(std::string const & table, std::set< hexenc<id> > & ids);
124
125 void get(hexenc<id> const & new_id,
126 data & dat,
127 std::string const & table);
128 void get_delta(hexenc<id> const & ident,
129 hexenc<id> const & base,
130 delta & del,
131 std::string const & table);
132 void get_version(hexenc<id> const & id,
133 data & dat,
134 std::string const & data_table,
135 std::string const & delta_table);
136
137 void put(hexenc<id> const & new_id,
138 data const & dat,
139 std::string const & table);
140 void drop(hexenc<id> const & base,
141 std::string const & table);
142 void put_delta(hexenc<id> const & id,
143 hexenc<id> const & base,
144 delta const & del,
145 std::string const & table);
146 void put_version(hexenc<id> const & old_id,
147 hexenc<id> const & new_id,
148 delta const & del,
149 std::string const & data_table,
150 std::string const & delta_table);
151 void put_reverse_version(hexenc<id> const & new_id,
152 hexenc<id> const & old_id,
153 delta const & reverse_del,
154 std::string const & data_table,
155 std::string const & delta_table);
156
157 void get_keys(std::string const & table, std::vector<rsa_keypair_id> & keys);
158
159 bool cert_exists(cert const & t,
160 std::string const & table);
161 void put_cert(cert const & t, std::string const & table);
162 void results_to_certs(results const & res,
163 std::vector<cert> & certs);
164
165 void get_certs(std::vector< cert > & certs,
166 std::string const & table);
167
168 void get_certs(hexenc<id> const & id,
169 std::vector< cert > & certs,
170 std::string const & table);
171
172 void get_certs(cert_name const & name,
173 std::vector< cert > & certs,
174 std::string const & table);
175
176 void get_certs(hexenc<id> const & id,
177 cert_name const & name,
178 std::vector< cert > & certs,
179 std::string const & table);
180
181 void get_certs(hexenc<id> const & id,
182 cert_name const & name,
183 base64<cert_value> const & val,
184 std::vector< cert > & certs,
185 std::string const & table);
186
187 void get_certs(cert_name const & name,
188 base64<cert_value> const & val,
189 std::vector<cert> & certs,
190 std::string const & table);
191
192 void begin_transaction(bool exclusive);
193 void commit_transaction();
194 void rollback_transaction();
195 friend class transaction_guard;
196 friend void rcs_put_raw_file_edge(hexenc<id> const & old_id,
197 hexenc<id> const & new_id,
198 delta const & del,
199 database & db);
200 friend void rcs_put_raw_manifest_edge(hexenc<id> const & old_id,
201 hexenc<id> const & new_id,
202 delta const & del,
203 database & db);
204
205 void check_filename();
206 void check_db_exists();
207 void open();
208 void close();
209
210public:
211
212 database(system_path const & file);
213
214 void set_filename(system_path const & file);
215 void initialize();
216 void debug(std::string const & sql, std::ostream & out);
217 void dump(std::ostream &);
218 void load(std::istream &);
219 void info(std::ostream &);
220 void version(std::ostream &);
221 void migrate();
222 void rehash();
223 void ensure_open();
224 bool database_specified();
225
226 bool file_version_exists(file_id const & id);
227 bool manifest_version_exists(manifest_id const & id);
228 bool revision_exists(revision_id const & id);
229
230 void get_file_ids(std::set<file_id> & ids);
231 void get_manifest_ids(std::set<manifest_id> & ids);
232 void get_revision_ids(std::set<revision_id> & ids);
233
234 void set_app(app_state * app);
235
236 // get plain version if it exists, or reconstruct version
237 // from deltas (if they exist)
238 void get_file_version(file_id const & id,
239 file_data & dat);
240
241 // get file delta if it exists, else calculate it.
242 // both manifests must exist.
243 void get_file_delta(file_id const & src,
244 file_id const & dst,
245 file_delta & del);
246
247 // put file w/o predecessor into db
248 void put_file(file_id const & new_id,
249 file_data const & dat);
250
251 // store new version and update old version to be a delta
252 void put_file_version(file_id const & old_id,
253 file_id const & new_id,
254 file_delta const & del);
255
256 // load in a "direct" new -> old reverse edge (used during
257 // netsync and CVS load-in)
258 void put_file_reverse_version(file_id const & old_id,
259 file_id const & new_id,
260 file_delta const & del);
261
262 // get plain version if it exists, or reconstruct version
263 // from deltas (if they exist).
264 void get_manifest_version(manifest_id const & id,
265 manifest_data & dat);
266
267 // get a constructed manifest
268 void get_manifest(manifest_id const & id,
269 manifest_map & mm);
270
271 // get manifest delta if it exists, else calculate it.
272 // both manifests must exist.
273 void get_manifest_delta(manifest_id const & src,
274 manifest_id const & dst,
275 manifest_delta & del);
276
277 // put manifest w/o predecessor into db
278 void put_manifest(manifest_id const & new_id,
279 manifest_data const & dat);
280
281 // store new version and update old version to be a delta
282 void put_manifest_version(manifest_id const & old_id,
283 manifest_id const & new_id,
284 manifest_delta const & del);
285
286 // load in a "direct" new -> old reverse edge (used during
287 // netsync and CVS load-in)
288 void put_manifest_reverse_version(manifest_id const & old_id,
289 manifest_id const & new_id,
290 manifest_delta const & del);
291
292
293 void get_revision_ancestry(std::multimap<revision_id, revision_id> & graph);
294
295 void get_revision_parents(revision_id const & id,
296 std::set<revision_id> & parents);
297
298 void get_revision_children(revision_id const & id,
299 std::set<revision_id> & children);
300
301 void get_revision_manifest(revision_id const & cid,
302 manifest_id & mid);
303
304 void deltify_revision(revision_id const & rid);
305
306 void get_revision(revision_id const & id,
307 revision_set & cs);
308
309 void get_revision(revision_id const & id,
310 revision_data & dat);
311
312 void put_revision(revision_id const & new_id,
313 revision_set const & cs);
314
315 void put_revision(revision_id const & new_id,
316 revision_data const & dat);
317
318 void delete_existing_revs_and_certs();
319
320 void delete_existing_rev_and_certs(revision_id const & rid);
321
322 void delete_branch_named(cert_value const & branch);
323
324 void delete_tag_named(cert_value const & tag);
325
326 // crypto key / cert operations
327
328 void get_key_ids(std::string const & pattern,
329 std::vector<rsa_keypair_id> & pubkeys);
330
331 void get_public_keys(std::vector<rsa_keypair_id> & pubkeys);
332
333 bool public_key_exists(hexenc<id> const & hash);
334 bool public_key_exists(rsa_keypair_id const & id);
335
336
337 void get_pubkey(hexenc<id> const & hash,
338 rsa_keypair_id & id,
339 base64<rsa_pub_key> & pub_encoded);
340
341 void get_key(rsa_keypair_id const & id,
342 base64<rsa_pub_key> & pub_encoded);
343
344 void put_key(rsa_keypair_id const & id,
345 base64<rsa_pub_key> const & pub_encoded);
346
347 void delete_public_key(rsa_keypair_id const & pub_id);
348
349 // note: this section is ridiculous. please do something about it.
350
351 bool manifest_cert_exists(manifest<cert> const & cert);
352 bool manifest_cert_exists(hexenc<id> const & hash);
353 void put_manifest_cert(manifest<cert> const & cert);
354
355 bool revision_cert_exists(revision<cert> const & cert);
356 bool revision_cert_exists(hexenc<id> const & hash);
357
358 void put_revision_cert(revision<cert> const & cert);
359
360 // this variant has to be rather coarse and fast, for netsync's use
361 void get_revision_cert_nobranch_index(std::vector< std::pair<hexenc<id>,
362 std::pair<revision_id, rsa_keypair_id> > > & idx);
363
364 void get_revision_certs(std::vector< revision<cert> > & certs);
365
366 void get_revision_certs(cert_name const & name,
367 std::vector< revision<cert> > & certs);
368
369 void get_revision_certs(revision_id const & id,
370 cert_name const & name,
371 std::vector< revision<cert> > & certs);
372
373 void get_revision_certs(cert_name const & name,
374 base64<cert_value> const & val,
375 std::vector< revision<cert> > & certs);
376
377 void get_revision_certs(revision_id const & id,
378 cert_name const & name,
379 base64<cert_value> const & value,
380 std::vector< revision<cert> > & certs);
381
382 void get_revision_certs(revision_id const & id,
383 std::vector< revision<cert> > & certs);
384
385 void get_revision_cert(hexenc<id> const & hash,
386 revision<cert> & cert);
387
388 void get_manifest_certs(manifest_id const & id,
389 std::vector< manifest<cert> > & certs);
390
391 void get_manifest_certs(cert_name const & name,
392 std::vector< manifest<cert> > & certs);
393
394 void get_manifest_certs(manifest_id const & id,
395 cert_name const & name,
396 std::vector< manifest<cert> > & certs);
397
398 void get_manifest_cert(hexenc<id> const & hash,
399 manifest<cert> & cert);
400
401 // epochs
402
403 void get_epochs(std::map<cert_value, epoch_data> & epochs);
404
405 void get_epoch(epoch_id const & eid, cert_value & branch, epoch_data & epo);
406
407 bool epoch_exists(epoch_id const & eid);
408
409 void set_epoch(cert_value const & branch, epoch_data const & epo);
410
411 void clear_epoch(cert_value const & branch);
412
413 // vars
414
415 void get_vars(std::map<var_key, var_value > & vars);
416
417 void get_var(var_key const & key, var_value & value);
418
419 bool var_exists(var_key const & key);
420
421 void set_var(var_key const & key, var_value const & value);
422
423 void clear_var(var_key const & key);
424
425 // branches
426 void get_branches(std::vector<std::string> & names);
427
428 // completion stuff
429
430 void complete(std::string const & partial,
431 std::set<revision_id> & completions);
432
433 void complete(std::string const & partial,
434 std::set<manifest_id> & completions);
435
436 void complete(std::string const & partial,
437 std::set<file_id> & completions);
438
439 void complete(std::string const & partial,
440 std::set< std::pair<key_id, utf8 > > & completions);
441
442 void complete(selectors::selector_type ty,
443 std::string const & partial,
444 std::vector<std::pair<selectors::selector_type,
445 std::string> > const & limit,
446 std::set<std::string> & completions);
447
448 ~database();
449
450};
451
452// transaction guards nest. acquire one in any scope you'd like
453// transaction-protected, and it'll make sure the db aborts a
454// txn if there's any exception before you call commit()
455
456// by default, locks the database exclusively.
457// if the transaction is intended to be read-only, call with exclusive=False
458// in this case, if a database update is attempted and another process is accessing
459// the database an exception will be thrown - uglier and more confusing for the user -
460// however no data inconsistency should result.
461//
462// an exception is thrown if an exclusive transaction_guard is created while
463// a non-exclusive transaction_guard exists.
464
465class transaction_guard
466{
467 bool committed;
468 database & db;
469public:
470 transaction_guard(database & d, bool exclusive=true);
471 ~transaction_guard();
472 void commit();
473};
474
475void
476close_all_databases();
477
478
479#endif // __DATABASE_HH__

Archive Download this file

Branches

Tags

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