diff --git a/xapian-core/backends/brass/brass_database.cc b/xapian-core/backends/brass/brass_database.cc
index 56f534e..aa6f9fa 100644
a
|
b
|
|
7 | 7 | * Copyright 2006,2008 Lemur Consulting Ltd |
8 | 8 | * Copyright 2009 Richard Boulton |
9 | 9 | * Copyright 2009 Kan-Ru Chen |
| 10 | * Copyright 2011 Dan Colish |
10 | 11 | * |
11 | 12 | * This program is free software; you can redistribute it and/or |
12 | 13 | * modify it under the terms of the GNU General Public License as |
… |
… |
BrassDatabase::set_revision_number(brass_revision_number_t new_revision)
|
470 | 471 | |
471 | 472 | throw; |
472 | 473 | } |
| 474 | |
| 475 | // Only remove the oldest_changeset if we successfully write a new changeset and |
| 476 | // we have a revision number greater than max_changesets |
| 477 | if (changes_fd >= 0 && max_changesets < new_revision) { |
| 478 | // use the oldest changeset we know about to being deleting |
| 479 | // if nothing went wrong only one file should be deleted, otherwise |
| 480 | // attempts will be made to clean up more |
| 481 | brass_revision_number_t oldest_changeset = get_oldest_changeset(); |
| 482 | unsigned int stop_changeset = new_revision - max_changesets; |
| 483 | while (oldest_changeset < stop_changeset) { |
| 484 | if (io_unlink(db_dir + "/changes" + str(oldest_changeset))) { |
| 485 | LOGLINE(DB, "Removed changeset " << oldest_changeset); |
| 486 | } else { |
| 487 | LOGLINE(DB, "Skipping changeset " << oldest_changeset << |
| 488 | ", likely removed before"); |
| 489 | } |
| 490 | set_oldest_changeset(oldest_changeset++); |
| 491 | } |
| 492 | } |
473 | 493 | } |
474 | 494 | |
475 | 495 | void |
… |
… |
BrassDatabase::get_uuid() const
|
1008 | 1028 | RETURN(version_file.get_uuid_string()); |
1009 | 1029 | } |
1010 | 1030 | |
| 1031 | brass_revision_number_t |
| 1032 | BrassDatabase::get_oldest_changeset() const |
| 1033 | { |
| 1034 | LOGCALL(DB, brass_revision_number_t, "BrassDatabase::get_oldest_changeset", NO_ARGS); |
| 1035 | return stats.get_oldest_changeset(); |
| 1036 | } |
| 1037 | |
| 1038 | void |
| 1039 | BrassDatabase::set_oldest_changeset(brass_revision_number_t changeset) |
| 1040 | { |
| 1041 | LOGCALL(DB, void, "BrassDatabase::set_oldest_changeset", changeset); |
| 1042 | stats.set_oldest_changeset(changeset); |
| 1043 | } |
| 1044 | |
1011 | 1045 | /////////////////////////////////////////////////////////////////////////// |
1012 | 1046 | |
1013 | 1047 | BrassWritableDatabase::BrassWritableDatabase(const string &dir, int action, |
diff --git a/xapian-core/backends/brass/brass_database.h b/xapian-core/backends/brass/brass_database.h
index 6f8e928..408fc5b 100644
a
|
b
|
|
4 | 4 | * Copyright 2002 Ananova Ltd |
5 | 5 | * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2010 Olly Betts |
6 | 6 | * Copyright 2008 Lemur Consulting Ltd |
| 7 | * Copyright 2011 Dan Colish |
7 | 8 | * |
8 | 9 | * This program is free software; you can redistribute it and/or |
9 | 10 | * modify it under the terms of the GNU General Public License as |
… |
… |
class BrassDatabase : public Xapian::Database::Internal {
|
216 | 217 | void get_changeset_revisions(const string & path, |
217 | 218 | brass_revision_number_t * startrev, |
218 | 219 | brass_revision_number_t * endrev) const; |
| 220 | |
| 221 | /** Get the oldest changeset on disk |
| 222 | */ |
| 223 | brass_revision_number_t get_oldest_changeset() const; |
| 224 | |
| 225 | /** Set the new oldest changeset on disk |
| 226 | */ |
| 227 | void set_oldest_changeset(brass_revision_number_t oldest_changeset); |
| 228 | |
219 | 229 | public: |
220 | 230 | /** Create and open a brass database. |
221 | 231 | * |
diff --git a/xapian-core/backends/brass/brass_dbstats.cc b/xapian-core/backends/brass/brass_dbstats.cc
index d4bff9e..9d5bcec 100644
a
|
b
|
|
2 | 2 | * @brief Brass class for database statistics. |
3 | 3 | */ |
4 | 4 | /* Copyright (C) 2009 Olly Betts |
| 5 | * Copyright (C) 2011 Dan Colish |
5 | 6 | * |
6 | 7 | * This program is free software; you can redistribute it and/or |
7 | 8 | * modify it under the terms of the GNU General Public License as |
… |
… |
BrassDatabaseStats::read(BrassPostListTable & postlist_table)
|
35 | 36 | string data; |
36 | 37 | if (!postlist_table.get_exact_entry(DATABASE_STATS_KEY, data)) { |
37 | 38 | // If there's no entry yet, then all the values are zero. |
38 | | total_doclen = 0; |
39 | | last_docid = 0; |
40 | | doclen_lbound = 0; |
41 | | doclen_ubound = 0; |
42 | | wdf_ubound = 0; |
| 39 | zero(); |
43 | 40 | return; |
44 | 41 | } |
45 | 42 | |
… |
… |
BrassDatabaseStats::read(BrassPostListTable & postlist_table)
|
50 | 47 | unpack_uint(&p, end, &doclen_lbound) && |
51 | 48 | unpack_uint(&p, end, &wdf_ubound) && |
52 | 49 | unpack_uint(&p, end, &doclen_ubound) && |
| 50 | unpack_uint(&p, end, &oldest_changeset) && |
53 | 51 | unpack_uint_last(&p, end, &total_doclen)) { |
54 | 52 | // doclen_ubound should always be >= wdf_ubound, so we store the |
55 | 53 | // difference as it may encode smaller. wdf_ubound is likely to |
… |
… |
BrassDatabaseStats::write(BrassPostListTable & postlist_table) const
|
75 | 73 | // difference as it may encode smaller. wdf_ubound is likely to |
76 | 74 | // be larger than doclen_lbound. |
77 | 75 | pack_uint(data, doclen_ubound - wdf_ubound); |
| 76 | pack_uint(data, oldest_changeset); |
78 | 77 | // Micro-optimisation: total_doclen is likely to be the largest value, so |
79 | 78 | // store it last as pack_uint_last() uses a slightly more compact encoding |
80 | 79 | // - this could save us a few bytes! |
diff --git a/xapian-core/backends/brass/brass_dbstats.h b/xapian-core/backends/brass/brass_dbstats.h
index d3a281e..131afd8 100644
a
|
b
|
|
2 | 2 | * @brief Brass class for database statistics. |
3 | 3 | */ |
4 | 4 | /* Copyright (C) 2009 Olly Betts |
| 5 | * Copyright (C) 2011 Dan Colish |
5 | 6 | * |
6 | 7 | * This program is free software; you can redistribute it and/or |
7 | 8 | * modify it under the terms of the GNU General Public License as |
… |
… |
class BrassDatabaseStats {
|
51 | 52 | /// An upper bound on the greatest wdf in this database. |
52 | 53 | Xapian::termcount wdf_ubound; |
53 | 54 | |
| 55 | /// Oldest changeset removed when max_changesets is set |
| 56 | brass_revision_number_t oldest_changeset; |
| 57 | |
54 | 58 | public: |
55 | 59 | BrassDatabaseStats() |
56 | 60 | : total_doclen(0), last_docid(0), doclen_lbound(0), doclen_ubound(0), |
57 | | wdf_ubound(0) { } |
| 61 | wdf_ubound(0), oldest_changeset(0) { } |
58 | 62 | |
59 | 63 | totlen_t get_total_doclen() const { return total_doclen; } |
60 | 64 | |
… |
… |
class BrassDatabaseStats {
|
70 | 74 | |
71 | 75 | Xapian::termcount get_wdf_upper_bound() const { return wdf_ubound; } |
72 | 76 | |
| 77 | brass_revision_number_t get_oldest_changeset() const { return oldest_changeset; } |
| 78 | |
73 | 79 | void zero() { |
74 | 80 | total_doclen = 0; |
75 | 81 | last_docid = 0; |
76 | 82 | doclen_lbound = 0; |
77 | 83 | doclen_ubound = 0; |
78 | 84 | wdf_ubound = 0; |
| 85 | oldest_changeset = 0; |
79 | 86 | } |
80 | 87 | |
81 | 88 | void read(BrassPostListTable & postlist_table); |
82 | 89 | |
83 | 90 | void set_last_docid(Xapian::docid did) { last_docid = did; } |
84 | 91 | |
| 92 | void set_oldest_changeset(brass_revision_number_t changeset) { oldest_changeset = changeset; } |
| 93 | |
85 | 94 | void add_document(Xapian::termcount doclen) { |
86 | 95 | if (total_doclen == 0 || (doclen && doclen < doclen_lbound)) |
87 | 96 | doclen_lbound = doclen; |
diff --git a/xapian-core/backends/brass/brass_version.cc b/xapian-core/backends/brass/brass_version.cc
index b54fb4b..b0190a9 100644
a
|
b
|
|
2 | 2 | * @brief BrassVersion class |
3 | 3 | */ |
4 | 4 | /* Copyright (C) 2006,2007,2008,2009,2010 Olly Betts |
| 5 | * Copyright (C) 2011 Dan Colish |
5 | 6 | * |
6 | 7 | * This program is free software; you can redistribute it and/or modify |
7 | 8 | * it under the terms of the GNU General Public License as published by |
… |
… |
|
43 | 44 | using namespace std; |
44 | 45 | |
45 | 46 | // YYYYMMDDX where X allows multiple format revisions in a day |
46 | | #define BRASS_VERSION 200912150 |
| 47 | #define BRASS_VERSION 201103110 |
| 48 | // 201103110 1.2.5? Bump for new max changesets dbstats |
47 | 49 | // 200912150 1.1.4 Brass debuts. |
48 | 50 | |
49 | 51 | #define MAGIC_STRING "IAmBrass" |
diff --git a/xapian-core/backends/chert/chert_database.cc b/xapian-core/backends/chert/chert_database.cc
index 3cc6b56..b8e54a7 100644
a
|
b
|
|
7 | 7 | * Copyright 2006,2008 Lemur Consulting Ltd |
8 | 8 | * Copyright 2009,2010 Richard Boulton |
9 | 9 | * Copyright 2009 Kan-Ru Chen |
| 10 | * Copyright 2011 Dan Colish |
10 | 11 | * |
11 | 12 | * This program is free software; you can redistribute it and/or |
12 | 13 | * modify it under the terms of the GNU General Public License as |
… |
… |
ChertDatabase::set_revision_number(chert_revision_number_t new_revision)
|
465 | 466 | |
466 | 467 | throw; |
467 | 468 | } |
| 469 | |
| 470 | if (changes_fd >= 0 && max_changesets < new_revision) { |
| 471 | // While change sets less than N - max_changesets exist, delete them |
| 472 | // 1 must be subtracted so we don't delete the changset we just wrote |
| 473 | // when max_changesets = 1 |
| 474 | unsigned rev = new_revision - max_changesets - 1; |
| 475 | while (io_unlink(db_dir + "/changes" + str(rev--))) { } |
| 476 | } |
468 | 477 | } |
469 | 478 | |
470 | 479 | void |
diff --git a/xapian-core/backends/flint/flint_database.cc b/xapian-core/backends/flint/flint_database.cc
index d5eb8a1..4623d94 100644
a
|
b
|
|
7 | 7 | * Copyright 2006,2008 Lemur Consulting Ltd |
8 | 8 | * Copyright 2009,2010 Richard Boulton |
9 | 9 | * Copyright 2009 Kan-Ru Chen |
| 10 | * Copyright 2011 Dan Colish |
10 | 11 | * |
11 | 12 | * This program is free software; you can redistribute it and/or |
12 | 13 | * modify it under the terms of the GNU General Public License as |
… |
… |
FlintDatabase::set_revision_number(flint_revision_number_t new_revision)
|
497 | 498 | |
498 | 499 | throw; |
499 | 500 | } |
| 501 | |
| 502 | if (changes_fd >= 0 && max_changesets < new_revision) { |
| 503 | // while change sets less than N - max_changesets exist, delete them |
| 504 | // 1 must be subtracted so we don't delete the changset we just wrote |
| 505 | // when max_changesets = 1 |
| 506 | unsigned rev = new_revision - max_changesets - 1; |
| 507 | while (io_unlink(db_dir + "/changes" + str(rev--))) { } |
| 508 | } |
500 | 509 | } |
501 | 510 | |
502 | 511 | void |
diff --git a/xapian-core/tests/api_replicate.cc b/xapian-core/tests/api_replicate.cc
index fdd18f8..9e118e0 100644
a
|
b
|
|
3 | 3 | * Copyright 2008 Lemur Consulting Ltd |
4 | 4 | * Copyright 2009,2010 Olly Betts |
5 | 5 | * Copyright 2010 Richard Boulton |
| 6 | * Copyright 2011 Dan Colish |
6 | 7 | * |
7 | 8 | * This program is free software; you can redistribute it and/or |
8 | 9 | * modify it under the terms of the GNU General Public License as |
… |
… |
DEFINE_TESTCASE(replicate3, replicas) {
|
512 | 513 | return true; |
513 | 514 | } |
514 | 515 | |
515 | | // Basic test of replication functionality. |
| 516 | // Tests for max_changesets |
516 | 517 | DEFINE_TESTCASE(replicate4, replicas) { |
517 | 518 | string tempdir = ".replicatmp"; |
518 | 519 | mktmpdir(tempdir); |
519 | 520 | string masterpath = get_named_writable_database_path("master"); |
520 | 521 | |
521 | | set_max_changesets(10); |
| 522 | set_max_changesets(1); |
522 | 523 | |
523 | 524 | Xapian::WritableDatabase orig(get_named_writable_database("master")); |
524 | 525 | Xapian::DatabaseMaster master(masterpath); |
… |
… |
DEFINE_TESTCASE(replicate4, replicas) {
|
555 | 556 | } |
556 | 557 | check_equal_dbs(masterpath, replicapath); |
557 | 558 | |
| 559 | // Add a document with no positions to the original database. |
| 560 | Xapian::Document doc2; |
| 561 | doc2.set_data(string("doc2")); |
| 562 | doc2.add_term("nopos"); |
| 563 | orig.add_document(doc2); |
| 564 | orig.commit(); |
| 565 | |
| 566 | // Replicate, and check that we have the positional information. |
| 567 | count = replicate(master, replica, tempdir, 1, 0, 1); |
| 568 | TEST_EQUAL(count, 2); |
| 569 | { |
| 570 | Xapian::Database dbcopy(replicapath); |
| 571 | TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid()); |
| 572 | } |
| 573 | check_equal_dbs(masterpath, replicapath); |
| 574 | |
| 575 | int changes_fd = -1; |
| 576 | string path = masterpath + "/changes1"; |
| 577 | #ifdef __WIN32__ |
| 578 | changes_fd = msvc_posix_open(path.c_str(), O_RDONLY); |
| 579 | #else |
| 580 | changes_fd = open(path.c_str(), O_RDONLY); |
| 581 | #endif |
| 582 | fdcloser closer(changes_fd); |
| 583 | |
| 584 | TEST_EQUAL(changes_fd, -1); |
| 585 | |
558 | 586 | // Need to close the replica before we remove the temporary directory on |
559 | 587 | // Windows. |
560 | 588 | replica.close(); |