monotone

monotone Mtn Source Tree

Root/database.cc

1// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include <algorithm>
11#include <deque>
12#include <fstream>
13#include <iterator>
14#include <list>
15#include <set>
16#include <sstream>
17#include <vector>
18
19#include <string.h>
20
21#include <boost/shared_ptr.hpp>
22#include <boost/lexical_cast.hpp>
23
24#include <sqlite3.h>
25
26#include "app_state.hh"
27#include "cert.hh"
28#include "cleanup.hh"
29#include "constants.hh"
30#include "database.hh"
31#include "hash_map.hh"
32#include "keys.hh"
33#include "platform-wrapped.hh"
34#include "revision.hh"
35#include "safe_map.hh"
36#include "sanity.hh"
37#include "schema_migration.hh"
38#include "transforms.hh"
39#include "ui.hh"
40#include "vocab.hh"
41#include "vocab_cast.hh"
42#include "xdelta.hh"
43#include "epoch.hh"
44#include "graph.hh"
45#include "roster_delta.hh"
46#include "rev_height.hh"
47
48// defined in schema.sql, converted to header:
49#include "schema.h"
50
51// this file defines a public, typed interface to the database.
52// the database class encapsulates all knowledge about sqlite,
53// the schema, and all SQL statements used to access the schema.
54//
55// see file schema.sql for the text of the schema.
56
57using std::deque;
58using std::istream;
59using std::ifstream;
60using std::make_pair;
61using std::map;
62using std::multimap;
63using std::ostream;
64using std::pair;
65using std::set;
66using std::string;
67using std::vector;
68
69using boost::shared_ptr;
70using boost::lexical_cast;
71
72int const one_row = 1;
73int const one_col = 1;
74int const any_rows = -1;
75int const any_cols = -1;
76
77namespace
78{
79 struct query_param
80 {
81 enum arg_type { text, blob };
82 arg_type type;
83 string data;
84 };
85
86 query_param
87 text(string const & txt)
88 {
89 query_param q = {
90 query_param::text,
91 txt,
92 };
93 return q;
94 }
95
96 query_param
97 blob(string const & blb)
98 {
99 query_param q = {
100 query_param::blob,
101 blb,
102 };
103 return q;
104 }
105}
106
107struct query
108{
109 explicit query(string const & cmd)
110 : sql_cmd(cmd)
111 {}
112
113 query()
114 {}
115
116 query & operator %(query_param const & qp)
117 {
118 args.push_back(qp);
119 return *this;
120 }
121
122 vector<query_param> args;
123 string sql_cmd;
124};
125
126database::database(system_path const & fn) :
127 filename(fn),
128 __sql(NULL),
129 transaction_level(0),
130 roster_cache(constants::db_roster_cache_sz,
131 roster_writeback_manager(*this)),
132 delayed_writes_size(0)
133{}
134
135bool
136database::is_dbfile(any_path const & file)
137{
138 system_path fn(file);// why is this needed?
139 bool same = (filename.as_internal() == fn.as_internal());
140 if (same)
141 L(FL("'%s' is the database file") % file);
142 return same;
143}
144
145void
146database::check_is_not_rosterified()
147{
148 results res;
149 string rosters_query = "SELECT 1 FROM rosters LIMIT 1";
150 fetch(res, one_col, any_rows, query(rosters_query));
151 N(res.empty(),
152 F("this database already contains rosters"));
153}
154
155void
156database::check_format()
157{
158 results res;
159
160 // Check for manifests, revisions, rosters, and heights.
161 fetch(res, one_col, any_rows, query("SELECT 1 FROM manifests LIMIT 1"));
162 bool have_manifests = !res.empty();
163 fetch(res, one_col, any_rows, query("SELECT 1 FROM revisions LIMIT 1"));
164 bool have_revisions = !res.empty();
165 fetch(res, one_col, any_rows, query("SELECT 1 FROM rosters LIMIT 1"));
166 bool have_rosters = !res.empty();
167 fetch(res, one_col, any_rows, query("SELECT 1 FROM heights LIMIT 1"));
168 bool have_heights = !res.empty();
169
170
171 if (!have_manifests)
172 {
173 // Must have been changesetified and rosterified already.
174 // Or else the database was just created.
175 // Do we need to regenerate cached data?
176 E(!have_revisions || (have_rosters && have_heights),
177 F("database %s lacks some cached data\n"
178 "run '%s db regenerate_caches' to restore use of this database")
179 % filename % ui.prog_name);
180 }
181 else
182 {
183 // The rosters and heights tables should be empty.
184 I(!have_rosters && !have_heights);
185
186 // they need to either changesetify or rosterify. which?
187 if (have_revisions)
188 E(false,
189 F("database %s contains old-style revisions\n"
190 "if you are a project leader or doing local testing:\n"
191 " see the file UPGRADE for instructions on upgrading.\n"
192 "if you are not a project leader:\n"
193 " wait for a leader to migrate project data, and then\n"
194 " pull into a fresh database.\n"
195 "sorry about the inconvenience.")
196 % filename);
197 else
198 E(false,
199 F("database %s contains manifests but no revisions\n"
200 "this is a very old database; it needs to be upgraded\n"
201 "please see README.changesets for details")
202 % filename);
203 }
204}
205
206static void
207sqlite3_gunzip_fn(sqlite3_context *f, int nargs, sqlite3_value ** args)
208{
209 if (nargs != 1)
210 {
211 sqlite3_result_error(f, "need exactly 1 arg to gunzip()", -1);
212 return;
213 }
214 data unpacked;
215 const char *val = (const char*) sqlite3_value_blob(args[0]);
216 int bytes = sqlite3_value_bytes(args[0]);
217 decode_gzip(gzip<data>(string(val,val+bytes)), unpacked);
218 sqlite3_result_blob(f, unpacked().c_str(), unpacked().size(), SQLITE_TRANSIENT);
219}
220
221void
222database::set_app(app_state * app)
223{
224 __app = app;
225}
226
227struct sqlite3 *
228database::sql(enum open_mode mode)
229{
230 if (! __sql)
231 {
232 check_filename();
233 check_db_exists();
234 open();
235
236 if (mode != schema_bypass_mode)
237 {
238 check_sql_schema(__sql, filename);
239
240 if (mode != format_bypass_mode)
241 check_format();
242 }
243
244 install_functions(__app);
245 }
246 else
247 I(mode == normal_mode);
248
249 return __sql;
250}
251
252void
253database::initialize()
254{
255 check_filename();
256 check_db_nonexistent();
257 open();
258
259 sqlite3_exec(__sql, schema_constant, NULL, NULL, NULL);
260 assert_sqlite3_ok(__sql);
261
262 sqlite3_exec(__sql, (FL("PRAGMA user_version = %u;")
263 % mtn_creator_code).str().c_str(), NULL, NULL, NULL);
264 assert_sqlite3_ok(__sql);
265
266 // make sure what we wanted is what we got
267 check_sql_schema(__sql, filename);
268
269 close();
270}
271
272struct
273dump_request
274{
275 dump_request() : sql(), out() {};
276 struct sqlite3 *sql;
277 ostream *out;
278};
279
280static void
281dump_row(ostream &out, sqlite3_stmt *stmt, string const& table_name)
282{
283 out << FL("INSERT INTO %s VALUES(") % table_name;
284 unsigned n = sqlite3_data_count(stmt);
285 for (unsigned i = 0; i < n; ++i)
286 {
287 if (i != 0)
288 out << ',';
289
290 if (sqlite3_column_type(stmt, i) == SQLITE_BLOB)
291 {
292 out << "X'";
293 const char *val = (const char*) sqlite3_column_blob(stmt, i);
294 int bytes = sqlite3_column_bytes(stmt, i);
295 out << encode_hexenc(string(val,val+bytes));
296 out << '\'';
297 }
298 else
299 {
300 const unsigned char *val = sqlite3_column_text(stmt, i);
301 if (val == NULL)
302 out << "NULL";
303 else
304 {
305 out << '\'';
306 for (const unsigned char *cp = val; *cp; ++cp)
307 {
308 if (*cp == '\'')
309 out << "''";
310 else
311 out << *cp;
312 }
313 out << '\'';
314 }
315 }
316 }
317 out << ");\n";
318}
319
320static int
321dump_table_cb(void *data, int n, char **vals, char **cols)
322{
323 dump_request *dump = reinterpret_cast<dump_request *>(data);
324 I(dump != NULL);
325 I(dump->sql != NULL);
326 I(vals != NULL);
327 I(vals[0] != NULL);
328 I(vals[1] != NULL);
329 I(vals[2] != NULL);
330 I(n == 3);
331 I(string(vals[1]) == "table");
332 *(dump->out) << vals[2] << ";\n";
333 string table_name(vals[0]);
334 string query = "SELECT * FROM " + table_name;
335 sqlite3_stmt *stmt = 0;
336 sqlite3_prepare_v2(dump->sql, query.c_str(), -1, &stmt, NULL);
337 assert_sqlite3_ok(dump->sql);
338
339 int stepresult = SQLITE_DONE;
340 do
341 {
342 stepresult = sqlite3_step(stmt);
343 I(stepresult == SQLITE_DONE || stepresult == SQLITE_ROW);
344 if (stepresult == SQLITE_ROW)
345 dump_row(*(dump->out), stmt, table_name);
346 }
347 while (stepresult == SQLITE_ROW);
348
349 sqlite3_finalize(stmt);
350 assert_sqlite3_ok(dump->sql);
351 return 0;
352}
353
354static int
355dump_index_cb(void *data, int n, char **vals, char **cols)
356{
357 dump_request *dump = reinterpret_cast<dump_request *>(data);
358 I(dump != NULL);
359 I(dump->sql != NULL);
360 I(vals != NULL);
361 I(vals[0] != NULL);
362 I(vals[1] != NULL);
363 I(vals[2] != NULL);
364 I(n == 3);
365 I(string(vals[1]) == "index");
366 *(dump->out) << vals[2] << ";\n";
367 return 0;
368}
369
370static int
371dump_user_version_cb(void *data, int n, char **vals, char **cols)
372{
373 dump_request *dump = reinterpret_cast<dump_request *>(data);
374 I(dump != NULL);
375 I(dump->sql != NULL);
376 I(vals != NULL);
377 I(vals[0] != NULL);
378 I(n == 1);
379 *(dump->out) << "PRAGMA user_version = " << vals[0] << ";\n";
380 return 0;
381}
382
383void
384database::dump(ostream & out)
385{
386 ensure_open_for_maintenance();
387
388 {
389 transaction_guard guard(*this);
390 dump_request req;
391 req.out = &out;
392 req.sql = sql();
393 out << "BEGIN EXCLUSIVE;\n";
394 int res;
395 res = sqlite3_exec(req.sql,
396 "SELECT name, type, sql FROM sqlite_master "
397 "WHERE type='table' AND sql NOT NULL "
398 "AND name not like 'sqlite_stat%' "
399 "ORDER BY name",
400 dump_table_cb, &req, NULL);
401 assert_sqlite3_ok(req.sql);
402 res = sqlite3_exec(req.sql,
403 "SELECT name, type, sql FROM sqlite_master "
404 "WHERE type='index' AND sql NOT NULL "
405 "ORDER BY name",
406 dump_index_cb, &req, NULL);
407 assert_sqlite3_ok(req.sql);
408 res = sqlite3_exec(req.sql,
409 "PRAGMA user_version;",
410 dump_user_version_cb, &req, NULL);
411 assert_sqlite3_ok(req.sql);
412 out << "COMMIT;\n";
413 guard.commit();
414 }
415}
416
417void
418database::load(istream & in)
419{
420 string line;
421 string sql_stmt;
422
423 check_filename();
424 check_db_nonexistent();
425 open();
426
427 // the page size can only be set before any other commands have been executed
428 sqlite3_exec(__sql, "PRAGMA page_size=8192", NULL, NULL, NULL);
429
430 while(in)
431 {
432 getline(in, line, ';');
433 sql_stmt += line + ';';
434
435 if (sqlite3_complete(sql_stmt.c_str()))
436 {
437 sqlite3_exec(__sql, sql_stmt.c_str(), NULL, NULL, NULL);
438 sql_stmt.clear();
439 }
440 }
441
442 assert_sqlite3_ok(__sql);
443}
444
445
446void
447database::debug(string const & sql, ostream & out)
448{
449 ensure_open_for_maintenance();
450
451 results res;
452 fetch(res, any_cols, any_rows, query(sql));
453 out << '\'' << sql << "' -> " << res.size() << " rows\n\n";
454 for (size_t i = 0; i < res.size(); ++i)
455 {
456 for (size_t j = 0; j < res[i].size(); ++j)
457 {
458 if (j != 0)
459 out << " | ";
460 out << res[i][j];
461 }
462 out << '\n';
463 }
464}
465
466// Subroutine of info(). This compares strings that might either be numbers
467// or error messages surrounded by square brackets. We want the longest
468// number, even if there's an error message that's longer than that.
469static bool longest_number(string a, string b)
470{
471 if(a.length() > 0 && a[0] == '[')
472 return true; // b is longer
473 if(b.length() > 0 && b[0] == '[')
474 return false; // a is longer
475
476 return a.length() < b.length();
477}
478
479// Subroutine of info() and some things it calls.
480// Given an informative_failure which is believed to represent an SQLite
481// error, either return a string version of the error message (if it was an
482// SQLite error) or rethrow the execption (if it wasn't).
483static string
484format_sqlite_error_for_info(informative_failure const & e)
485{
486 string err(e.what());
487 string prefix = _("error: ");
488 prefix.append(_("sqlite error: "));
489 if (err.find(prefix) != 0)
490 throw;
491
492 err.replace(0, prefix.length(), "[");
493 string::size_type nl = err.find('\n');
494 if (nl != string::npos)
495 err.erase(nl);
496
497 err.append("]");
498 return err;
499}
500
501// Subroutine of info(). Pretty-print the database's "creator code", which
502// is a 32-bit unsigned number that we interpret as a four-character ASCII
503// string, provided that all four characters are graphic. (On disk, it's
504// stored in the "user version" field of the database.)
505static string
506format_creator_code(uint32_t code)
507{
508 char buf[5];
509 string result;
510
511 if (code == 0)
512 return _("not set");
513
514 buf[4] = '\0';
515 buf[3] = ((code & 0x000000ff) >> 0);
516 buf[2] = ((code & 0x0000ff00) >> 8);
517 buf[1] = ((code & 0x00ff0000) >> 16);
518 buf[0] = ((code & 0xff000000) >> 24);
519
520 if (isgraph(buf[0]) && isgraph(buf[1]) && isgraph(buf[2]) && isgraph(buf[3]))
521 result = (FL("%s (0x%08x)") % buf % code).str();
522 else
523 result = (FL("0x%08x") % code).str();
524 if (code != mtn_creator_code)
525 result += _(" (not a monotone database)");
526 return result;
527}
528
529
530void
531database::info(ostream & out)
532{
533 // don't check the schema
534 ensure_open_for_maintenance();
535
536 // do a dummy query to confirm that the database file is an sqlite3
537 // database. (this doesn't happen on open() because sqlite postpones the
538 // actual file open until the first access. we can't piggyback it on the
539 // query of the user version because there's a bug in sqlite 3.3.10:
540 // the routine that reads meta-values from the database header does not
541 // check the file format. reported as sqlite bug #2182.)
542 sqlite3_exec(__sql, "SELECT 1 FROM sqlite_master LIMIT 0", 0, 0, 0);
543 assert_sqlite3_ok(__sql);
544
545 uint32_t ccode;
546 {
547 results res;
548 fetch(res, one_col, one_row, query("PRAGMA user_version"));
549 I(res.size() == 1);
550 ccode = lexical_cast<uint32_t>(res[0][0]);
551 }
552
553 vector<string> counts;
554 counts.push_back(count("rosters"));
555 counts.push_back(count("roster_deltas"));
556 counts.push_back(count("files"));
557 counts.push_back(count("file_deltas"));
558 counts.push_back(count("revisions"));
559 counts.push_back(count("revision_ancestry"));
560 counts.push_back(count("revision_certs"));
561
562 {
563 results res;
564 try
565 {
566 fetch(res, one_col, any_rows,
567 query("SELECT node FROM next_roster_node_number"));
568 if (res.empty())
569 counts.push_back("0");
570 else
571 {
572 I(res.size() == 1);
573 counts.push_back((F("%u")
574 % (lexical_cast<u64>(res[0][0]) - 1)).str());
575 }
576 }
577 catch (informative_failure const & e)
578 {
579 counts.push_back(format_sqlite_error_for_info(e));
580 }
581 }
582
583 vector<string> bytes;
584 {
585 u64 total = 0;
586 bytes.push_back(space("rosters",
587 "length(id) + length(checksum) + length(data)",
588 total));
589 bytes.push_back(space("roster_deltas",
590 "length(id) + length(checksum)"
591 "+ length(base) + length(delta)", total));
592 bytes.push_back(space("files", "length(id) + length(data)", total));
593 bytes.push_back(space("file_deltas",
594 "length(id) + length(base) + length(delta)", total));
595 bytes.push_back(space("revisions", "length(id) + length(data)", total));
596 bytes.push_back(space("revision_ancestry",
597 "length(parent) + length(child)", total));
598 bytes.push_back(space("revision_certs",
599 "length(hash) + length(id) + length(name)"
600 "+ length(value) + length(keypair)"
601 "+ length(signature)", total));
602 bytes.push_back(space("heights", "length(revision) + length(height)",
603 total));
604 bytes.push_back((F("%u") % total).str());
605 }
606
607 // pad each vector's strings on the left with spaces to make them all the
608 // same length
609 {
610 string::size_type width
611 = max_element(counts.begin(), counts.end(), longest_number)->length();
612 for(vector<string>::iterator i = counts.begin(); i != counts.end(); i++)
613 if (width > i->length() && (*i)[0] != '[')
614 i->insert(0, width - i->length(), ' ');
615
616 width = max_element(bytes.begin(), bytes.end(), longest_number)->length();
617 for(vector<string>::iterator i = bytes.begin(); i != bytes.end(); i++)
618 if (width > i->length() && (*i)[0] != '[')
619 i->insert(0, width - i->length(), ' ');
620 }
621
622 i18n_format form =
623 F("creator code : %s\n"
624 "schema version : %s\n"
625 "counts:\n"
626 " full rosters : %s\n"
627 " roster deltas : %s\n"
628 " full files : %s\n"
629 " file deltas : %s\n"
630 " revisions : %s\n"
631 " ancestry edges : %s\n"
632 " certs : %s\n"
633 " logical files : %s\n"
634 "bytes:\n"
635 " full rosters : %s\n"
636 " roster deltas : %s\n"
637 " full files : %s\n"
638 " file deltas : %s\n"
639 " revisions : %s\n"
640 " cached ancestry : %s\n"
641 " certs : %s\n"
642 " heights : %s\n"
643 " total : %s\n"
644 "database:\n"
645 " page size : %s\n"
646 " cache size : %s"
647 );
648
649 form = form % format_creator_code(ccode);
650 form = form % describe_sql_schema(__sql);
651
652 for (vector<string>::iterator i = counts.begin(); i != counts.end(); i++)
653 form = form % *i;
654
655 for (vector<string>::iterator i = bytes.begin(); i != bytes.end(); i++)
656 form = form % *i;
657
658 form = form % page_size();
659 form = form % cache_size();
660
661 out << form.str() << '\n'; // final newline is kept out of the translation
662}
663
664void
665database::version(ostream & out)
666{
667 ensure_open_for_maintenance();
668 out << (F("database schema version: %s") % describe_sql_schema(__sql)).str()
669 << '\n';
670}
671
672void
673database::migrate()
674{
675 ensure_open_for_maintenance();
676 migrate_sql_schema(__sql, *__app);
677}
678
679void
680database::test_migration_step(string const & schema)
681{
682 ensure_open_for_maintenance();
683 ::test_migration_step(__sql, *__app, schema);
684}
685
686void
687database::ensure_open()
688{
689 sql();
690}
691
692void
693database::ensure_open_for_format_changes()
694{
695 sql(format_bypass_mode);
696}
697
698void
699database::ensure_open_for_maintenance()
700{
701 sql(schema_bypass_mode);
702}
703
704database::~database()
705{
706 L(FL("statement cache statistics"));
707 L(FL("prepared %d statements") % statement_cache.size());
708
709 for (map<string, statement>::const_iterator i = statement_cache.begin();
710 i != statement_cache.end(); ++i)
711 L(FL("%d executions of %s") % i->second.count % i->first);
712 // trigger destructors to finalize cached statements
713 statement_cache.clear();
714
715 if (__sql)
716 close();
717}
718
719void
720database::execute(query const & query)
721{
722 results res;
723 fetch(res, 0, 0, query);
724}
725
726void
727database::fetch(results & res,
728 int const want_cols,
729 int const want_rows,
730 query const & query)
731{
732 int nrow;
733 int ncol;
734 int rescode;
735
736 res.clear();
737 res.resize(0);
738
739 map<string, statement>::iterator i = statement_cache.find(query.sql_cmd);
740 if (i == statement_cache.end())
741 {
742 statement_cache.insert(make_pair(query.sql_cmd, statement()));
743 i = statement_cache.find(query.sql_cmd);
744 I(i != statement_cache.end());
745
746 const char * tail;
747 sqlite3_prepare_v2(sql(), query.sql_cmd.c_str(), -1, i->second.stmt.paddr(), &tail);
748 assert_sqlite3_ok(sql());
749 L(FL("prepared statement %s") % query.sql_cmd);
750
751 // no support for multiple statements here
752 E(*tail == 0,
753 F("multiple statements in query: %s") % query.sql_cmd);
754 }
755
756 ncol = sqlite3_column_count(i->second.stmt());
757
758 E(want_cols == any_cols || want_cols == ncol,
759 F("wanted %d columns got %d in query: %s") % want_cols % ncol % query.sql_cmd);
760
761 // bind parameters for this execution
762
763 int params = sqlite3_bind_parameter_count(i->second.stmt());
764
765 // Ensure that exactly the right number of parameters were given
766 I(params == int(query.args.size()));
767
768 // profiling finds this logging to be quite expensive
769 if (global_sanity.debug)
770 L(FL("binding %d parameters for %s") % params % query.sql_cmd);
771
772 for (int param = 1; param <= params; param++)
773 {
774 // profiling finds this logging to be quite expensive
775 if (global_sanity.debug)
776 {
777 string log;
778 switch (query.args[param-1].type)
779 {
780 case query_param::text:
781 case query_param::blob:
782 log = query.args[param-1].data;
783 break;
784 }
785
786 if (log.size() > constants::log_line_sz)
787 log = log.substr(0, constants::log_line_sz);
788
789 L(FL("binding %d with value '%s'") % param % log);
790 }
791
792 switch (idx(query.args, param - 1).type)
793 {
794 case query_param::text:
795 sqlite3_bind_text(i->second.stmt(), param,
796 idx(query.args, param - 1).data.c_str(), -1,
797 SQLITE_STATIC);
798 break;
799 case query_param::blob:
800 {
801 string const & data = idx(query.args, param - 1).data;
802 sqlite3_bind_blob(i->second.stmt(), param,
803 data.data(), data.size(),
804 SQLITE_STATIC);
805 }
806 break;
807 default:
808 I(false);
809 }
810
811 assert_sqlite3_ok(sql());
812 }
813
814 // execute and process results
815
816 nrow = 0;
817 for (rescode = sqlite3_step(i->second.stmt()); rescode == SQLITE_ROW;
818 rescode = sqlite3_step(i->second.stmt()))
819 {
820 vector<string> row;
821 for (int col = 0; col < ncol; col++)
822 {
823 const char * value = (const char*)sqlite3_column_blob(i->second.stmt(), col);
824 int bytes = sqlite3_column_bytes(i->second.stmt(), col);
825 E(value, F("null result in query: %s") % query.sql_cmd);
826 row.push_back(string(value, value + bytes));
827 //L(FL("row %d col %d value='%s'") % nrow % col % value);
828 }
829 res.push_back(row);
830 }
831
832 if (rescode != SQLITE_DONE)
833 assert_sqlite3_ok(sql());
834
835 sqlite3_reset(i->second.stmt());
836 assert_sqlite3_ok(sql());
837
838 nrow = res.size();
839
840 i->second.count++;
841
842 E(want_rows == any_rows || want_rows == nrow,
843 F("wanted %d rows got %d in query: %s") % want_rows % nrow % query.sql_cmd);
844}
845
846bool
847database::table_has_entry(std::string const & key, std::string const & column,
848 std::string const & table)
849{
850 results res;
851 query q("SELECT 1 FROM " + table + " WHERE " + column + " = ? LIMIT 1");
852 fetch(res, one_col, any_rows, q % text(key));
853 return !res.empty();
854}
855
856// general application-level logic
857
858void
859database::set_filename(system_path const & file)
860{
861 I(!__sql);
862 filename = file;
863}
864
865system_path
866database::get_filename()
867{
868 return filename;
869}
870
871void
872database::begin_transaction(bool exclusive)
873{
874 if (transaction_level == 0)
875 {
876 I(delayed_files.empty());
877 I(roster_cache.all_clean());
878 if (exclusive)
879 execute(query("BEGIN EXCLUSIVE"));
880 else
881 execute(query("BEGIN DEFERRED"));
882 transaction_exclusive = exclusive;
883 }
884 else
885 {
886 // You can't start an exclusive transaction within a non-exclusive
887 // transaction
888 I(!exclusive || transaction_exclusive);
889 }
890 transaction_level++;
891}
892
893
894size_t
895database::size_delayed_file(file_id const & id, file_data const & dat)
896{
897 return id.inner()().size() + dat.inner()().size();
898}
899
900bool
901database::have_delayed_file(file_id const & id)
902{
903 return delayed_files.find(id) != delayed_files.end();
904}
905
906void
907database::load_delayed_file(file_id const & id, file_data & dat)
908{
909 dat = safe_get(delayed_files, id);
910}
911
912// precondition: have_delayed_file(an_id) == true
913void
914database::cancel_delayed_file(file_id const & an_id)
915{
916 file_data const & dat = safe_get(delayed_files, an_id);
917 size_t cancel_size = size_delayed_file(an_id, dat);
918 I(cancel_size <= delayed_writes_size);
919 delayed_writes_size -= cancel_size;
920
921 safe_erase(delayed_files, an_id);
922}
923
924void
925database::schedule_delayed_file(file_id const & an_id,
926 file_data const & dat)
927{
928 if (!have_delayed_file(an_id))
929 {
930 safe_insert(delayed_files, make_pair(an_id, dat));
931 delayed_writes_size += size_delayed_file(an_id, dat);
932 }
933 if (delayed_writes_size > constants::db_max_delayed_file_bytes)
934 flush_delayed_writes();
935}
936
937void
938database::flush_delayed_writes()
939{
940 for (map<file_id, file_data>::const_iterator i = delayed_files.begin();
941 i != delayed_files.end(); ++i)
942 write_delayed_file(i->first, i->second);
943 clear_delayed_writes();
944}
945
946void
947database::clear_delayed_writes()
948{
949 delayed_files.clear();
950 delayed_writes_size = 0;
951}
952
953void
954database::roster_writeback_manager::writeout(revision_id const & id,
955 cached_roster const & cr)
956{
957 I(cr.first);
958 I(cr.second);
959 db.write_delayed_roster(id, *(cr.first), *(cr.second));
960}
961
962unsigned long
963database::roster_size_estimator::operator()(cached_roster const & cr)
964{
965 I(cr.first);
966 I(cr.second);
967 // do estimate using a totally made up multiplier, probably wildly off
968 return cr.first->all_nodes().size() * constants::db_estimated_roster_node_sz;
969}
970
971void
972database::commit_transaction()
973{
974 if (transaction_level == 1)
975 {
976 flush_delayed_writes();
977 roster_cache.clean_all();
978 execute(query("COMMIT"));
979 }
980 transaction_level--;
981}
982
983void
984database::rollback_transaction()
985{
986 if (transaction_level == 1)
987 {
988 clear_delayed_writes();
989 roster_cache.clear_and_drop_writes();
990 execute(query("ROLLBACK"));
991 }
992 transaction_level--;
993}
994
995
996bool
997database::file_or_manifest_base_exists(hexenc<id> const & ident,
998 std::string const & table)
999{
1000 // just check for a delayed file, since there are no delayed manifests
1001 if (have_delayed_file(file_id(ident)))
1002 return true;
1003 return table_has_entry(ident(), "id", table);
1004}
1005
1006// returns true if we are currently storing (or planning to store) a
1007// full-text for 'ident'
1008bool
1009database::roster_base_stored(revision_id const & ident)
1010{
1011 if (roster_cache.exists(ident) && roster_cache.is_dirty(ident))
1012 return true;
1013 return table_has_entry(ident.inner()(), "id", "rosters");
1014}
1015
1016// returns true if we currently have a full-text for 'ident' available
1017// (possibly cached). Warning: the results of this method are invalidated
1018// by calling roster_cache.insert_{clean,dirty}, because they can trigger
1019// cache cleaning.
1020bool
1021database::roster_base_available(revision_id const & ident)
1022{
1023 if (roster_cache.exists(ident))
1024 return true;
1025 return table_has_entry(ident.inner()(), "id", "rosters");
1026}
1027
1028bool
1029database::delta_exists(string const & ident,
1030 string const & table)
1031{
1032 return table_has_entry(ident, "id", table);
1033}
1034
1035string
1036database::count(string const & table)
1037{
1038 try
1039 {
1040 results res;
1041 query q("SELECT COUNT(*) FROM " + table);
1042 fetch(res, one_col, one_row, q);
1043 return (F("%u") % lexical_cast<u64>(res[0][0])).str();
1044 }
1045 catch (informative_failure const & e)
1046 {
1047 return format_sqlite_error_for_info(e);
1048 }
1049
1050}
1051
1052string
1053database::space(string const & table, string const & rowspace, u64 & total)
1054{
1055 try
1056 {
1057 results res;
1058 // SUM({empty set}) is NULL; TOTAL({empty set}) is 0.0
1059 query q("SELECT TOTAL(" + rowspace + ") FROM " + table);
1060 fetch(res, one_col, one_row, q);
1061 u64 bytes = static_cast<u64>(lexical_cast<double>(res[0][0]));
1062 total += bytes;
1063 return (F("%u") % bytes).str();
1064 }
1065 catch (informative_failure & e)
1066 {
1067 return format_sqlite_error_for_info(e);
1068 }
1069}
1070
1071unsigned int
1072database::page_size()
1073{
1074 results res;
1075 query q("PRAGMA page_size");
1076 fetch(res, one_col, one_row, q);
1077 return lexical_cast<unsigned int>(res[0][0]);
1078}
1079
1080unsigned int
1081database::cache_size()
1082{
1083 // This returns the persistent (default) cache size. It's possible to
1084 // override this setting transiently at runtime by setting PRAGMA
1085 // cache_size.
1086 results res;
1087 query q("PRAGMA default_cache_size");
1088 fetch(res, one_col, one_row, q);
1089 return lexical_cast<unsigned int>(res[0][0]);
1090}
1091
1092void
1093database::get_ids(string const & table, set< hexenc<id> > & ids)
1094{
1095 results res;
1096 query q("SELECT id FROM " + table);
1097 fetch(res, one_col, any_rows, q);
1098
1099 for (size_t i = 0; i < res.size(); ++i)
1100 {
1101 ids.insert(hexenc<id>(res[i][0]));
1102 }
1103}
1104
1105// for files and legacy manifest support
1106void
1107database::get_file_or_manifest_base_unchecked(hexenc<id> const & ident,
1108 data & dat,
1109 string const & table)
1110{
1111 if (have_delayed_file(file_id(ident)))
1112 {
1113 file_data tmp;
1114 load_delayed_file(file_id(ident), tmp);
1115 dat = tmp.inner();
1116 return;
1117 }
1118
1119 results res;
1120 query q("SELECT data FROM " + table + " WHERE id = ?");
1121 fetch(res, one_col, one_row, q % text(ident()));
1122
1123 gzip<data> rdata(res[0][0]);
1124 data rdata_unpacked;
1125 decode_gzip(rdata,rdata_unpacked);
1126
1127 dat = rdata_unpacked;
1128}
1129
1130// for files and legacy manifest support
1131void
1132database::get_file_or_manifest_delta_unchecked(hexenc<id> const & ident,
1133 hexenc<id> const & base,
1134 delta & del,
1135 string const & table)
1136{
1137 I(ident() != "");
1138 I(base() != "");
1139 results res;
1140 query q("SELECT delta FROM " + table + " WHERE id = ? AND base = ?");
1141 fetch(res, one_col, one_row, q % text(ident()) % text(base()));
1142
1143 gzip<delta> del_packed(res[0][0]);
1144 decode_gzip(del_packed, del);
1145}
1146
1147void
1148database::get_roster_base(string const & ident_str,
1149 roster_t & roster, marking_map & marking)
1150{
1151 revision_id ident(ident_str);
1152 if (roster_cache.exists(ident))
1153 {
1154 cached_roster cr;
1155 roster_cache.fetch(ident, cr);
1156 I(cr.first);
1157 roster = *(cr.first);
1158 I(cr.second);
1159 marking = *(cr.second);
1160 return;
1161 }
1162 results res;
1163 query q("SELECT checksum, data FROM rosters WHERE id = ?");
1164 fetch(res, 2, one_row, q % text(ident_str));
1165
1166 hexenc<id> checksum(res[0][0]);
1167 hexenc<id> calculated;
1168 calculate_ident(data(res[0][1]), calculated);
1169 I(calculated == checksum);
1170
1171 gzip<data> dat_packed(res[0][1]);
1172 data dat;
1173 decode_gzip(dat_packed, dat);
1174 read_roster_and_marking(roster_data(dat), roster, marking);
1175}
1176
1177void
1178database::get_roster_delta(string const & ident,
1179 string const & base,
1180 roster<delta> & del)
1181{
1182 results res;
1183 query q("SELECT checksum, delta FROM roster_deltas WHERE id = ? AND base = ?");
1184 fetch(res, 2, one_row, q % text(ident) % text(base));
1185
1186 hexenc<id> checksum(res[0][0]);
1187 hexenc<id> calculated;
1188 calculate_ident(data(res[0][1]), calculated);
1189 I(calculated == checksum);
1190
1191 gzip<delta> del_packed(res[0][1]);
1192 delta tmp;
1193 decode_gzip(del_packed, tmp);
1194 del = roster<delta>(tmp);
1195}
1196
1197void
1198database::write_delayed_file(file_id const & ident,
1199 file_data const & dat)
1200{
1201 gzip<data> dat_packed;
1202 encode_gzip(dat.inner(), dat_packed);
1203
1204 // ident is a hash, which we should check
1205 I(!null_id(ident));
1206 file_id tid;
1207 calculate_ident(dat, tid);
1208 MM(ident);
1209 MM(tid);
1210 I(tid == ident);
1211 // and then write things to the db
1212 query q("INSERT INTO files (id, data) VALUES (?, ?)");
1213 execute(q % text(ident.inner()()) % blob(dat_packed()));
1214}
1215
1216void
1217database::write_delayed_roster(revision_id const & ident,
1218 roster_t const & roster,
1219 marking_map const & marking)
1220{
1221 roster_data dat;
1222 write_roster_and_marking(roster, marking, dat);
1223 gzip<data> dat_packed;
1224 encode_gzip(dat.inner(), dat_packed);
1225
1226 // ident is a number, and we should calculate a checksum on what
1227 // we write
1228 hexenc<id> checksum;
1229 calculate_ident(data(dat_packed()), checksum);
1230
1231 // and then write it
1232 query q("INSERT INTO rosters (id, checksum, data) VALUES (?, ?, ?)");
1233 execute(q % text(ident.inner()()) % text(checksum()) % blob(dat_packed()));
1234}
1235
1236
1237void
1238database::put_file_delta(file_id const & ident,
1239 file_id const & base,
1240 file_delta const & del)
1241{
1242 // nb: delta schema is (id, base, delta)
1243 I(!null_id(ident));
1244 I(!null_id(base));
1245
1246 gzip<delta> del_packed;
1247 encode_gzip(del.inner(), del_packed);
1248
1249 query q("INSERT INTO file_deltas VALUES (?, ?, ?)");
1250 execute(q
1251 % text(ident.inner()())
1252 % text(base.inner()())
1253 % blob(del_packed()));
1254}
1255
1256void
1257database::put_roster_delta(revision_id const & ident,
1258 revision_id const & base,
1259 roster_delta const & del)
1260{
1261 gzip<delta> del_packed;
1262 encode_gzip(del.inner(), del_packed);
1263
1264 hexenc<id> checksum;
1265 calculate_ident(data(del_packed()), checksum);
1266
1267 query q("INSERT INTO roster_deltas (id, base, checksum, delta) VALUES (?, ?, ?, ?)");
1268 execute(q
1269 % text(ident.inner()())
1270 % text(base.inner()())
1271 % text(checksum())
1272 % blob(del_packed()));
1273}
1274
1275
1276// static ticker cache_hits("vcache hits", "h", 1);
1277
1278struct datasz
1279{
1280 unsigned long operator()(data const & t) { return t().size(); }
1281};
1282
1283static LRUWritebackCache<string, data, datasz>
1284vcache(constants::db_version_cache_sz);
1285
1286struct file_and_manifest_reconstruction_graph : public reconstruction_graph
1287{
1288 database & db;
1289 string const & data_table;
1290 string const & delta_table;
1291
1292 file_and_manifest_reconstruction_graph(database & db,
1293 string const & data_table,
1294 string const & delta_table)
1295 : db(db), data_table(data_table), delta_table(delta_table)
1296 {}
1297 virtual bool is_base(std::string const & node) const
1298 {
1299 return vcache.exists(node)
1300 || db.file_or_manifest_base_exists(hexenc<id>(node), data_table);
1301 }
1302 virtual void get_next(std::string const & from, std::set<std::string> & next) const
1303 {
1304 next.clear();
1305 database::results res;
1306 query q("SELECT base FROM " + delta_table + " WHERE id = ?");
1307 db.fetch(res, one_col, any_rows, q % text(from));
1308 for (database::results::const_iterator i = res.begin(); i != res.end(); ++i)
1309 next.insert((*i)[0]);
1310 }
1311};
1312
1313// used for files and legacy manifest migration
1314void
1315database::get_version(hexenc<id> const & ident,
1316 data & dat,
1317 string const & data_table,
1318 string const & delta_table)
1319{
1320 I(ident() != "");
1321
1322 reconstruction_path selected_path;
1323 {
1324 file_and_manifest_reconstruction_graph graph(*this, data_table, delta_table);
1325 get_reconstruction_path(ident(), graph, selected_path);
1326 }
1327
1328 I(!selected_path.empty());
1329
1330 hexenc<id> curr = hexenc<id>(selected_path.back());
1331 selected_path.pop_back();
1332 data begin;
1333
1334 if (vcache.exists(curr()))
1335 I(vcache.fetch(curr(), begin));
1336 else
1337 get_file_or_manifest_base_unchecked(curr, begin, data_table);
1338
1339 shared_ptr<delta_applicator> appl = new_piecewise_applicator();
1340 appl->begin(begin());
1341
1342 for (reconstruction_path::reverse_iterator i = selected_path.rbegin();
1343 i != selected_path.rend(); ++i)
1344 {
1345 hexenc<id> const nxt = hexenc<id>(*i);
1346
1347 if (!vcache.exists(curr()))
1348 {
1349 string tmp;
1350 appl->finish(tmp);
1351 vcache.insert_clean(curr(), data(tmp));
1352 }
1353
1354 L(FL("following delta %s -> %s") % curr % nxt);
1355 delta del;
1356 get_file_or_manifest_delta_unchecked(nxt, curr, del, delta_table);
1357 apply_delta(appl, del());
1358
1359 appl->next();
1360 curr = nxt;
1361 }
1362
1363 string tmp;
1364 appl->finish(tmp);
1365 dat = data(tmp);
1366
1367 hexenc<id> final;
1368 calculate_ident(dat, final);
1369 I(final == ident);
1370
1371 if (!vcache.exists(ident()))
1372 vcache.insert_clean(ident(), dat);
1373}
1374
1375struct roster_reconstruction_graph : public reconstruction_graph
1376{
1377 database & db;
1378 roster_reconstruction_graph(database & db) : db(db) {}
1379 virtual bool is_base(std::string const & node) const
1380 {
1381 return db.roster_base_available(revision_id(node));
1382 }
1383 virtual void get_next(std::string const & from, std::set<std::string> & next) const
1384 {
1385 next.clear();
1386 database::results res;
1387 query q("SELECT base FROM roster_deltas WHERE id = ?");
1388 db.fetch(res, one_col, any_rows, q % text(from));
1389 for (database::results::const_iterator i = res.begin(); i != res.end(); ++i)
1390 next.insert((*i)[0]);
1391 }
1392};
1393
1394struct database::extractor
1395{
1396 virtual bool look_at_delta(roster_delta const & del) = 0;
1397 virtual void look_at_roster(roster_t const & roster, marking_map const & mm) = 0;
1398 virtual ~extractor() {};
1399};
1400
1401struct database::markings_extractor : public database::extractor
1402{
1403private:
1404 node_id const & nid;
1405 marking_t & markings;
1406
1407public:
1408 markings_extractor(node_id const & _nid, marking_t & _markings) :
1409 nid(_nid), markings(_markings) {} ;
1410
1411 bool look_at_delta(roster_delta const & del)
1412 {
1413 return try_get_markings_from_roster_delta(del, nid, markings);
1414 }
1415
1416 void look_at_roster(roster_t const & roster, marking_map const & mm)
1417 {
1418 map<node_id, marking_t>::const_iterator mmi =
1419 mm.find(nid);
1420 I(mmi != mm.end());
1421 markings = mmi->second;
1422 }
1423};
1424
1425struct database::file_content_extractor : database::extractor
1426{
1427private:
1428 node_id const & nid;
1429 file_id & content;
1430
1431public:
1432 file_content_extractor(node_id const & _nid, file_id & _content) :
1433 nid(_nid), content(_content) {} ;
1434
1435 bool look_at_delta(roster_delta const & del)
1436 {
1437 return try_get_content_from_roster_delta(del, nid, content);
1438 }
1439
1440 void look_at_roster(roster_t const & roster, marking_map const & mm)
1441 {
1442 if (roster.has_node(nid))
1443 content = downcast_to_file_t(roster.get_node(nid))->content;
1444 else
1445 content = file_id();
1446 }
1447};
1448
1449void
1450database::extract_from_deltas(revision_id const & id, extractor & x)
1451{
1452 reconstruction_path selected_path;
1453 {
1454 roster_reconstruction_graph graph(*this);
1455 {
1456 // we look at the nearest delta(s) first, without constructing the
1457 // whole path, as that would be a rather expensive operation.
1458 //
1459 // the reason why this strategy is worth the effort is, that in most
1460 // cases we are looking at the parent of a (content-)marked node, thus
1461 // the information we are for is right there in the delta leading to
1462 // this node.
1463 //
1464 // recording the deltas visited here in a set as to avoid inspecting
1465 // them later seems to be of little value, as it imposes a cost here,
1466 // but can seldom be exploited.
1467 set<string> deltas;
1468 graph.get_next(id.inner()(), deltas);
1469 for (set<string>::const_iterator i = deltas.begin();
1470 i != deltas.end(); ++i)
1471 {
1472 roster_delta del;
1473 get_roster_delta(id.inner()(), *i, del);
1474 bool found = x.look_at_delta(del);
1475 if (found)
1476 return;
1477 }
1478 }
1479 get_reconstruction_path(id.inner()(), graph, selected_path);
1480 }
1481
1482 int path_length(selected_path.size());
1483 int i(0);
1484 string target_rev;
1485
1486 for (reconstruction_path::const_iterator p = selected_path.begin();
1487 p != selected_path.end(); ++p)
1488 {
1489 if (i > 0)
1490 {
1491 roster_delta del;
1492 get_roster_delta(target_rev, *p, del);
1493 bool found = x.look_at_delta(del);
1494 if (found)
1495 return;
1496 }
1497 if (i == path_length-1)
1498 {
1499 // last iteration, we have reached a roster base
1500 roster_t roster;
1501 marking_map mm;
1502 get_roster_base(*p, roster, mm);
1503 x.look_at_roster(roster, mm);
1504 return;
1505 }
1506 target_rev = *p;
1507 ++i;
1508 }
1509}
1510
1511void
1512database::get_markings(revision_id const & id,
1513 node_id const & nid,
1514 marking_t & markings)
1515{
1516 markings_extractor x(nid, markings);
1517 extract_from_deltas(id, x);
1518}
1519
1520void
1521database::get_file_content(revision_id const & id,
1522 node_id const & nid,
1523 file_id & content)
1524{
1525 // the imaginary root revision doesn't have any file.
1526 if (null_id(id))
1527 {
1528 content = file_id();
1529 return;
1530 }
1531 file_content_extractor x(nid, content);
1532 extract_from_deltas(id, x);
1533}
1534
1535void
1536database::get_roster_version(revision_id const & id,
1537 cached_roster & cr)
1538{
1539 // if we already have it, exit early
1540 if (roster_cache.exists(id))
1541 {
1542 roster_cache.fetch(id, cr);
1543 return;
1544 }
1545
1546 reconstruction_path selected_path;
1547 {
1548 roster_reconstruction_graph graph(*this);
1549 get_reconstruction_path(id.inner()(), graph, selected_path);
1550 }
1551
1552 string curr = selected_path.back();
1553 selected_path.pop_back();
1554 // we know that this isn't already in the cache (because of the early exit
1555 // above), so we should create new objects and spend time filling them in.
1556 shared_ptr<roster_t> roster(new roster_t);
1557 shared_ptr<marking_map> marking(new marking_map);
1558 get_roster_base(curr, *roster, *marking);
1559
1560 for (reconstruction_path::reverse_iterator i = selected_path.rbegin();
1561 i != selected_path.rend(); ++i)
1562 {
1563 string const nxt = *i;
1564 L(FL("following delta %s -> %s") % curr % nxt);
1565 roster_delta del;
1566 get_roster_delta(nxt, curr, del);
1567 apply_roster_delta(del, *roster, *marking);
1568 curr = nxt;
1569 }
1570
1571 // Double-check that the thing we got out looks okay. We know that when
1572 // the roster was written to the database, it passed both of these tests,
1573 // and we also know that the data on disk has passed our checks for data
1574 // corruption -- so in theory, we know that what we got out is exactly
1575 // what we put in, and these checks are redundant. (They cannot catch all
1576 // possible errors in any case, e.g., they don't test that the marking is
1577 // correct.) What they can do, though, is serve as a sanity check on the
1578 // delta reconstruction code; if there is a bug where we put something
1579 // into the database and then later get something different back out, then
1580 // this is the only thing that can catch it.
1581 roster->check_sane_against(*marking);
1582 manifest_id expected_mid, actual_mid;
1583 get_revision_manifest(id, expected_mid);
1584 calculate_ident(*roster, actual_mid);
1585 I(expected_mid == actual_mid);
1586
1587 // const'ify the objects, to save them and pass them out
1588 cr.first = roster;
1589 cr.second = marking;
1590 roster_cache.insert_clean(id, cr);
1591}
1592
1593
1594void
1595database::drop(string const & ident,
1596 string const & table)
1597{
1598 string drop = "DELETE FROM " + table + " WHERE id = ?";
1599 execute(query(drop) % text(ident));
1600}
1601
1602// ------------------------------------------------------------
1603// -- --
1604// -- public interface follows --
1605// -- --
1606// ------------------------------------------------------------
1607
1608bool
1609database::file_version_exists(file_id const & id)
1610{
1611 return delta_exists(id.inner()(), "file_deltas")
1612 || file_or_manifest_base_exists(id.inner(), "files");
1613}
1614
1615bool
1616database::roster_version_exists(revision_id const & id)
1617{
1618 return delta_exists(id.inner()(), "roster_deltas")
1619 || roster_base_available(id);
1620}
1621
1622bool
1623database::revision_exists(revision_id const & id)
1624{
1625 results res;
1626 query q("SELECT id FROM revisions WHERE id = ?");
1627 fetch(res, one_col, any_rows, q % text(id.inner()()));
1628 I(res.size() <= 1);
1629 return res.size() == 1;
1630}
1631
1632void
1633database::get_file_ids(set<file_id> & ids)
1634{
1635 ids.clear();
1636 set< hexenc<id> > tmp;
1637 get_ids("files", tmp);
1638 get_ids("file_deltas", tmp);
1639 add_decoration_to_container(tmp, ids);
1640}
1641
1642void
1643database::get_revision_ids(set<revision_id> & ids)
1644{
1645 ids.clear();
1646 set< hexenc<id> > tmp;
1647 get_ids("revisions", tmp);
1648 add_decoration_to_container(tmp, ids);
1649}
1650
1651void
1652database::get_roster_ids(set<revision_id> & ids)
1653{
1654 ids.clear();
1655 set< hexenc<id> > tmp;
1656 get_ids("rosters", tmp);
1657 add_decoration_to_container(tmp, ids);
1658 get_ids("roster_deltas", tmp);
1659 add_decoration_to_container(tmp, ids);
1660}
1661
1662void
1663database::get_file_version(file_id const & id,
1664 file_data & dat)
1665{
1666 data tmp;
1667 get_version(id.inner(), tmp, "files", "file_deltas");
1668 dat = file_data(tmp);
1669}
1670
1671void
1672database::get_manifest_version(manifest_id const & id,
1673 manifest_data & dat)
1674{
1675 data tmp;
1676 get_version(id.inner(), tmp, "manifests", "manifest_deltas");
1677 dat = manifest_data(tmp);
1678}
1679
1680void
1681database::put_file(file_id const & id,
1682 file_data const & dat)
1683{
1684 schedule_delayed_file(id, dat);
1685}
1686
1687void
1688database::put_file_version(file_id const & old_id,
1689 file_id const & new_id,
1690 file_delta const & del)
1691{
1692 file_data old_data, new_data;
1693 file_delta reverse_delta;
1694
1695 get_file_version(old_id, old_data);
1696 {
1697 data tmp;
1698 patch(old_data.inner(), del.inner(), tmp);
1699 new_data = file_data(tmp);
1700 }
1701 {
1702 string tmp;
1703 invert_xdelta(old_data.inner()(), del.inner()(), tmp);
1704 reverse_delta = file_delta(tmp);
1705 data old_tmp;
1706 hexenc<id> old_tmp_id;
1707 patch(new_data.inner(), reverse_delta.inner(), old_tmp);
1708 calculate_ident(old_tmp, old_tmp_id);
1709 I(file_id(old_tmp_id) == old_id);
1710 }
1711
1712 transaction_guard guard(*this);
1713 if (file_or_manifest_base_exists(old_id.inner(), "files"))
1714 {
1715 // descendent of a head version replaces the head, therefore old head
1716 // must be disposed of
1717 if (have_delayed_file(old_id))
1718 cancel_delayed_file(old_id);
1719 else
1720 drop(old_id.inner()(), "files");
1721 }
1722 schedule_delayed_file(new_id, new_data);
1723 put_file_delta(old_id, new_id, reverse_delta);
1724 guard.commit();
1725}
1726
1727void
1728database::get_arbitrary_file_delta(file_id const & src_id,
1729 file_id const & dst_id,
1730 file_delta & del)
1731{
1732 delta dtmp;
1733 // Deltas stored in the database go from base -> id.
1734 results res;
1735 query q1("SELECT delta FROM file_deltas "
1736 "WHERE base = ? AND id = ?");
1737 fetch(res, one_col, any_rows,
1738 q1 % text(src_id.inner()()) % text(dst_id.inner()()));
1739
1740 if (!res.empty())
1741 {
1742 // Exact hit: a plain delta from src -> dst.
1743 gzip<delta> del_packed(res[0][0]);
1744 decode_gzip(del_packed, dtmp);
1745 del = file_delta(dtmp);
1746 return;
1747 }
1748
1749 query q2("SELECT delta FROM file_deltas "
1750 "WHERE base = ? AND id = ?");
1751 fetch(res, one_col, any_rows,
1752 q2 % text(dst_id.inner()()) % text(src_id.inner()()));
1753
1754 if (!res.empty())
1755 {
1756 // We have a delta from dst -> src; we need to
1757 // invert this to a delta from src -> dst.
1758 gzip<delta> del_packed(res[0][0]);
1759 decode_gzip(del_packed, dtmp);
1760 string fwd_delta;
1761 file_data dst;
1762 get_file_version(dst_id, dst);
1763 invert_xdelta(dst.inner()(), dtmp(), fwd_delta);
1764 del = file_delta(fwd_delta);
1765 return;
1766 }
1767
1768 // No deltas of use; just load both versions and diff.
1769 file_data fd1, fd2;
1770 get_file_version(src_id, fd1);
1771 get_file_version(dst_id, fd2);
1772 diff(fd1.inner(), fd2.inner(), dtmp);
1773 del = file_delta(dtmp);
1774}
1775
1776
1777void
1778database::get_revision_ancestry(multimap<revision_id, revision_id> & graph)
1779{
1780 results res;
1781 graph.clear();
1782 fetch(res, 2, any_rows,
1783 query("SELECT parent,child FROM revision_ancestry"));
1784 for (size_t i = 0; i < res.size(); ++i)
1785 graph.insert(make_pair(revision_id(res[i][0]),
1786 revision_id(res[i][1])));
1787}
1788
1789void
1790database::get_revision_parents(revision_id const & id,
1791 set<revision_id> & parents)
1792{
1793 I(!null_id(id));
1794 results res;
1795 parents.clear();
1796 fetch(res, one_col, any_rows,
1797 query("SELECT parent FROM revision_ancestry WHERE child = ?")
1798 % text(id.inner()()));
1799 for (size_t i = 0; i < res.size(); ++i)
1800 parents.insert(revision_id(res[i][0]));
1801}
1802
1803void
1804database::get_revision_children(revision_id const & id,
1805 set<revision_id> & children)
1806{
1807 results res;
1808 children.clear();
1809 fetch(res, one_col, any_rows,
1810 query("SELECT child FROM revision_ancestry WHERE parent = ?")
1811 % text(id.inner()()));
1812 for (size_t i = 0; i < res.size(); ++i)
1813 children.insert(revision_id(res[i][0]));
1814}
1815
1816void
1817database::get_revision_manifest(revision_id const & rid,
1818 manifest_id & mid)
1819{
1820 revision_t rev;
1821 get_revision(rid, rev);
1822 mid = rev.new_manifest;
1823}
1824
1825void
1826database::get_revision(revision_id const & id,
1827 revision_t & rev)
1828{
1829 revision_data d;
1830 get_revision(id, d);
1831 read_revision(d, rev);
1832}
1833
1834void
1835database::get_revision(revision_id const & id,
1836 revision_data & dat)
1837{
1838 I(!null_id(id));
1839 results res;
1840 fetch(res, one_col, one_row,
1841 query("SELECT data FROM revisions WHERE id = ?")
1842 % text(id.inner()()));
1843
1844 gzip<data> gzdata(res[0][0]);
1845 data rdat;
1846 decode_gzip(gzdata,rdat);
1847
1848 // verify that we got a revision with the right id
1849 {
1850 revision_id tmp;
1851 calculate_ident(revision_data(rdat), tmp);
1852 I(id == tmp);
1853 }
1854
1855 dat = revision_data(rdat);
1856}
1857
1858void
1859database::get_rev_height(revision_id const & id,
1860 rev_height & height)
1861{
1862 if (null_id(id))
1863 {
1864 height = rev_height::root_height();
1865 return;
1866 }
1867
1868 results res;
1869 fetch(res, one_col, one_row,
1870 query("SELECT height FROM heights WHERE revision = ?")
1871 % text(id.inner()()));
1872
1873 I(res.size() == 1);
1874
1875 height = rev_height(res[0][0]);
1876 I(height.valid());
1877}
1878
1879void
1880database::put_rev_height(revision_id const & id,
1881 rev_height const & height)
1882{
1883 I(!null_id(id));
1884 I(revision_exists(id));
1885 I(height.valid());
1886
1887 execute(query("INSERT INTO heights VALUES(?, ?)")
1888 % text(id.inner()())
1889 % blob(height()));
1890}
1891
1892bool
1893database::has_rev_height(rev_height const & height)
1894{
1895 results res;
1896 fetch(res, one_col, any_rows,
1897 query("SELECT height FROM heights WHERE height = ?")
1898 % blob(height()));
1899 I((res.size() == 1) || (res.size() == 0));
1900 return res.size() == 1;
1901}
1902
1903void
1904database::deltify_revision(revision_id const & rid)
1905{
1906 transaction_guard guard(*this);
1907 revision_t rev;
1908 MM(rev);
1909 MM(rid);
1910 get_revision(rid, rev);
1911 // Make sure that all parent revs have their files replaced with deltas
1912 // from this rev's files.
1913 {
1914 for (edge_map::const_iterator i = rev.edges.begin();
1915 i != rev.edges.end(); ++i)
1916 {
1917 for (map<split_path, pair<file_id, file_id> >::const_iterator
1918 j = edge_changes(i).deltas_applied.begin();
1919 j != edge_changes(i).deltas_applied.end(); ++j)
1920 {
1921 if (file_or_manifest_base_exists(delta_entry_src(j).inner(), "files") &&
1922 file_version_exists(delta_entry_dst(j)))
1923 {
1924 file_data old_data;
1925 file_data new_data;
1926 get_file_version(delta_entry_src(j), old_data);
1927 get_file_version(delta_entry_dst(j), new_data);
1928 delta delt;
1929 diff(old_data.inner(), new_data.inner(), delt);
1930 file_delta del(delt);
1931 drop(delta_entry_dst(j).inner()(), "files");
1932 drop(delta_entry_dst(j).inner()(), "file_deltas");
1933 put_file_version(delta_entry_src(j), delta_entry_dst(j), del);
1934 }
1935 }
1936 }
1937 }
1938 guard.commit();
1939}
1940
1941
1942void
1943database::put_revision(revision_id const & new_id,
1944 revision_t const & rev)
1945{
1946 MM(new_id);
1947 MM(rev);
1948
1949 I(!null_id(new_id));
1950 I(!revision_exists(new_id));
1951
1952 I(rev.made_for == made_for_database);
1953 rev.check_sane();
1954 revision_data d;
1955 MM(d.inner());
1956 write_revision(rev, d);
1957
1958 // Phase 1: confirm the revision makes sense, and we the required files
1959 // actually exist
1960 {
1961 revision_id tmp;
1962 MM(tmp);
1963 calculate_ident(d, tmp);
1964 I(tmp == new_id);
1965 for (edge_map::const_iterator e = rev.edges.begin(); e != rev.edges.end(); ++e)
1966 {
1967 cset const & cs = edge_changes(e);
1968 for (map<split_path, file_id>::const_iterator
1969 i = cs.files_added.begin(); i != cs.files_added.end(); ++i)
1970 I(file_version_exists(i->second));
1971 for (map<split_path, pair<file_id, file_id> >::const_iterator
1972 i = cs.deltas_applied.begin(); i != cs.deltas_applied.end(); ++i)
1973 I(file_version_exists(i->second.second));
1974 }
1975 }
1976
1977 transaction_guard guard(*this);
1978
1979 // Phase 2: Write the revision data (inside a transaction)
1980
1981 gzip<data> d_packed;
1982 encode_gzip(d.inner(), d_packed);
1983 execute(query("INSERT INTO revisions VALUES(?, ?)")
1984 % text(new_id.inner()())
1985 % blob(d_packed()));
1986
1987 for (edge_map::const_iterator e = rev.edges.begin();
1988 e != rev.edges.end(); ++e)
1989 {
1990 execute(query("INSERT INTO revision_ancestry VALUES(?, ?)")
1991 % text(edge_old_revision(e).inner()())
1992 % text(new_id.inner()()));
1993 }
1994
1995 // Phase 3: Construct and write the roster (which also checks the manifest
1996 // id as it goes)
1997
1998 put_roster_for_revision(new_id, rev);
1999
2000 // Phase 4: rewrite any files that need deltas added
2001
2002 deltify_revision(new_id);
2003
2004 // Phase 5: determine the revision height
2005
2006 put_height_for_revision(new_id, rev);
2007
2008 // Finally, commit.
2009
2010 guard.commit();
2011}
2012
2013void
2014database::put_height_for_revision(revision_id const & new_id,
2015 revision_t const & rev)
2016{
2017 I(!null_id(new_id));
2018
2019 rev_height highest_parent;
2020 // we always branch off the highest parent ...
2021 for (edge_map::const_iterator e = rev.edges.begin();
2022 e != rev.edges.end(); ++e)
2023 {
2024 rev_height parent; MM(parent);
2025 get_rev_height(edge_old_revision(e), parent);
2026 if (parent > highest_parent)
2027 {
2028 highest_parent = parent;
2029 }
2030 }
2031
2032 // ... then find the first unused child
2033 u32 childnr(0);
2034 rev_height candidate; MM(candidate);
2035 while(true)
2036 {
2037 candidate = highest_parent.child_height(childnr);
2038 if (!has_rev_height(candidate))
2039 {
2040 break;
2041 }
2042 I(childnr < std::numeric_limits<u32>::max());
2043 ++childnr;
2044 }
2045 put_rev_height(new_id, candidate);
2046}
2047
2048void
2049database::put_roster_for_revision(revision_id const & new_id,
2050 revision_t const & rev)
2051{
2052 // Construct, the roster, sanity-check the manifest id, and then write it
2053 // to the db
2054 shared_ptr<roster_t> ros_writeable(new roster_t); MM(*ros_writeable);
2055 shared_ptr<marking_map> mm_writeable(new marking_map); MM(*mm_writeable);
2056 manifest_id roster_manifest_id;
2057 MM(roster_manifest_id);
2058 make_roster_for_revision(rev, new_id, *ros_writeable, *mm_writeable, *__app);
2059 calculate_ident(*ros_writeable, roster_manifest_id);
2060 I(rev.new_manifest == roster_manifest_id);
2061 // const'ify the objects, suitable for caching etc.
2062 roster_t_cp ros = ros_writeable;
2063 marking_map_cp mm = mm_writeable;
2064 put_roster(new_id, ros, mm);
2065}
2066
2067void
2068database::put_revision(revision_id const & new_id,
2069 revision_data const & dat)
2070{
2071 revision_t rev;
2072 read_revision(dat, rev);
2073 put_revision(new_id, rev);
2074}
2075
2076
2077void
2078database::delete_existing_revs_and_certs()
2079{
2080 execute(query("DELETE FROM revisions"));
2081 execute(query("DELETE FROM revision_ancestry"));
2082 execute(query("DELETE FROM revision_certs"));
2083}
2084
2085void
2086database::delete_existing_manifests()
2087{
2088 execute(query("DELETE FROM manifests"));
2089 execute(query("DELETE FROM manifest_deltas"));
2090}
2091
2092void
2093database::delete_existing_rosters()
2094{
2095 execute(query("DELETE FROM rosters"));
2096 execute(query("DELETE FROM roster_deltas"));
2097 execute(query("DELETE FROM next_roster_node_number"));
2098}
2099
2100void
2101database::delete_existing_heights()
2102{
2103 execute(query("DELETE FROM heights"));
2104}
2105
2106/// Deletes one revision from the local database.
2107/// @see kill_rev_locally
2108void
2109database::delete_existing_rev_and_certs(revision_id const & rid)
2110{
2111 transaction_guard guard (*this);
2112
2113 // Check that the revision exists and doesn't have any children.
2114 I(revision_exists(rid));
2115 set<revision_id> children;
2116 get_revision_children(rid, children);
2117 I(children.empty());
2118
2119
2120 L(FL("Killing revision %s locally") % rid);
2121
2122 // Kill the certs, ancestry, and revision.
2123 execute(query("DELETE from revision_certs WHERE id = ?")
2124 % text(rid.inner()()));
2125 cert_stamper.note_change();
2126
2127 execute(query("DELETE from revision_ancestry WHERE child = ?")
2128 % text(rid.inner()()));
2129
2130 execute(query("DELETE from heights WHERE revision = ?")
2131 % text(rid.inner()()));
2132
2133 execute(query("DELETE from revisions WHERE id = ?")
2134 % text(rid.inner()()));
2135
2136 guard.commit();
2137}
2138
2139/// Deletes all certs referring to a particular branch.
2140void
2141database::delete_branch_named(cert_value const & branch)
2142{
2143 L(FL("Deleting all references to branch %s") % branch);
2144 execute(query("DELETE FROM revision_certs WHERE name='branch' AND value =?")
2145 % blob(branch()));
2146 cert_stamper.note_change();
2147 execute(query("DELETE FROM branch_epochs WHERE branch=?")
2148 % blob(branch()));
2149}
2150
2151/// Deletes all certs referring to a particular tag.
2152void
2153database::delete_tag_named(cert_value const & tag)
2154{
2155 L(FL("Deleting all references to tag %s") % tag);
2156 execute(query("DELETE FROM revision_certs WHERE name='tag' AND value =?")
2157 % blob(tag()));
2158 cert_stamper.note_change();
2159}
2160
2161// crypto key management
2162
2163void
2164database::get_key_ids(string const & pattern,
2165 vector<rsa_keypair_id> & pubkeys)
2166{
2167 pubkeys.clear();
2168 results res;
2169
2170 if (pattern != "")
2171 fetch(res, one_col, any_rows,
2172 query("SELECT id FROM public_keys WHERE id GLOB ?")
2173 % text(pattern));
2174 else
2175 fetch(res, one_col, any_rows,
2176 query("SELECT id FROM public_keys"));
2177
2178 for (size_t i = 0; i < res.size(); ++i)
2179 pubkeys.push_back(rsa_keypair_id(res[i][0]));
2180}
2181
2182void
2183database::get_keys(string const & table, vector<rsa_keypair_id> & keys)
2184{
2185 keys.clear();
2186 results res;
2187 fetch(res, one_col, any_rows, query("SELECT id FROM " + table));
2188 for (size_t i = 0; i < res.size(); ++i)
2189 keys.push_back(rsa_keypair_id(res[i][0]));
2190}
2191
2192void
2193database::get_public_keys(vector<rsa_keypair_id> & keys)
2194{
2195 get_keys("public_keys", keys);
2196}
2197
2198bool
2199database::public_key_exists(hexenc<id> const & hash)
2200{
2201 results res;
2202 fetch(res, one_col, any_rows,
2203 query("SELECT id FROM public_keys WHERE hash = ?")
2204 % text(hash()));
2205 I((res.size() == 1) || (res.size() == 0));
2206 if (res.size() == 1)
2207 return true;
2208 return false;
2209}
2210
2211bool
2212database::public_key_exists(rsa_keypair_id const & id)
2213{
2214 results res;
2215 fetch(res, one_col, any_rows,
2216 query("SELECT id FROM public_keys WHERE id = ?")
2217 % text(id()));
2218 I((res.size() == 1) || (res.size() == 0));
2219 if (res.size() == 1)
2220 return true;
2221 return false;
2222}
2223
2224void
2225database::get_pubkey(hexenc<id> const & hash,
2226 rsa_keypair_id & id,
2227 base64<rsa_pub_key> & pub_encoded)
2228{
2229 results res;
2230 fetch(res, 2, one_row,
2231 query("SELECT id, keydata FROM public_keys WHERE hash = ?")
2232 % text(hash()));
2233 id = rsa_keypair_id(res[0][0]);
2234 encode_base64(rsa_pub_key(res[0][1]), pub_encoded);
2235}
2236
2237void
2238database::get_key(rsa_keypair_id const & pub_id,
2239 base64<rsa_pub_key> & pub_encoded)
2240{
2241 results res;
2242 fetch(res, one_col, one_row,
2243 query("SELECT keydata FROM public_keys WHERE id = ?")
2244 % text(pub_id()));
2245 encode_base64(rsa_pub_key(res[0][0]), pub_encoded);
2246}
2247
2248void
2249database::put_key(rsa_keypair_id const & pub_id,
2250 base64<rsa_pub_key> const & pub_encoded)
2251{
2252 hexenc<id> thash;
2253 key_hash_code(pub_id, pub_encoded, thash);
2254 I(!public_key_exists(thash));
2255 E(!public_key_exists(pub_id),
2256 F("another key with name '%s' already exists") % pub_id);
2257 rsa_pub_key pub_key;
2258 decode_base64(pub_encoded, pub_key);
2259 execute(query("INSERT INTO public_keys VALUES(?, ?, ?)")
2260 % text(thash())
2261 % text(pub_id())
2262 % blob(pub_key()));
2263}
2264
2265void
2266database::delete_public_key(rsa_keypair_id const & pub_id)
2267{
2268 execute(query("DELETE FROM public_keys WHERE id = ?")
2269 % text(pub_id()));
2270}
2271
2272// cert management
2273
2274bool
2275database::cert_exists(cert const & t,
2276 string const & table)
2277{
2278 results res;
2279 cert_value value;
2280 decode_base64(t.value, value);
2281 rsa_sha1_signature sig;
2282 decode_base64(t.sig, sig);
2283 query q = query("SELECT id FROM " + table + " WHERE id = ? "
2284 "AND name = ? "
2285 "AND value = ? "
2286 "AND keypair = ? "
2287 "AND signature = ?")
2288 % text(t.ident())
2289 % text(t.name())
2290 % blob(value())
2291 % text(t.key())
2292 % blob(sig());
2293
2294 fetch(res, 1, any_rows, q);
2295
2296 I(res.size() == 0 || res.size() == 1);
2297 return res.size() == 1;
2298}
2299
2300void
2301database::put_cert(cert const & t,
2302 string const & table)
2303{
2304 hexenc<id> thash;
2305 cert_hash_code(t, thash);
2306 cert_value value;
2307 decode_base64(t.value, value);
2308 rsa_sha1_signature sig;
2309 decode_base64(t.sig, sig);
2310
2311 string insert = "INSERT INTO " + table + " VALUES(?, ?, ?, ?, ?, ?)";
2312
2313 execute(query(insert)
2314 % text(thash())
2315 % text(t.ident())
2316 % text(t.name())
2317 % blob(value())
2318 % text(t.key())
2319 % blob(sig()));
2320}
2321
2322void
2323database::results_to_certs(results const & res,
2324 vector<cert> & certs)
2325{
2326 certs.clear();
2327 for (size_t i = 0; i < res.size(); ++i)
2328 {
2329 cert t;
2330 base64<cert_value> value;
2331 encode_base64(cert_value(res[i][2]), value);
2332 base64<rsa_sha1_signature> sig;
2333 encode_base64(rsa_sha1_signature(res[i][4]), sig);
2334 t = cert(hexenc<id>(res[i][0]),
2335 cert_name(res[i][1]),
2336 value,
2337 rsa_keypair_id(res[i][3]),
2338 sig);
2339 certs.push_back(t);
2340 }
2341}
2342
2343void
2344database::install_functions(app_state * app)
2345{
2346 // register any functions we're going to use
2347 I(sqlite3_create_function(sql(), "gunzip", -1,
2348 SQLITE_UTF8, NULL,
2349 &sqlite3_gunzip_fn,
2350 NULL, NULL) == 0);
2351}
2352
2353void
2354database::get_certs(vector<cert> & certs,
2355 string const & table)
2356{
2357 results res;
2358 query q("SELECT id, name, value, keypair, signature FROM " + table);
2359 fetch(res, 5, any_rows, q);
2360 results_to_certs(res, certs);
2361}
2362
2363
2364void
2365database::get_certs(hexenc<id> const & ident,
2366 vector<cert> & certs,
2367 string const & table)
2368{
2369 results res;
2370 query q("SELECT id, name, value, keypair, signature FROM " + table +
2371 " WHERE id = ?");
2372
2373 fetch(res, 5, any_rows, q % text(ident()));
2374 results_to_certs(res, certs);
2375}
2376
2377
2378void
2379database::get_certs(cert_name const & name,
2380 vector<cert> & certs,
2381 string const & table)
2382{
2383 results res;
2384 query q("SELECT id, name, value, keypair, signature FROM " + table +
2385 " WHERE name = ?");
2386 fetch(res, 5, any_rows, q % text(name()));
2387 results_to_certs(res, certs);
2388}
2389
2390
2391void
2392database::get_certs(hexenc<id> const & ident,
2393 cert_name const & name,
2394 vector<cert> & certs,
2395 string const & table)
2396{
2397 results res;
2398 query q("SELECT id, name, value, keypair, signature FROM " + table +
2399 " WHERE id = ? AND name = ?");
2400
2401 fetch(res, 5, any_rows,
2402 q % text(ident())
2403 % text(name()));
2404 results_to_certs(res, certs);
2405}
2406
2407void
2408database::get_certs(cert_name const & name,
2409 base64<cert_value> const & val,
2410 vector<cert> & certs,
2411 string const & table)
2412{
2413 results res;
2414 query q("SELECT id, name, value, keypair, signature FROM " + table +
2415 " WHERE name = ? AND value = ?");
2416
2417 cert_value binvalue;
2418 decode_base64(val, binvalue);
2419 fetch(res, 5, any_rows,
2420 q % text(name())
2421 % blob(binvalue()));
2422 results_to_certs(res, certs);
2423}
2424
2425
2426void
2427database::get_certs(hexenc<id> const & ident,
2428 cert_name const & name,
2429 base64<cert_value> const & value,
2430 vector<cert> & certs,
2431 string const & table)
2432{
2433 results res;
2434 query q("SELECT id, name, value, keypair, signature FROM " + table +
2435 " WHERE id = ? AND name = ? AND value = ?");
2436
2437 cert_value binvalue;
2438 decode_base64(value, binvalue);
2439 fetch(res, 5, any_rows,
2440 q % text(ident())
2441 % text(name())
2442 % blob(binvalue()));
2443 results_to_certs(res, certs);
2444}
2445
2446
2447
2448bool
2449database::revision_cert_exists(revision<cert> const & cert)
2450{
2451 return cert_exists(cert.inner(), "revision_certs");
2452}
2453
2454void
2455database::put_revision_cert(revision<cert> const & cert)
2456{
2457 put_cert(cert.inner(), "revision_certs");
2458 cert_stamper.note_change();
2459}
2460
2461outdated_indicator
2462database::get_revision_cert_nobranch_index(vector< pair<hexenc<id>,
2463 pair<revision_id, rsa_keypair_id> > > & idx)
2464{
2465 results res;
2466 fetch(res, 3, any_rows,
2467 query("SELECT hash, id, keypair "
2468 "FROM 'revision_certs' WHERE name != 'branch'"));
2469
2470 idx.clear();
2471 idx.reserve(res.size());
2472 for (results::const_iterator i = res.begin(); i != res.end(); ++i)
2473 {
2474 idx.push_back(make_pair(hexenc<id>((*i)[0]),
2475 make_pair(revision_id((*i)[1]),
2476 rsa_keypair_id((*i)[2]))));
2477 }
2478 return cert_stamper.get_indicator();
2479}
2480
2481outdated_indicator
2482database::get_revision_certs(vector< revision<cert> > & ts)
2483{
2484 vector<cert> certs;
2485 get_certs(certs, "revision_certs");
2486 ts.clear();
2487 add_decoration_to_container(certs, ts);
2488 return cert_stamper.get_indicator();
2489}
2490
2491outdated_indicator
2492database::get_revision_certs(cert_name const & name,
2493 vector< revision<cert> > & ts)
2494{
2495 vector<cert> certs;
2496 get_certs(name, certs, "revision_certs");
2497 ts.clear();
2498 add_decoration_to_container(certs, ts);
2499 return cert_stamper.get_indicator();
2500}
2501
2502outdated_indicator
2503database::get_revision_certs(revision_id const & id,
2504 cert_name const & name,
2505 vector< revision<cert> > & ts)
2506{
2507 vector<cert> certs;
2508 get_certs(id.inner(), name, certs, "revision_certs");
2509 ts.clear();
2510 add_decoration_to_container(certs, ts);
2511 return cert_stamper.get_indicator();
2512}
2513
2514outdated_indicator
2515database::get_revision_certs(revision_id const & id,
2516 cert_name const & name,
2517 base64<cert_value> const & val,
2518 vector< revision<cert> > & ts)
2519{
2520 vector<cert> certs;
2521 get_certs(id.inner(), name, val, certs, "revision_certs");
2522 ts.clear();
2523 add_decoration_to_container(certs, ts);
2524 return cert_stamper.get_indicator();
2525}
2526
2527outdated_indicator
2528database::get_revisions_with_cert(cert_name const & name,
2529 base64<cert_value> const & val,
2530 set<revision_id> & revisions)
2531{
2532 revisions.clear();
2533 results res;
2534 query q("SELECT id FROM revision_certs WHERE name = ? AND value = ?");
2535 cert_value binvalue;
2536 decode_base64(val, binvalue);
2537 fetch(res, one_col, any_rows, q % text(name()) % blob(binvalue()));
2538 for (results::const_iterator i = res.begin(); i != res.end(); ++i)
2539 revisions.insert(revision_id((*i)[0]));
2540 return cert_stamper.get_indicator();
2541}
2542
2543outdated_indicator
2544database::get_revision_certs(cert_name const & name,
2545 base64<cert_value> const & val,
2546 vector< revision<cert> > & ts)
2547{
2548 vector<cert> certs;
2549 get_certs(name, val, certs, "revision_certs");
2550 ts.clear();
2551 add_decoration_to_container(certs, ts);
2552 return cert_stamper.get_indicator();
2553}
2554
2555outdated_indicator
2556database::get_revision_certs(revision_id const & id,
2557 vector< revision<cert> > & ts)
2558{
2559 vector<cert> certs;
2560 get_certs(id.inner(), certs, "revision_certs");
2561 ts.clear();
2562 add_decoration_to_container(certs, ts);
2563 return cert_stamper.get_indicator();
2564}
2565
2566outdated_indicator
2567database::get_revision_certs(revision_id const & ident,
2568 vector< hexenc<id> > & ts)
2569{
2570 results res;
2571 vector<cert> certs;
2572 fetch(res, one_col, any_rows,
2573 query("SELECT hash "
2574 "FROM revision_certs "
2575 "WHERE id = ?")
2576 % text(ident.inner()()));
2577 ts.clear();
2578 for (size_t i = 0; i < res.size(); ++i)
2579 ts.push_back(hexenc<id>(res[i][0]));
2580 return cert_stamper.get_indicator();
2581}
2582
2583void
2584database::get_revision_cert(hexenc<id> const & hash,
2585 revision<cert> & c)
2586{
2587 results res;
2588 vector<cert> certs;
2589 fetch(res, 5, one_row,
2590 query("SELECT id, name, value, keypair, signature "
2591 "FROM revision_certs "
2592 "WHERE hash = ?")
2593 % text(hash()));
2594 results_to_certs(res, certs);
2595 I(certs.size() == 1);
2596 c = revision<cert>(certs[0]);
2597}
2598
2599bool
2600database::revision_cert_exists(hexenc<id> const & hash)
2601{
2602 results res;
2603 vector<cert> certs;
2604 fetch(res, one_col, any_rows,
2605 query("SELECT id "
2606 "FROM revision_certs "
2607 "WHERE hash = ?")
2608 % text(hash()));
2609 I(res.size() == 0 || res.size() == 1);
2610 return (res.size() == 1);
2611}
2612
2613void
2614database::get_manifest_certs(manifest_id const & id,
2615 vector< manifest<cert> > & ts)
2616{
2617 vector<cert> certs;
2618 get_certs(id.inner(), certs, "manifest_certs");
2619 ts.clear();
2620 add_decoration_to_container(certs, ts);
2621}
2622
2623
2624void
2625database::get_manifest_certs(cert_name const & name,
2626 vector< manifest<cert> > & ts)
2627{
2628 vector<cert> certs;
2629 get_certs(name, certs, "manifest_certs");
2630 ts.clear();
2631 add_decoration_to_container(certs, ts);
2632}
2633
2634
2635// completions
2636void
2637database::complete(string const & partial,
2638 set<revision_id> & completions)
2639{
2640 results res;
2641 completions.clear();
2642
2643 string pattern = partial + "*";
2644
2645 fetch(res, 1, any_rows,
2646 query("SELECT id FROM revisions WHERE id GLOB ?")
2647 % text(pattern));
2648
2649 for (size_t i = 0; i < res.size(); ++i)
2650 completions.insert(revision_id(res[i][0]));
2651}
2652
2653
2654void
2655database::complete(string const & partial,
2656 set<file_id> & completions)
2657{
2658 results res;
2659 completions.clear();
2660
2661 string pattern = partial + "*";
2662
2663 fetch(res, 1, any_rows,
2664 query("SELECT id FROM files WHERE id GLOB ?")
2665 % text(pattern));
2666
2667 for (size_t i = 0; i < res.size(); ++i)
2668 completions.insert(file_id(res[i][0]));
2669
2670 res.clear();
2671
2672 fetch(res, 1, any_rows,
2673 query("SELECT id FROM file_deltas WHERE id GLOB ?")
2674 % text(pattern));
2675
2676 for (size_t i = 0; i < res.size(); ++i)
2677 completions.insert(file_id(res[i][0]));
2678}
2679
2680void
2681database::complete(string const & partial,
2682 set< pair<key_id, utf8 > > & completions)
2683{
2684 results res;
2685 completions.clear();
2686
2687 string pattern = partial + "*";
2688
2689 fetch(res, 2, any_rows,
2690 query("SELECT hash, id FROM public_keys WHERE hash GLOB ?")
2691 % text(pattern));
2692
2693 for (size_t i = 0; i < res.size(); ++i)
2694 completions.insert(make_pair(key_id(res[i][0]), utf8(res[i][1])));
2695}
2696
2697using selectors::selector_type;
2698
2699static void selector_to_certname(selector_type ty,
2700 cert_name & name,
2701 string & prefix,
2702 string & suffix)
2703{
2704 prefix = suffix = "*";
2705 switch (ty)
2706 {
2707 case selectors::sel_author:
2708 prefix = suffix = "";
2709 name = author_cert_name;
2710 break;
2711 case selectors::sel_branch:
2712 prefix = suffix = "";
2713 name = branch_cert_name;
2714 break;
2715 case selectors::sel_head:
2716 prefix = suffix = "";
2717 name = branch_cert_name;
2718 break;
2719 case selectors::sel_date:
2720 case selectors::sel_later:
2721 case selectors::sel_earlier:
2722 name = date_cert_name;
2723 break;
2724 case selectors::sel_tag:
2725 prefix = suffix = "";
2726 name = tag_cert_name;
2727 break;
2728 case selectors::sel_ident:
2729 case selectors::sel_cert:
2730 case selectors::sel_unknown:
2731 I(false); // don't do this.
2732 break;
2733 }
2734}
2735
2736void database::complete(selector_type ty,
2737 string const & partial,
2738 vector<pair<selector_type, string> > const & limit,
2739 set<string> & completions)
2740{
2741 //L(FL("database::complete for partial '%s'") % partial);
2742 completions.clear();
2743
2744 // step 1: the limit is transformed into an SQL select statement which
2745 // selects a set of IDs from the revision_certs table which match the
2746 // limit. this is done by building an SQL select statement for each term
2747 // in the limit and then INTERSECTing them all.
2748
2749 query lim;
2750 lim.sql_cmd = "(";
2751 if (limit.empty())
2752 {
2753 lim.sql_cmd += "SELECT id FROM revision_certs";
2754 }
2755 else
2756 {
2757 bool first_limit = true;
2758 for (vector<pair<selector_type, string> >::const_iterator i = limit.begin();
2759 i != limit.end(); ++i)
2760 {
2761 if (first_limit)
2762 first_limit = false;
2763 else
2764 lim.sql_cmd += " INTERSECT ";
2765
2766 if (i->first == selectors::sel_ident)
2767 {
2768 lim.sql_cmd += "SELECT id FROM revision_certs WHERE id GLOB ?";
2769 lim % text(i->second + "*");
2770 }
2771 else if (i->first == selectors::sel_cert)
2772 {
2773 if (i->second.length() > 0)
2774 {
2775 size_t spot = i->second.find("=");
2776
2777 if (spot != (size_t)-1)
2778 {
2779 string certname;
2780 string certvalue;
2781
2782 certname = i->second.substr(0, spot);
2783 spot++;
2784 certvalue = i->second.substr(spot);
2785 lim.sql_cmd += "SELECT id FROM revision_certs WHERE name=? AND CAST(value AS TEXT) glob ?";
2786 lim % text(certname) % text(certvalue);
2787 }
2788 else
2789 {
2790 lim.sql_cmd += "SELECT id FROM revision_certs WHERE name=?";
2791 lim % text(i->second);
2792 }
2793
2794 }
2795 }
2796 else if (i->first == selectors::sel_unknown)
2797 {
2798 lim.sql_cmd += "SELECT id FROM revision_certs WHERE (name=? OR name=? OR name=?)";
2799 lim % text(author_cert_name()) % text(tag_cert_name()) % text(branch_cert_name());
2800 lim.sql_cmd += " AND CAST(value AS TEXT) glob ?";
2801 lim % text(i->second + "*");
2802 }
2803 else if (i->first == selectors::sel_head)
2804 {
2805 // get branch names
2806 set<branch_name> branch_names;
2807 if (i->second.size() == 0)
2808 {
2809 __app->require_workspace("the empty head selector h: refers to the head of the current branch");
2810 branch_names.insert(__app->opts.branchname);
2811 }
2812 else
2813 {
2814 __app->get_project().get_branch_list(globish(i->second), branch_names);
2815 }
2816
2817 // for each branch name, get the branch heads
2818 set<revision_id> heads;
2819 for (set<branch_name>::const_iterator bn = branch_names.begin();
2820 bn != branch_names.end(); bn++)
2821 {
2822 set<revision_id> branch_heads;
2823 __app->get_project().get_branch_heads(*bn, branch_heads);
2824 heads.insert(branch_heads.begin(), branch_heads.end());
2825 L(FL("after get_branch_heads for %s, heads has %d entries") % (*bn) % heads.size());
2826 }
2827
2828 lim.sql_cmd += "SELECT id FROM revision_certs WHERE id IN (";
2829 if (heads.size())
2830 {
2831 set<revision_id>::const_iterator r = heads.begin();
2832 lim.sql_cmd += "?";
2833 lim % text(r->inner()());
2834 r++;
2835 while (r != heads.end())
2836 {
2837 lim.sql_cmd += ", ?";
2838 lim % text(r->inner()());
2839 r++;
2840 }
2841 }
2842 lim.sql_cmd += ") ";
2843 }
2844 else
2845 {
2846 cert_name certname;
2847 string prefix;
2848 string suffix;
2849 selector_to_certname(i->first, certname, prefix, suffix);
2850 L(FL("processing selector type %d with i->second '%s'") % ty % i->second);
2851 if ((i->first == selectors::sel_branch) && (i->second.size() == 0))
2852 {
2853 __app->require_workspace("the empty branch selector b: refers to the current branch");
2854 lim.sql_cmd += "SELECT id FROM revision_certs WHERE name=? AND CAST(value AS TEXT) glob ?";
2855 lim % text(branch_cert_name()) % text(__app->opts.branchname());
2856 L(FL("limiting to current branch '%s'") % __app->opts.branchname);
2857 }
2858 else
2859 {
2860 lim.sql_cmd += "SELECT id FROM revision_certs WHERE name=? AND ";
2861 lim % text(certname());
2862 switch (i->first)
2863 {
2864 case selectors::sel_earlier:
2865 lim.sql_cmd += "value <= ?";
2866 lim % blob(i->second);
2867 break;
2868 case selectors::sel_later:
2869 lim.sql_cmd += "value > ?";
2870 lim % blob(i->second);
2871 break;
2872 default:
2873 lim.sql_cmd += "CAST(value AS TEXT) glob ?";
2874 lim % text(prefix + i->second + suffix);
2875 break;
2876 }
2877 }
2878 }
2879 //L(FL("found selector type %d, selecting_head is now %d") % i->first % selecting_head);
2880 }
2881 }
2882 lim.sql_cmd += ")";
2883
2884 // step 2: depending on what we've been asked to disambiguate, we
2885 // will complete either some idents, or cert values, or "unknown"
2886 // which generally means "author, tag or branch"
2887
2888 if (ty == selectors::sel_ident)
2889 {
2890 lim.sql_cmd = "SELECT id FROM " + lim.sql_cmd;
2891 }
2892 else
2893 {
2894 string prefix = "*";
2895 string suffix = "*";
2896 lim.sql_cmd = "SELECT value FROM revision_certs WHERE";
2897 if (ty == selectors::sel_unknown)
2898 {
2899 lim.sql_cmd += " (name=? OR name=? OR name=?)";
2900 lim % text(author_cert_name()) % text(tag_cert_name()) % text(branch_cert_name());
2901 }
2902 else
2903 {
2904 cert_name certname;
2905 selector_to_certname(ty, certname, prefix, suffix);
2906 lim.sql_cmd += " (name=?)";
2907 lim % text(certname());
2908 }
2909
2910 lim.sql_cmd += " AND (CAST(value AS TEXT) GLOB ?) AND (id IN " + lim.sql_cmd + ")";
2911 lim % text(prefix + partial + suffix);
2912 }
2913
2914 results res;
2915 fetch(res, one_col, any_rows, lim);
2916 for (size_t i = 0; i < res.size(); ++i)
2917 {
2918 if (ty == selectors::sel_ident)
2919 completions.insert(res[i][0]);
2920 else
2921 {
2922 data row_decoded(res[i][0]);
2923 completions.insert(row_decoded());
2924 }
2925 }
2926}
2927
2928// epochs
2929
2930void
2931database::get_epochs(map<branch_name, epoch_data> & epochs)
2932{
2933 epochs.clear();
2934 results res;
2935 fetch(res, 2, any_rows, query("SELECT branch, epoch FROM branch_epochs"));
2936 for (results::const_iterator i = res.begin(); i != res.end(); ++i)
2937 {
2938 branch_name decoded(idx(*i, 0));
2939 I(epochs.find(decoded) == epochs.end());
2940 epochs.insert(make_pair(decoded, epoch_data(idx(*i, 1))));
2941 }
2942}
2943
2944void
2945database::get_epoch(epoch_id const & eid,
2946 branch_name & branch, epoch_data & epo)
2947{
2948 I(epoch_exists(eid));
2949 results res;
2950 fetch(res, 2, any_rows,
2951 query("SELECT branch, epoch FROM branch_epochs"
2952 " WHERE hash = ?")
2953 % text(eid.inner()()));
2954 I(res.size() == 1);
2955 branch = branch_name(idx(idx(res, 0), 0));
2956 epo = epoch_data(idx(idx(res, 0), 1));
2957}
2958
2959bool
2960database::epoch_exists(epoch_id const & eid)
2961{
2962 results res;
2963 fetch(res, one_col, any_rows,
2964 query("SELECT hash FROM branch_epochs WHERE hash = ?")
2965 % text(eid.inner()()));
2966 I(res.size() == 1 || res.size() == 0);
2967 return res.size() == 1;
2968}
2969
2970void
2971database::set_epoch(branch_name const & branch, epoch_data const & epo)
2972{
2973 epoch_id eid;
2974 epoch_hash_code(branch, epo, eid);
2975 I(epo.inner()().size() == constants::epochlen);
2976 execute(query("INSERT OR REPLACE INTO branch_epochs VALUES(?, ?, ?)")
2977 % text(eid.inner()())
2978 % blob(branch())
2979 % text(epo.inner()()));
2980}
2981
2982void
2983database::clear_epoch(branch_name const & branch)
2984{
2985 execute(query("DELETE FROM branch_epochs WHERE branch = ?")
2986 % blob(branch()));
2987}
2988
2989bool
2990database::check_integrity()
2991{
2992 results res;
2993 fetch(res, one_col, any_rows, query("PRAGMA integrity_check"));
2994 I(res.size() == 1);
2995 I(res[0].size() == 1);
2996
2997 return res[0][0] == "ok";
2998}
2999
3000// vars
3001
3002void
3003database::get_vars(map<var_key, var_value> & vars)
3004{
3005 vars.clear();
3006 results res;
3007 fetch(res, 3, any_rows, query("SELECT domain, name, value FROM db_vars"));
3008 for (results::const_iterator i = res.begin(); i != res.end(); ++i)
3009 {
3010 var_domain domain(idx(*i, 0));
3011 var_name name(idx(*i, 1));
3012 var_value value(idx(*i, 2));
3013 I(vars.find(make_pair(domain, name)) == vars.end());
3014 vars.insert(make_pair(make_pair(domain, name), value));
3015 }
3016}
3017
3018void
3019database::get_var(var_key const & key, var_value & value)
3020{
3021 // FIXME: sillyly inefficient. Doesn't really matter, though.
3022 map<var_key, var_value> vars;
3023 get_vars(vars);
3024 map<var_key, var_value>::const_iterator i = vars.find(key);
3025 I(i != vars.end());
3026 value = i->second;
3027}
3028
3029bool
3030database::var_exists(var_key const & key)
3031{
3032 // FIXME: sillyly inefficient. Doesn't really matter, though.
3033 map<var_key, var_value> vars;
3034 get_vars(vars);
3035 map<var_key, var_value>::const_iterator i = vars.find(key);
3036 return i != vars.end();
3037}
3038
3039void
3040database::set_var(var_key const & key, var_value const & value)
3041{
3042 execute(query("INSERT OR REPLACE INTO db_vars VALUES(?, ?, ?)")
3043 % text(key.first())
3044 % blob(key.second())
3045 % blob(value()));
3046}
3047
3048void
3049database::clear_var(var_key const & key)
3050{
3051 execute(query("DELETE FROM db_vars WHERE domain = ? AND name = ?")
3052 % text(key.first())
3053 % blob(key.second()));
3054}
3055
3056// branches
3057
3058outdated_indicator
3059database::get_branches(vector<string> & names)
3060{
3061 results res;
3062 query q("SELECT DISTINCT value FROM revision_certs WHERE name = ?");
3063 string cert_name = "branch";
3064 fetch(res, one_col, any_rows, q % text(cert_name));
3065 for (size_t i = 0; i < res.size(); ++i)
3066 {
3067 names.push_back(res[i][0]);
3068 }
3069 return cert_stamper.get_indicator();
3070}
3071
3072outdated_indicator
3073database::get_branches(string const & glob,
3074 vector<string> & names)
3075{
3076 results res;
3077 query q("SELECT DISTINCT value FROM revision_certs WHERE name = ? AND CAST(value AS TEXT) glob ?");
3078 string cert_name = "branch";
3079 fetch(res, one_col, any_rows, q % text(cert_name) % text(glob));
3080 for (size_t i = 0; i < res.size(); ++i)
3081 {
3082 names.push_back(res[i][0]);
3083 }
3084 return cert_stamper.get_indicator();
3085}
3086
3087void
3088database::get_roster(revision_id const & rev_id,
3089 roster_t & roster)
3090{
3091 marking_map mm;
3092 get_roster(rev_id, roster, mm);
3093}
3094
3095void
3096database::get_roster(revision_id const & rev_id,
3097 roster_t & roster,
3098 marking_map & marking)
3099{
3100 if (rev_id.inner()().empty())
3101 {
3102 roster = roster_t();
3103 marking = marking_map();
3104 return;
3105 }
3106
3107 cached_roster cr;
3108 get_roster(rev_id, cr);
3109 roster = *cr.first;
3110 marking = *cr.second;
3111}
3112
3113void
3114database::get_roster(revision_id const & rev_id,
3115 cached_roster & cr)
3116{
3117 get_roster_version(rev_id, cr);
3118 I(cr.first);
3119 I(cr.second);
3120}
3121
3122void
3123database::put_roster(revision_id const & rev_id,
3124 roster_t_cp const & roster,
3125 marking_map_cp const & marking)
3126{
3127 I(roster);
3128 I(marking);
3129 MM(rev_id);
3130
3131 transaction_guard guard(*this);
3132
3133 // Our task is to add this roster, and deltify all the incoming edges (if
3134 // they aren't already).
3135
3136 roster_cache.insert_dirty(rev_id, make_pair(roster, marking));
3137
3138 set<revision_id> parents;
3139 get_revision_parents(rev_id, parents);
3140
3141 // Now do what deltify would do if we bothered
3142 for (set<revision_id>::const_iterator i = parents.begin();
3143 i != parents.end(); ++i)
3144 {
3145 if (null_id(*i))
3146 continue;
3147 revision_id old_rev = *i;
3148 if (roster_base_stored(old_rev))
3149 {
3150 cached_roster cr;
3151 get_roster_version(old_rev, cr);
3152 roster_delta reverse_delta;
3153 delta_rosters(*roster, *marking, *(cr.first), *(cr.second), reverse_delta);
3154 if (roster_cache.exists(old_rev))
3155 roster_cache.mark_clean(old_rev);
3156 drop(old_rev.inner()(), "rosters");
3157 put_roster_delta(old_rev, rev_id, reverse_delta);
3158 }
3159 }
3160 guard.commit();
3161}
3162
3163// helper for get_uncommon_ancestors
3164void
3165database::do_step_ancestor(set<height_rev_pair> & this_frontier,
3166 set<revision_id> & this_seen,
3167 set<revision_id> const & other_seen,
3168 set<revision_id> & this_uncommon_ancs)
3169{
3170 const height_rev_pair h_rev = *this_frontier.rbegin();
3171 const revision_id & rid(h_rev.second);
3172
3173 this_frontier.erase(h_rev);
3174
3175 if (other_seen.find(rid) == other_seen.end())
3176 {
3177 this_uncommon_ancs.insert(rid);
3178 }
3179
3180 // extend the frontier with parents
3181 results res;
3182 fetch(res, 2, any_rows,
3183 query("SELECT parent, height FROM revision_ancestry r, heights h"
3184 " WHERE child = ? AND r.parent = h.revision")
3185 % text(rid.inner()()));
3186
3187 for (size_t i = 0; i < res.size(); ++i)
3188 {
3189 revision_id par_rid(res[i][0]);
3190 if (this_seen.find(par_rid) == this_seen.end())
3191 {
3192 this_frontier.insert(make_pair(rev_height(res[i][1]), par_rid));
3193 this_seen.insert(par_rid);
3194 }
3195 }
3196}
3197
3198void
3199database::get_uncommon_ancestors(revision_id const & a,
3200 revision_id const & b,
3201 set<revision_id> & a_uncommon_ancs,
3202 set<revision_id> & b_uncommon_ancs)
3203{
3204 a_uncommon_ancs.clear();
3205 b_uncommon_ancs.clear();
3206
3207 // We extend a frontier from each revision until it reaches
3208 // a revision that has been seen by the other frontier. By
3209 // traversing in ascending height order we can ensure that
3210 // any common ancestor will have been 'seen' by both sides
3211 // before it is traversed.
3212
3213 set<height_rev_pair> a_frontier, b_frontier;
3214 rev_height height;
3215 get_rev_height(a, height);
3216 a_frontier.insert(make_pair(height, a));
3217 get_rev_height(b, height);
3218 b_frontier.insert(make_pair(height, b));
3219
3220 set<revision_id> a_seen, b_seen;
3221 a_seen.insert(a);
3222 b_seen.insert(b);
3223
3224 while (!a_frontier.empty() || !b_frontier.empty())
3225 {
3226 // We take the leaf-most (ie highest) height entry from either
3227 // a_frontier or b_frontier.
3228 // If one of them is empty, we take entries from the other.
3229 bool step_a;
3230 if (a_frontier.empty())
3231 {
3232 step_a = false;
3233 }
3234 else
3235 {
3236 if (!b_frontier.empty())
3237 {
3238 if (a_frontier == b_frontier)
3239 {
3240 // if both frontiers are the same, then we can safely say that
3241 // we've found all uncommon ancestors. This stopping condition
3242 // can result in traversing more nodes than required, but is simple.
3243 break;
3244 }
3245 step_a = (*a_frontier.rbegin() > *b_frontier.rbegin());
3246 }
3247 else
3248 {
3249 // b is empty
3250 step_a = true;
3251 }
3252 }
3253
3254 if (step_a)
3255 {
3256 do_step_ancestor(a_frontier, a_seen, b_seen, a_uncommon_ancs);
3257 }
3258 else
3259 {
3260 do_step_ancestor(b_frontier, b_seen, a_seen, b_uncommon_ancs);
3261 }
3262 }
3263}
3264
3265
3266u64
3267database::next_id_from_table(string const & table)
3268{
3269 transaction_guard guard(*this);
3270 results res;
3271
3272 // We implement this as a fixed db var.
3273
3274 fetch(res, one_col, any_rows,
3275 query(string("SELECT node FROM ") + table));
3276
3277 u64 n;
3278 if (res.empty())
3279 {
3280 n = 1;
3281 execute (query(string("INSERT INTO ") + table + " VALUES(?)")
3282 % text(lexical_cast<string>(n)));
3283 }
3284 else
3285 {
3286 I(res.size() == 1);
3287 n = lexical_cast<u64>(res[0][0]);
3288 ++n;
3289 execute(query(string("UPDATE ") + table + " SET node = ?")
3290 % text(lexical_cast<string>(n)));
3291
3292 }
3293 guard.commit();
3294 return n;
3295}
3296
3297node_id
3298database::next_node_id()
3299{
3300 return static_cast<node_id>(next_id_from_table("next_roster_node_number"));
3301}
3302
3303void
3304database::check_filename()
3305{
3306 N(!filename.empty(), F("no database specified"));
3307}
3308
3309
3310void
3311database::check_db_exists()
3312{
3313 switch (get_path_status(filename))
3314 {
3315 case path::nonexistent:
3316 N(false, F("database %s does not exist") % filename);
3317 break;
3318 case path::file:
3319 return;
3320 case path::directory:
3321 {
3322 system_path database_option;
3323 branch_name branch_option;
3324 rsa_keypair_id key_option;
3325 system_path keydir_option;
3326 if (workspace::get_ws_options_from_path(
3327 filename,
3328 database_option,
3329 branch_option,
3330 key_option,
3331 keydir_option))
3332 {
3333 N(database_option.empty(),
3334 F("You gave a database option of: \n"
3335 "%s\n"
3336 "That is actually a workspace. Did you mean: \n"
3337 "%s") % filename % database_option );
3338 }
3339 N(false, F("%s is a directory, not a database") % filename);
3340 }
3341 break;
3342 }
3343}
3344
3345void
3346database::check_db_nonexistent()
3347{
3348 require_path_is_nonexistent(filename,
3349 F("database %s already exists")
3350 % filename);
3351
3352 system_path journal(filename.as_internal() + "-journal");
3353 require_path_is_nonexistent(journal,
3354 F("existing (possibly stale) journal file '%s' "
3355 "has same stem as new database '%s'\n"
3356 "cancelling database creation")
3357 % journal % filename);
3358
3359}
3360
3361bool
3362database::database_specified()
3363{
3364 return !filename.empty();
3365}
3366
3367
3368void
3369database::open()
3370{
3371 I(!__sql);
3372
3373 if (sqlite3_open(filename.as_external().c_str(), &__sql) == SQLITE_NOMEM)
3374 throw std::bad_alloc();
3375
3376 I(__sql);
3377 assert_sqlite3_ok(__sql);
3378}
3379
3380void
3381database::close()
3382{
3383 I(__sql);
3384
3385 sqlite3_close(__sql);
3386 __sql = 0;
3387
3388 I(!__sql);
3389}
3390
3391// transaction guards
3392
3393transaction_guard::transaction_guard(database & d, bool exclusive,
3394 size_t checkpoint_batch_size,
3395 size_t checkpoint_batch_bytes)
3396 : committed(false), db(d), exclusive(exclusive),
3397 checkpoint_batch_size(checkpoint_batch_size),
3398 checkpoint_batch_bytes(checkpoint_batch_bytes),
3399 checkpointed_calls(0),
3400 checkpointed_bytes(0)
3401{
3402 db.begin_transaction(exclusive);
3403}
3404
3405transaction_guard::~transaction_guard()
3406{
3407 if (committed)
3408 db.commit_transaction();
3409 else
3410 db.rollback_transaction();
3411}
3412
3413void
3414transaction_guard::do_checkpoint()
3415{
3416 db.commit_transaction();
3417 db.begin_transaction(exclusive);
3418 checkpointed_calls = 0;
3419 checkpointed_bytes = 0;
3420}
3421
3422void
3423transaction_guard::maybe_checkpoint(size_t nbytes)
3424{
3425 checkpointed_calls += 1;
3426 checkpointed_bytes += nbytes;
3427 if (checkpointed_calls >= checkpoint_batch_size
3428 || checkpointed_bytes >= checkpoint_batch_bytes)
3429 do_checkpoint();
3430}
3431
3432void
3433transaction_guard::commit()
3434{
3435 committed = true;
3436}
3437
3438// Local Variables:
3439// mode: C++
3440// fill-column: 76
3441// c-file-style: "gnu"
3442// indent-tabs-mode: nil
3443// End:
3444// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

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