00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025
00026 #include "api_replicate.h"
00027
00028 #include <xapian.h>
00029
00030 #include "apitest.h"
00031 #include "dbcheck.h"
00032 #include "safeerrno.h"
00033 #include "safefcntl.h"
00034 #include "safesysstat.h"
00035 #include "safeunistd.h"
00036 #include "str.h"
00037 #include "testsuite.h"
00038 #include "testutils.h"
00039 #include "utils.h"
00040 #include "unixcmds.h"
00041
00042 #include <sys/types.h>
00043
00044 #include <cstdlib>
00045 #include <string>
00046
00047 #include <stdlib.h>
00048
00049 using namespace std;
00050
00051 static void rmtmpdir(const string & path) {
00052 rm_rf(path);
00053 }
00054
00055 static void mktmpdir(const string & path) {
00056 rmtmpdir(path);
00057 if (mkdir(path, 0700) == -1 && errno != EEXIST) {
00058 FAIL_TEST("Can't make temporary directory");
00059 }
00060 }
00061
00062 static off_t file_size(const string & path) {
00063 struct stat sb;
00064 if (stat(path.c_str(), &sb)) {
00065 FAIL_TEST("Can't stat '" + path + "'");
00066 }
00067 return sb.st_size;
00068 }
00069
00070 static size_t do_read(int fd, char * p, size_t desired)
00071 {
00072 size_t total = 0;
00073 while (desired) {
00074 ssize_t c = read(fd, p, desired);
00075 if (c == 0) return total;
00076 if (c < 0) {
00077 if (errno == EINTR) continue;
00078 FAIL_TEST("Error reading from file");
00079 }
00080 p += c;
00081 total += c;
00082 desired -= c;
00083 }
00084 return total;
00085 }
00086
00087 static void do_write(int fd, const char * p, size_t n)
00088 {
00089 while (n) {
00090 ssize_t c = write(fd, p, n);
00091 if (c < 0) {
00092 if (errno == EINTR) continue;
00093 FAIL_TEST("Error writing to file");
00094 }
00095 p += c;
00096 n -= c;
00097 }
00098 }
00099
00100
00101 static off_t
00102 truncated_copy(const string & srcpath, const string & destpath, off_t tocopy)
00103 {
00104 int fdin = open(srcpath.c_str(), O_RDONLY | O_BINARY);
00105 if (fdin == -1) {
00106 FAIL_TEST("Open failed (when opening '" + srcpath + "')");
00107 }
00108
00109 int fdout = open(destpath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
00110 if (fdout == -1) {
00111 FAIL_TEST("Open failed (when creating '" + destpath + "')");
00112 }
00113
00114 #define BUFSIZE 1024
00115 char buf[BUFSIZE];
00116 size_t total_bytes = 0;
00117 while (tocopy > 0) {
00118 size_t thiscopy = tocopy > BUFSIZE ? BUFSIZE : tocopy;
00119 size_t bytes = do_read(fdin, buf, thiscopy);
00120 if (thiscopy != bytes) {
00121 FAIL_TEST("Couldn't read desired number of bytes from changeset");
00122 }
00123 tocopy -= bytes;
00124 total_bytes += bytes;
00125 do_write(fdout, buf, bytes);
00126 }
00127 #undef BUFSIZE
00128
00129 close(fdin);
00130 close(fdout);
00131
00132 return total_bytes;
00133 }
00134
00135
00136
00137 static void
00138 get_changeset(const string & changesetpath,
00139 Xapian::DatabaseMaster & master,
00140 Xapian::DatabaseReplica & replica,
00141 int expected_changesets,
00142 int expected_fullcopies,
00143 bool expected_changed,
00144 bool full_copy = false)
00145 {
00146 int fd = open(changesetpath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
00147 if (fd == -1) {
00148 FAIL_TEST("Open failed (when creating a new changeset file at '"
00149 + changesetpath + "')");
00150 }
00151 fdcloser fdc(fd);
00152 Xapian::ReplicationInfo info1;
00153 master.write_changesets_to_fd(fd,
00154 full_copy ? "" : replica.get_revision_info(),
00155 &info1);
00156
00157 TEST_EQUAL(info1.changeset_count, expected_changesets);
00158 TEST_EQUAL(info1.fullcopy_count, expected_fullcopies);
00159 TEST_EQUAL(info1.changed, expected_changed);
00160 }
00161
00162 static int
00163 apply_changeset(const string & changesetpath,
00164 Xapian::DatabaseReplica & replica,
00165 int expected_changesets,
00166 int expected_fullcopies,
00167 bool expected_changed)
00168 {
00169 int fd = open(changesetpath.c_str(), O_RDONLY | O_BINARY);
00170 if (fd == -1) {
00171 FAIL_TEST("Open failed (when reading changeset file at '"
00172 + changesetpath + "')");
00173 }
00174 fdcloser fdc(fd);
00175
00176 int count = 1;
00177 replica.set_read_fd(fd);
00178 Xapian::ReplicationInfo info1;
00179 Xapian::ReplicationInfo info2;
00180 bool client_changed = false;
00181 while (replica.apply_next_changeset(&info2, 0)) {
00182 ++count;
00183 info1.changeset_count += info2.changeset_count;
00184 info1.fullcopy_count += info2.fullcopy_count;
00185 if (info2.changed)
00186 client_changed = true;
00187 }
00188 info1.changeset_count += info2.changeset_count;
00189 info1.fullcopy_count += info2.fullcopy_count;
00190 if (info2.changed)
00191 client_changed = true;
00192
00193 TEST_EQUAL(info1.changeset_count, expected_changesets);
00194 TEST_EQUAL(info1.fullcopy_count, expected_fullcopies);
00195 TEST_EQUAL(client_changed, expected_changed);
00196 return count;
00197 }
00198
00199 static int
00200 replicate(Xapian::DatabaseMaster & master,
00201 Xapian::DatabaseReplica & replica,
00202 const string & tempdir,
00203 int expected_changesets,
00204 int expected_fullcopies,
00205 bool expected_changed,
00206 bool full_copy = false)
00207 {
00208 string changesetpath = tempdir + "/changeset";
00209 get_changeset(changesetpath, master, replica,
00210 expected_changesets,
00211 expected_fullcopies,
00212 expected_changed,
00213 full_copy);
00214 return apply_changeset(changesetpath, replica,
00215 expected_changesets,
00216 expected_fullcopies,
00217 expected_changed);
00218 }
00219
00220
00221 static void
00222 check_equal_dbs(const string & masterpath, const string & replicapath)
00223 {
00224 Xapian::Database master(masterpath);
00225 Xapian::Database replica(replicapath);
00226
00227 TEST_EQUAL(master.get_uuid(), master.get_uuid());
00228 dbcheck(replica, master.get_doccount(), master.get_lastdocid());
00229
00230 for (Xapian::TermIterator t = master.allterms_begin();
00231 t != master.allterms_end(); ++t) {
00232 TEST_EQUAL(postlist_to_string(master, *t),
00233 postlist_to_string(replica, *t));
00234 }
00235 }
00236
00237 #if 0 // Dynamic version which we don't currently need.
00238 static void
00239 set_max_changesets(int count) {
00240 #ifdef __WIN32__
00241 _putenv_s("XAPIAN_MAX_CHANGESETS", str(count).c_str());
00242 #elif defined HAVE_SETENV
00243 setenv("XAPIAN_MAX_CHANGESETS", str(count).c_str(), 1);
00244 #else
00245 static char buf[64] = "XAPIAN_MAX_CHANGESETS=";
00246 sprintf(buf + CONST_STRLEN("XAPIAN_MAX_CHANGESETS="), "%d", count);
00247 putenv(buf);
00248 #endif
00249 }
00250 #endif
00251
00252 #ifdef __WIN32__
00253 # define set_max_changesets(N) _putenv_s("XAPIAN_MAX_CHANGESETS", #N)
00254 #elif defined HAVE_SETENV
00255 # define set_max_changesets(N) setenv("XAPIAN_MAX_CHANGESETS", #N, 1)
00256 #else
00257 # define set_max_changesets(N) putenv(const_cast<char*>("XAPIAN_MAX_CHANGESETS="#N))
00258 #endif
00259
00260 struct unset_max_changesets_helper_ {
00261 unset_max_changesets_helper_() { }
00262 ~unset_max_changesets_helper_() { set_max_changesets(0); }
00263 };
00264
00265
00266
00267 #define UNSET_MAX_CHANGESETS_AFTERWARDS unset_max_changesets_helper_ ezlxq
00268
00269
00270
00271
00272
00273 DEFINE_TESTCASE(replicate1, replicas) {
00274 UNSET_MAX_CHANGESETS_AFTERWARDS;
00275 string tempdir = ".replicatmp";
00276 mktmpdir(tempdir);
00277 string masterpath = get_named_writable_database_path("master");
00278
00279 set_max_changesets(10);
00280
00281 Xapian::WritableDatabase orig(get_named_writable_database("master"));
00282 Xapian::DatabaseMaster master(masterpath);
00283 string replicapath = tempdir + "/replica";
00284 Xapian::DatabaseReplica replica(replicapath);
00285
00286
00287 Xapian::Document doc1;
00288 doc1.set_data(string("doc1"));
00289 doc1.add_posting("doc", 1);
00290 doc1.add_posting("one", 1);
00291 orig.add_document(doc1);
00292 orig.commit();
00293
00294
00295
00296 int count = replicate(master, replica, tempdir, 0, 1, true);
00297 TEST_EQUAL(count, 1);
00298 {
00299 Xapian::Database dbcopy(replicapath);
00300 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00301 }
00302
00303
00304
00305 count = replicate(master, replica, tempdir, 0, 0, false);
00306 TEST_EQUAL(count, 1);
00307 {
00308 Xapian::Database dbcopy(replicapath);
00309 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00310 }
00311
00312
00313
00314 replica.close();
00315 replica = Xapian::DatabaseReplica(replicapath);
00316 count = replicate(master, replica, tempdir, 0, 0, false);
00317 TEST_EQUAL(count, 1);
00318 {
00319 Xapian::Database dbcopy(replicapath);
00320 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00321 }
00322
00323 orig.add_document(doc1);
00324 orig.commit();
00325 orig.add_document(doc1);
00326 orig.commit();
00327
00328 count = replicate(master, replica, tempdir, 2, 0, true);
00329 TEST_EQUAL(count, 3);
00330 {
00331 Xapian::Database dbcopy(replicapath);
00332 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00333 }
00334
00335 check_equal_dbs(masterpath, replicapath);
00336
00337
00338
00339 replica.close();
00340 rmtmpdir(tempdir);
00341 return true;
00342 }
00343
00344
00345 DEFINE_TESTCASE(replicate2, replicas) {
00346 SKIP_TEST_FOR_BACKEND("brass");
00347 UNSET_MAX_CHANGESETS_AFTERWARDS;
00348
00349 string tempdir = ".replicatmp";
00350 mktmpdir(tempdir);
00351 string masterpath = get_named_writable_database_path("master");
00352
00353 set_max_changesets(10);
00354
00355 Xapian::WritableDatabase orig(get_named_writable_database("master"));
00356 Xapian::DatabaseMaster master(masterpath);
00357 string replicapath = tempdir + "/replica";
00358 Xapian::DatabaseReplica replica(replicapath);
00359
00360 Xapian::DatabaseMaster master2(replicapath);
00361 string replica2path = tempdir + "/replica2";
00362 Xapian::DatabaseReplica replica2(replica2path);
00363
00364
00365 Xapian::Document doc1;
00366 doc1.set_data(string("doc1"));
00367 doc1.add_posting("doc", 1);
00368 doc1.add_posting("one", 1);
00369 orig.add_document(doc1);
00370 orig.commit();
00371
00372
00373
00374 TEST_EQUAL(replicate(master, replica, tempdir, 0, 1, true), 1);
00375 check_equal_dbs(masterpath, replicapath);
00376
00377
00378 TEST_EQUAL(replicate(master2, replica2, tempdir, 0, 1, true), 1);
00379 check_equal_dbs(masterpath, replica2path);
00380
00381 orig.add_document(doc1);
00382 orig.commit();
00383 orig.add_document(doc1);
00384 orig.commit();
00385
00386
00387 TEST_EQUAL(replicate(master2, replica2, tempdir, 0, 0, false), 1);
00388 check_equal_dbs(replicapath, replica2path);
00389
00390
00391 TEST_EQUAL(replicate(master, replica, tempdir, 2, 0, 1), 3);
00392 check_equal_dbs(masterpath, replicapath);
00393 TEST_EQUAL(replicate(master2, replica2, tempdir, 2, 0, 1), 3);
00394 check_equal_dbs(masterpath, replica2path);
00395
00396
00397 set_max_changesets(0);
00398 orig.close();
00399 orig = get_writable_database_again();
00400 orig.add_document(doc1);
00401 orig.commit();
00402
00403
00404 TEST_EQUAL(replicate(master, replica, tempdir, 0, 1, true), 1);
00405 check_equal_dbs(masterpath, replicapath);
00406 TEST_EQUAL(replicate(master2, replica2, tempdir, 0, 1, true), 1);
00407 check_equal_dbs(masterpath, replica2path);
00408
00409
00410
00411 set_max_changesets(1);
00412 orig.close();
00413 orig = get_writable_database_again();
00414 orig.add_document(doc1);
00415 orig.commit();
00416
00417
00418 TEST_EQUAL(replicate(master, replica, tempdir, 1, 0, 1), 2);
00419 check_equal_dbs(masterpath, replicapath);
00420 TEST_EQUAL(replicate(master2, replica2, tempdir, 1, 0, 1), 2);
00421 check_equal_dbs(masterpath, replica2path);
00422
00423
00424 orig.add_document(doc1);
00425 orig.commit();
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 replica.close();
00439 replica2.close();
00440 rmtmpdir(tempdir);
00441 return true;
00442 }
00443
00444 static void
00445 replicate_with_brokenness(Xapian::DatabaseMaster & master,
00446 Xapian::DatabaseReplica & replica,
00447 const string & tempdir,
00448 int expected_changesets,
00449 int expected_fullcopies,
00450 bool expected_changed)
00451 {
00452 string changesetpath = tempdir + "/changeset";
00453 get_changeset(changesetpath, master, replica,
00454 1, 0, 1);
00455
00456
00457 string brokenchangesetpath = tempdir + "/changeset_broken";
00458 off_t filesize = file_size(changesetpath);
00459 off_t len = 10;
00460 off_t copylen;
00461 while (len < filesize) {
00462 copylen = truncated_copy(changesetpath, brokenchangesetpath, len);
00463 TEST_EQUAL(copylen, len);
00464 tout << "Trying replication with a changeset truncated to " << len <<
00465 " bytes, from " << filesize << " bytes\n";
00466 TEST_EXCEPTION(Xapian::NetworkError,
00467 apply_changeset(brokenchangesetpath, replica,
00468 expected_changesets, expected_fullcopies,
00469 expected_changed));
00470 if (len < 30 || len >= filesize - 10) {
00471
00472 ++len;
00473 } else {
00474
00475
00476 len += 1000;
00477 if (len >= filesize - 10) {
00478 len = filesize - 10;
00479 }
00480 }
00481 }
00482 }
00483
00484
00485 DEFINE_TESTCASE(replicate3, replicas) {
00486 UNSET_MAX_CHANGESETS_AFTERWARDS;
00487 string tempdir = ".replicatmp";
00488 mktmpdir(tempdir);
00489 string masterpath = get_named_writable_database_path("master");
00490
00491 set_max_changesets(10);
00492
00493 Xapian::WritableDatabase orig(get_named_writable_database("master"));
00494 Xapian::DatabaseMaster master(masterpath);
00495 string replicapath = tempdir + "/replica";
00496 Xapian::DatabaseReplica replica(replicapath);
00497
00498
00499 Xapian::Document doc1;
00500 doc1.set_data(string("doc1"));
00501 doc1.add_posting("doc", 1);
00502 doc1.add_posting("one", 1);
00503 orig.add_document(doc1);
00504 orig.commit();
00505
00506 TEST_EQUAL(replicate(master, replica, tempdir, 0, 1, true), 1);
00507 check_equal_dbs(masterpath, replicapath);
00508
00509
00510 orig.add_document(doc1);
00511 orig.commit();
00512
00513 replicate_with_brokenness(master, replica, tempdir, 1, 0, true);
00514
00515
00516
00517 check_equal_dbs(masterpath, replicapath);
00518
00519
00520
00521 orig.add_document(doc1);
00522 orig.commit();
00523 TEST_EQUAL(replicate(master, replica, tempdir, 1, 0, true), 2);
00524
00525
00526
00527 replica.close();
00528 rmtmpdir(tempdir);
00529 return true;
00530 }
00531
00532
00533 DEFINE_TESTCASE(replicate4, replicas) {
00534 UNSET_MAX_CHANGESETS_AFTERWARDS;
00535 string tempdir = ".replicatmp";
00536 mktmpdir(tempdir);
00537 string masterpath = get_named_writable_database_path("master");
00538
00539 set_max_changesets(1);
00540
00541 Xapian::WritableDatabase orig(get_named_writable_database("master"));
00542 Xapian::DatabaseMaster master(masterpath);
00543 string replicapath = tempdir + "/replica";
00544 Xapian::DatabaseReplica replica(replicapath);
00545
00546
00547 Xapian::Document doc1;
00548 doc1.set_data(string("doc1"));
00549 doc1.add_term("nopos");
00550 orig.add_document(doc1);
00551 orig.commit();
00552
00553
00554
00555 int count = replicate(master, replica, tempdir, 0, 1, true);
00556 TEST_EQUAL(count, 1);
00557 {
00558 Xapian::Database dbcopy(replicapath);
00559 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00560 }
00561
00562
00563 doc1.add_posting("pos", 1);
00564 orig.add_document(doc1);
00565 orig.commit();
00566
00567
00568 count = replicate(master, replica, tempdir, 1, 0, true);
00569 TEST_EQUAL(count, 2);
00570 {
00571 Xapian::Database dbcopy(replicapath);
00572 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00573 }
00574 check_equal_dbs(masterpath, replicapath);
00575
00576
00577 Xapian::Document doc2;
00578 doc2.set_data(string("doc2"));
00579 doc2.add_term("nopos");
00580 orig.add_document(doc2);
00581 orig.commit();
00582
00583
00584 count = replicate(master, replica, tempdir, 1, 0, true);
00585 TEST_EQUAL(count, 2);
00586 {
00587 Xapian::Database dbcopy(replicapath);
00588 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00589 }
00590 check_equal_dbs(masterpath, replicapath);
00591 TEST(!file_exists(masterpath + "/changes1"));
00592
00593
00594 set_max_changesets(0);
00595
00596
00597 Xapian::Document doc3;
00598 doc3.set_data(string("doc3"));
00599 doc3.add_term("nonopos");
00600 orig.add_document(doc3);
00601 orig.commit();
00602
00603
00604 count = replicate(master, replica, tempdir, 0, 1, true);
00605 TEST_EQUAL(count, 1);
00606 {
00607 Xapian::Database dbcopy(replicapath);
00608 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00609 }
00610
00611 check_equal_dbs(masterpath, replicapath);
00612 TEST(!file_exists(masterpath + "/changes3"));
00613
00614
00615
00616
00617 replica.close();
00618 rmtmpdir(tempdir);
00619 return true;
00620 }
00621
00622
00623
00624 DEFINE_TESTCASE(replicate5, replicas) {
00625 SKIP_TEST_FOR_BACKEND("chert");
00626 SKIP_TEST_FOR_BACKEND("flint");
00627 UNSET_MAX_CHANGESETS_AFTERWARDS;
00628 string tempdir = ".replicatmp";
00629 mktmpdir(tempdir);
00630 string masterpath = get_named_writable_database_path("master");
00631
00632 set_max_changesets(2);
00633
00634 Xapian::WritableDatabase orig(get_named_writable_database("master"));
00635 Xapian::DatabaseMaster master(masterpath);
00636 string replicapath = tempdir + "/replica";
00637 Xapian::DatabaseReplica replica(replicapath);
00638
00639
00640 Xapian::Document doc1;
00641 doc1.set_data(string("doc1"));
00642 doc1.add_term("nopos");
00643 orig.add_document(doc1);
00644 orig.commit();
00645
00646
00647
00648 int count = replicate(master, replica, tempdir, 0, 1, true);
00649 TEST_EQUAL(count, 1);
00650 {
00651 Xapian::Database dbcopy(replicapath);
00652 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00653 }
00654
00655
00656 doc1.add_posting("pos", 1);
00657 orig.add_document(doc1);
00658 orig.commit();
00659
00660
00661 count = replicate(master, replica, tempdir, 1, 0, true);
00662 TEST_EQUAL(count, 2);
00663 {
00664 Xapian::Database dbcopy(replicapath);
00665 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00666 }
00667 check_equal_dbs(masterpath, replicapath);
00668
00669
00670 Xapian::Document doc2;
00671 doc2.set_data(string("doc2"));
00672 doc2.add_term("nopos");
00673 orig.add_document(doc2);
00674 orig.commit();
00675
00676
00677 count = replicate(master, replica, tempdir, 1, 0, true);
00678 TEST_EQUAL(count, 2);
00679 {
00680 Xapian::Database dbcopy(replicapath);
00681 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00682 }
00683 check_equal_dbs(masterpath, replicapath);
00684
00685
00686 Xapian::Document doc3;
00687 doc3.set_data(string("doc3"));
00688 doc3.add_term("nonopos");
00689 orig.add_document(doc3);
00690 orig.commit();
00691
00692
00693 count = replicate(master, replica, tempdir, 1, 0, true);
00694 TEST_EQUAL(count, 2);
00695 {
00696 Xapian::Database dbcopy(replicapath);
00697 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00698 }
00699 check_equal_dbs(masterpath, replicapath);
00700
00701
00702 TEST(!file_exists(masterpath + "/changes1"));
00703 TEST(file_exists(masterpath + "/changes2"));
00704 TEST(file_exists(masterpath + "/changes3"));
00705
00706 set_max_changesets(3);
00707 masterpath = get_named_writable_database_path("master");
00708
00709
00710 Xapian::Document doc4;
00711 doc4.set_data(string("doc4"));
00712 doc4.add_term("nononopos");
00713 orig.add_document(doc4);
00714 orig.commit();
00715
00716
00717 count = replicate(master, replica, tempdir, 1, 0, true);
00718 TEST_EQUAL(count, 2);
00719 {
00720 Xapian::Database dbcopy(replicapath);
00721 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00722 }
00723 check_equal_dbs(masterpath, replicapath);
00724
00725
00726 Xapian::Document doc5;
00727 doc5.set_data(string("doc5"));
00728 doc5.add_term("nonononopos");
00729 orig.add_document(doc5);
00730 orig.commit();
00731
00732
00733 count = replicate(master, replica, tempdir, 1, 0, true);
00734 TEST_EQUAL(count, 2);
00735 {
00736 Xapian::Database dbcopy(replicapath);
00737 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00738 }
00739 check_equal_dbs(masterpath, replicapath);
00740
00741 TEST(!file_exists(masterpath + "/changes2"));
00742 TEST(file_exists(masterpath + "/changes3"));
00743 TEST(file_exists(masterpath + "/changes4"));
00744 TEST(file_exists(masterpath + "/changes5"));
00745
00746
00747
00748 replica.close();
00749 rmtmpdir(tempdir);
00750 return true;
00751 }
00752
00754 DEFINE_TESTCASE(replicate6, replicas) {
00755 UNSET_MAX_CHANGESETS_AFTERWARDS;
00756 string tempdir = ".replicatmp";
00757 mktmpdir(tempdir);
00758 string masterpath = get_named_writable_database_path("master");
00759
00760 set_max_changesets(10);
00761
00762 Xapian::WritableDatabase orig(get_named_writable_database("master"));
00763 Xapian::DatabaseMaster master(masterpath);
00764 string replicapath = tempdir + "/replica";
00765 Xapian::DatabaseReplica replica(replicapath);
00766
00767
00768 Xapian::Document doc1;
00769 doc1.set_data(string("doc1"));
00770 doc1.add_posting("doc", 1);
00771 doc1.add_posting("one", 1);
00772 orig.add_document(doc1);
00773 orig.commit();
00774
00775 rm_rf(masterpath + "1");
00776 cp_R(masterpath, masterpath + "1");
00777
00778 orig.add_document(doc1);
00779 orig.commit();
00780
00781
00782
00783 int count = replicate(master, replica, tempdir, 0, 1, true);
00784 TEST_EQUAL(count, 1);
00785 {
00786 Xapian::Database dbcopy(replicapath);
00787 TEST_EQUAL(orig.get_uuid(), dbcopy.get_uuid());
00788 }
00789
00790 Xapian::DatabaseMaster master1(masterpath + "1");
00791
00792
00793 count = replicate(master1, replica, tempdir, 0, 0, false);
00794 TEST_EQUAL(count, 1);
00795
00796
00797 count = replicate(master1, replica, tempdir, 0, 1, true, true);
00798 TEST_EQUAL(count, 1);
00799
00800
00801 orig.add_document(doc1);
00802 orig.commit();
00803
00804 count = replicate(master, replica, tempdir, 2, 0, true);
00805 TEST_EQUAL(count, 3);
00806
00807 check_equal_dbs(masterpath, replicapath);
00808
00809
00810
00811 replica.close();
00812 rmtmpdir(tempdir);
00813 return true;
00814 }