Ticket #451: compactchunks.patch

File compactchunks.patch, 21.4 KB (added by Richard Boulton, 14 years ago)

Patch implementing a --rebuild-chunks option to xapian-compact for chert databases

  • tests/api_compact.cc

     
    259259
    260260    return true;
    261261}
     262
     263static void
     264make_rebuildchunks_db(Xapian::WritableDatabase &db, const string & s)
     265{
     266    char * p = const_cast<char *>(s.c_str());
     267    bool valuesonly = false;
     268    if (*p == 'v') {
     269        valuesonly = true;
     270        ++p;
     271    }
     272    Xapian::docid first = strtoul(p, &p, 10);
     273    if (*p != '-') {
     274        FAIL_TEST("Bad rebuildchunks db param: (expected -): " << s);
     275    }
     276    ++p;
     277    Xapian::docid last = strtoul(p, &p, 10);
     278    if (*p != ':') {
     279        FAIL_TEST("Bad rebuildchunks db param: (expected colon): " << s);
     280    }
     281    ++p;
     282    Xapian::docid step = strtoul(p, &p, 10);
     283
     284    for (Xapian::docid i = first; i <= last; i += step) {
     285        Xapian::Document doc;
     286        if (!valuesonly) {
     287            doc.add_term("a");
     288            doc.add_term("Q" + str(i));
     289        }
     290        doc.add_value(0, "v" + str(i));
     291        if (i % 3 == 0)
     292            doc.add_value(1, "v" + str(i));
     293        db.replace_document(i, doc);
     294    }
     295
     296    db.commit();
     297}
     298
     299// Test use of compact with the --rebuild-chunks option.
     300DEFINE_TESTCASE(compactrebuildchunks1, chert) {
     301    int status;
     302    string cmd = XAPIAN_COMPACT" "SILENT" --no-renumber --rebuild-chunks ";
     303    string indb1path = get_database_path("compactrebuildchunks1in1",
     304                                         make_rebuildchunks_db, "1-10001:2");
     305    string indb2path = get_database_path("compactrebuildchunks1in2",
     306                                         make_rebuildchunks_db, "2-10000:2");
     307    string outdbpath = get_named_writable_database_path("compactrebuildchunks1out");
     308    rm_rf(outdbpath);
     309
     310    status = system(cmd + indb1path + " " + indb2path + " " + outdbpath);
     311    TEST_EQUAL(WEXITSTATUS(status), 0);
     312
     313    Xapian::Database out(outdbpath);
     314    dbcheck(out, 10001, 10001);
     315    for (Xapian::docid i = 1; i <= 10001; ++i) {
     316        Xapian::Document doc(out.get_document(i));
     317        Xapian::Document correctdoc;
     318        correctdoc.add_term("a");
     319        correctdoc.add_term("Q" + str(i));
     320        correctdoc.add_value(0, "v" + str(i));
     321        if (i % 3 == 0)
     322            correctdoc.add_value(1, "v" + str(i));
     323        TEST_EQUAL(doc.serialise(), correctdoc.serialise());
     324    }
     325
     326    return true;
     327}
     328
     329// Test use of compact with the --rebuild-chunks option with no terms.
     330DEFINE_TESTCASE(compactrebuildchunks2, chert) {
     331    int status;
     332    string cmd = XAPIAN_COMPACT" "SILENT" --no-renumber --rebuild-chunks ";
     333    string indb1path = get_database_path("compactrebuildchunks2in1",
     334                                         make_rebuildchunks_db, "v1-10001:2");
     335    string indb2path = get_database_path("compactrebuildchunks2in2",
     336                                         make_rebuildchunks_db, "v2-10000:2");
     337    string outdbpath = get_named_writable_database_path("compactrebuildchunks2out");
     338    rm_rf(outdbpath);
     339
     340    status = system(cmd + indb1path + " " + indb2path + " " + outdbpath);
     341    TEST_EQUAL(WEXITSTATUS(status), 0);
     342
     343    Xapian::Database out(outdbpath);
     344    dbcheck(out, 10001, 10001);
     345    for (Xapian::docid i = 1; i <= 10001; ++i) {
     346        Xapian::Document doc(out.get_document(i));
     347        Xapian::Document correctdoc;
     348        correctdoc.add_value(0, "v" + str(i));
     349        if (i % 3 == 0)
     350            correctdoc.add_value(1, "v" + str(i));
     351        TEST_EQUAL(doc.serialise(), correctdoc.serialise());
     352    }
     353
     354    return true;
     355}
  • bin/xapian-compact.cc

     
    5656#define OPT_HELP 1
    5757#define OPT_VERSION 2
    5858#define OPT_NO_RENUMBER 3
     59#define OPT_REBUILD_CHUNKS 4
    5960
    6061static void show_usage() {
    6162    cout << "Usage: "PROG_NAME" [OPTIONS] SOURCE_DATABASE... DESTINATION_DATABASE\n\n"
     
    7273"                    external references to them, or have set them to match\n"
    7374"                    unique ids from an external source).  Currently this\n"
    7475"                    option is only supported when merging databases if they\n"
    75 "                    have disjoint ranges of used document ids\n"
     76"                    have disjoint ranges of used document ids, or if\n"
     77"                    --rebuild-chunks is also specified.\n"
     78"  --rebuild-chunks  Rebuild the chunks in chunked tables.  Slower, but may\n"
     79"                    produce a more compact database, and allows overlapping\n"
     80"                    document IDs with the --no-renumber option.\n"
    7681"  --help            display this help and exit\n"
    7782"  --version         output version information and exit" << endl;
    7883}
     
    179184        {"multipass",   no_argument, 0, 'm'},
    180185        {"blocksize",   required_argument, 0, 'b'},
    181186        {"no-renumber", no_argument, 0, OPT_NO_RENUMBER},
     187        {"rebuild-chunks", no_argument, 0, OPT_REBUILD_CHUNKS},
    182188        {"help",        no_argument, 0, OPT_HELP},
    183189        {"version",     no_argument, 0, OPT_VERSION},
    184190        {NULL,          0, 0, 0}
     
    188194    size_t block_size = 8192;
    189195    bool multipass = false;
    190196    bool renumber = true;
     197    bool rebuild_chunks = false;
    191198
    192199    int c;
    193200    while ((c = gnu_getopt_long(argc, argv, opts, long_opts, 0)) != -1) {
     
    220227            case OPT_NO_RENUMBER:
    221228                renumber = false;
    222229                break;
     230            case OPT_REBUILD_CHUNKS:
     231                rebuild_chunks = true;
     232                break;
    223233            case OPT_HELP:
    224234                cout << PROG_NAME" - "PROG_DESC"\n\n";
    225235                show_usage();
     
    397407                if (p.first == 0 && p.second == 0)
    398408                    continue;
    399409                // Check for overlap with the previous database's range.
    400                 if (p.first <= last_end) {
     410                if (!rebuild_chunks && p.first <= last_end) {
    401411                    cout << argv[0]
    402                         << ": when merging databases, --no-renumber is only currently supported if the databases have disjoint ranges of used document ids.\n";
     412                        << ": when merging databases which have disjoint ranges of used document ids, --no-renumber is only supported together with --rebuild-chunks.\n";
    403413                    cout << sources[order[j - 1]] << " has range "
    404414                         << last_start << "-" << last_end << '\n';
    405415                    cout << sources[n] << " has range "
     
    435445
    436446        if (backend == FLINT) {
    437447            compact_flint(destdir, sources, offset, block_size, compaction,
    438                           multipass, last_docid);
     448                          multipass, last_docid, rebuild_chunks);
    439449        } else if (backend == BRASS) {
    440450            compact_brass(destdir, sources, offset, block_size, compaction,
    441                           multipass, last_docid);
     451                          multipass, last_docid, rebuild_chunks);
    442452        } else {
    443453            compact_chert(destdir, sources, offset, block_size, compaction,
    444                           multipass, last_docid);
     454                          multipass, last_docid, rebuild_chunks);
    445455        }
    446456
    447457        // Create the version file ("iamchert", etc).
  • bin/xapian-compact.h

     
    3333compact_brass(const char * destdir, const std::vector<std::string> & sources,
    3434              const std::vector<Xapian::docid> & offset, size_t block_size,
    3535              compaction_level compaction, bool multipass,
    36               Xapian::docid tot_off);
     36              Xapian::docid tot_off, bool rebuild_chunks);
    3737
    3838void
    3939compact_chert(const char * destdir, const std::vector<std::string> & sources,
    4040              const std::vector<Xapian::docid> & offset, size_t block_size,
    4141              compaction_level compaction, bool multipass,
    42               Xapian::docid tot_off);
     42              Xapian::docid tot_off, bool rebuild_chunks);
    4343
    4444void
    4545compact_flint(const char * destdir, const std::vector<std::string> & sources,
    4646              const std::vector<Xapian::docid> & offset, size_t block_size,
    4747              compaction_level compaction, bool multipass,
    48               Xapian::docid tot_off);
     48              Xapian::docid tot_off, bool rebuild_chunks);
    4949
    5050#endif
  • bin/xapian-compact-chert.cc

     
    22 * @brief Compact a chert database, or merge and compact several.
    33 */
    44/* Copyright (C) 2004,2005,2006,2007,2008,2009,2010 Olly Betts
     5 * Copyright (C) 2010 Richard Boulton
    56 *
    67 * This program is free software; you can redistribute it and/or
    78 * modify it under the terms of the GNU General Public License as
     
    2930
    3031#include <cstdio>
    3132
     33#include "autoptr.h"
    3234#include "safeerrno.h"
    3335#include <sys/types.h>
    3436#include "safesysstat.h"
     
    193195}
    194196
    195197static void
     198merge_postlist_chunks(ChertTable * out,
     199                      priority_queue<PostlistCursor *,
     200                                     vector<PostlistCursor *>,
     201                                     PostlistCursorGt> & pq);
     202static void
     203rebuild_valuelist_chunks(ChertTable * out,
     204                         priority_queue<PostlistCursor *,
     205                                        vector<PostlistCursor *>,
     206                                        PostlistCursorGt> & pq);
     207static void
     208rebuild_postlist_chunks(ChertTable * out,
     209                        priority_queue<PostlistCursor *,
     210                                       vector<PostlistCursor *>,
     211                                       PostlistCursorGt> & pq);
     212
     213static void
    196214merge_postlists(ChertTable * out, vector<Xapian::docid>::const_iterator offset,
    197215                vector<string>::const_iterator b, vector<string>::const_iterator e,
    198                 Xapian::docid tot_off)
     216                Xapian::docid tot_off, bool rebuild_chunks)
    199217{
    200218    totlen_t tot_totlen = 0;
    201219    Xapian::termcount doclen_lbound = static_cast<Xapian::termcount>(-1);
     
    364382        }
    365383    }
    366384
     385    if (rebuild_chunks) {
     386        rebuild_valuelist_chunks(out, pq);
     387        rebuild_postlist_chunks(out, pq);
     388    } else {
     389        merge_postlist_chunks(out, pq);
     390    }
     391}
     392
     393/// Merge postlist chunks, without rebuilding them.
     394static void
     395merge_postlist_chunks(ChertTable * out,
     396                      priority_queue<PostlistCursor *,
     397                                     vector<PostlistCursor *>,
     398                                     PostlistCursorGt> & pq)
     399{
    367400    // Merge valuestream chunks.
    368401    while (!pq.empty()) {
    369402        PostlistCursor * cur = pq.top();
     
    381414
    382415    Xapian::termcount tf = 0, cf = 0; // Initialise to avoid warnings.
    383416    vector<pair<Xapian::docid, string> > tags;
     417    string last_key;
    384418    while (true) {
    385419        PostlistCursor * cur = NULL;
    386420        if (!pq.empty()) {
     
    391425        if (cur == NULL || cur->key != last_key) {
    392426            if (!tags.empty()) {
    393427                string first_tag;
    394                 pack_uint(first_tag, tf);
     428                pack_uint(first_tag, tf);
    395429                pack_uint(first_tag, cf);
    396430                pack_uint(first_tag, tags[0].first - 1);
    397431                string tag = tags[0].second;
     
    431465    }
    432466}
    433467
     468class ValueChunkReader {
     469    string chunk;
     470    const char * p;
     471    const char * end;
     472    Xapian::docid did;
     473    Xapian::valueno slot;
     474    string value;
     475  public:
     476    ValueChunkReader(const string & key, const string & chunk_)
     477    {
     478        Assert(key.size() > 2 && key[0] == '\0' && key[1] == '\xd8');
     479        p = key.data() + 2;
     480        end = key.data() + key.size();
     481        if (!unpack_uint(&p, end, &slot))
     482            throw Xapian::DatabaseCorruptError("Invalid value number");
     483        if (!unpack_uint_preserving_sort(&p, end, &did))
     484            throw Xapian::DatabaseCorruptError("Invalid docid in value key");
     485        if (p != end)
     486            throw Xapian::DatabaseCorruptError("Junk at end of value key");
     487
     488        chunk = chunk_;
     489        p = chunk.data();
     490        end = p + chunk.size();
     491        if (!unpack_string(&p, end, value))
     492            throw Xapian::DatabaseCorruptError("Invalid initial value");
     493    }
     494    bool at_end() const { return p == NULL; }
     495    Xapian::docid get_docid() const { return did; }
     496    string get_value() const { return value; }
     497    Xapian::valueno get_slot() const { return slot; }
     498    void next() {
     499        if (p == end) {
     500            p = NULL;
     501            return;
     502        }
     503        Xapian::docid delta;
     504        if (!unpack_uint(&p, end, &delta))
     505            throw Xapian::DatabaseCorruptError("Invalid docid delta in valuechunk");
     506        did += delta + 1;
     507        if (!unpack_string(&p, end, value))
     508            throw Xapian::DatabaseCorruptError("Invalid value in valuechunk");
     509    }
     510};
     511
     512class ValueChunkReaderGt {
     513  public:
     514    /** Return true if and only if a's id is strictly greater than b's id.
     515     */
     516    bool operator()(const ValueChunkReader *a, const ValueChunkReader *b) {
     517        return (a->get_docid() > b->get_docid());
     518    }
     519};
     520
     521static const size_t VALUE_CHUNK_SIZE_THRESHOLD = 2000;
     522
     523inline std::string
     524make_valuechunk_key(Xapian::valueno slot, Xapian::docid did)
     525{
     526    std::string key("\0\xd8", 2);
     527    pack_uint(key, slot);
     528    pack_uint_preserving_sort(key, did);
     529    return key;
     530}
     531
     532/// Build merged valuelist chunks
     533static void
     534rebuild_valuelist_chunks(ChertTable * out,
     535                         priority_queue<PostlistCursor *,
     536                                        vector<PostlistCursor *>,
     537                                        PostlistCursorGt> & pq)
     538{
     539    priority_queue<ValueChunkReader *,
     540                   vector<ValueChunkReader *>,
     541                   ValueChunkReaderGt> chunks;
     542    Xapian::valueno cur_slot = Xapian::valueno(-1);
     543    while (true) {
     544        PostlistCursor * cur = NULL;
     545        if (!pq.empty()) {
     546            cur = pq.top();
     547            if (is_valuechunk_key(cur->key)) {
     548                pq.pop();
     549            } else {
     550                cur = NULL;
     551            }
     552        }
     553
     554        Xapian::valueno new_slot = Xapian::valueno(-1);
     555        AutoPtr<ValueChunkReader> r;
     556        if (cur != NULL) {
     557            r = AutoPtr<ValueChunkReader>(new ValueChunkReader(cur->key, cur->tag));
     558            new_slot = r->get_slot();
     559        }
     560
     561        if (cur == NULL || new_slot != cur_slot) {
     562            if (!chunks.empty()) {
     563                string key, tag;
     564                Xapian::docid prev_docid(0);
     565                while (!chunks.empty()) {
     566                    AutoPtr<ValueChunkReader> reader(chunks.top());
     567                    chunks.pop();
     568                    if (tag.empty()) {
     569                        key = make_valuechunk_key(reader->get_slot(),
     570                                                  reader->get_docid());
     571                    } else {
     572                        pack_uint(tag, reader->get_docid() - prev_docid - 1);
     573                    }
     574                    prev_docid = reader->get_docid();
     575                    pack_string(tag, reader->get_value());
     576                    if (tag.size() >= VALUE_CHUNK_SIZE_THRESHOLD) {
     577                        out->add(key, tag);
     578                        tag.resize(0);
     579                    }
     580
     581                    reader->next();
     582                    if (!reader->at_end()) {
     583                        chunks.push(reader.release());
     584                    }
     585                }
     586                if (!tag.empty()) {
     587                    out->add(key, tag);
     588                    tag.resize(0);
     589                }
     590            }
     591            Assert(chunks.empty());
     592            if (cur == NULL) break;
     593        }
     594        cur_slot = new_slot;
     595
     596        chunks.push(r.release());
     597        if (cur->next()) {
     598            pq.push(cur);
     599        } else {
     600            delete cur;
     601        }
     602    }
     603
     604    while (!pq.empty()) {
     605        PostlistCursor * cur = pq.top();
     606        const string & key = cur->key;
     607        if (!is_valuechunk_key(key)) break;
     608        Assert(!is_user_metadata_key(key));
     609        out->add(key, cur->tag);
     610        pq.pop();
     611        if (cur->next()) {
     612            pq.push(cur);
     613        } else {
     614            delete cur;
     615        }
     616    }
     617}
     618
     619class XAPIAN_VISIBILITY_DEFAULT PostlistChunkReader {
     620    string chunk;
     621    const char *p;
     622    const char *end;
     623    Xapian::docid did;
     624    Xapian::termcount wdf;
     625  public:
     626    PostlistChunkReader(Xapian::docid firstdid, const string & chunk_)
     627            : chunk(chunk_), p(chunk.data()), end(p + chunk.size()),
     628              did(firstdid), wdf(0)
     629    {
     630        bool is_last_chunk;
     631        if (!unpack_bool(&p, end, &is_last_chunk))
     632            throw Xapian::DatabaseCorruptError(
     633                "Bad postlist chunk - no is_last_chunk bool");
     634        Xapian::docid increase_to_last;
     635        if (!unpack_uint(&p, end, &increase_to_last))
     636            throw Xapian::DatabaseCorruptError(
     637                "Bad postlist chunk - no increase_to_last");
     638
     639        if (!unpack_uint(&p, end, &wdf))
     640            throw Xapian::DatabaseCorruptError("Bad postlist chunk - no wdf");
     641    }
     642    bool at_end() const { return p == NULL; }
     643    Xapian::docid get_docid() const { return did; }
     644    Xapian::termcount get_wdf() const { return wdf; }
     645    void next() {
     646        if (p == end) {
     647            p = NULL;
     648            return;
     649        }
     650        Xapian::docid did_increase;
     651        if (!unpack_uint(&p, end, &did_increase))
     652            throw Xapian::DatabaseCorruptError(
     653                "Bad postlist chunk - no docid increase");
     654        did += did_increase + 1;
     655
     656        if (!unpack_uint(&p, end, &wdf))
     657            throw Xapian::DatabaseCorruptError(
     658                "Bad postlist chunk - no wdf");
     659    }
     660};
     661
     662class PostlistChunkReaderGt {
     663  public:
     664    /** Return true if and only if a's id is strictly greater than b's id.
     665     */
     666    bool operator()(const PostlistChunkReader *a, const PostlistChunkReader *b) {
     667        return (a->get_docid() > b->get_docid());
     668    }
     669};
     670
     671static const size_t POSTLIST_CHUNK_SIZE_THRESHOLD = 2000;
     672/// Build merged postlist chunks
     673static void
     674rebuild_postlist_chunks(ChertTable * out,
     675                        priority_queue<PostlistCursor *,
     676                                       vector<PostlistCursor *>,
     677                                       PostlistCursorGt> & pq)
     678{
     679    Xapian::termcount tf = 0, cf = 0;
     680    priority_queue<PostlistChunkReader *,
     681                   vector<PostlistChunkReader *>,
     682                   PostlistChunkReaderGt> tags;
     683    string last_key;
     684    while (true) {
     685        PostlistCursor * cur = NULL;
     686        if (!pq.empty()) {
     687            cur = pq.top();
     688            pq.pop();
     689        }
     690        Assert(cur == NULL || !is_user_metadata_key(cur->key));
     691        if (cur == NULL || cur->key != last_key) {
     692            if (!tags.empty()) {
     693                string term;
     694                if (!is_doclenchunk_key(last_key)) {
     695                    const char * p = last_key.data();
     696                    const char * end = p + last_key.size();
     697                    if (!unpack_string_preserving_sort(&p, end, term) || p != end)
     698                        throw Xapian::DatabaseCorruptError("Bad postlist chunk key");
     699                }
     700
     701                string key, tag, tagstart;
     702                Xapian::docid prevdocid = 0;
     703                bool firstkey = true;
     704                Xapian::docid firstdocid = 0;
     705                while (!tags.empty()) {
     706                    AutoPtr<PostlistChunkReader> reader(tags.top());
     707                    tags.pop();
     708                    if (reader->get_docid() == prevdocid)
     709                        throw Xapian::InvalidOperationError("Docid " + str(prevdocid) + " occurs in multiple input databases");
     710
     711                    if (tag.size() >=
     712                        POSTLIST_CHUNK_SIZE_THRESHOLD) {
     713                        pack_bool(tagstart, false); // not last chunk
     714                        pack_uint(tagstart, prevdocid - firstdocid);
     715                        out->add(key, tagstart + tag);
     716                        tag.resize(0);
     717                        tagstart.resize(0);
     718                    }
     719
     720                    if (tag.empty()) {
     721                        firstdocid = reader->get_docid();
     722                        if (firstkey) {
     723                            key = pack_chert_postlist_key(term);
     724                            pack_uint(tagstart, tf);
     725                            pack_uint(tagstart, cf);
     726                            pack_uint(tagstart, reader->get_docid() - 1);
     727                            firstkey = false;
     728                        } else {
     729                            key = pack_chert_postlist_key(term, reader->get_docid());
     730                        }
     731                    } else {
     732                        pack_uint(tag, reader->get_docid() - prevdocid - 1);
     733                    }
     734                    pack_uint(tag, reader->get_wdf());
     735
     736                    prevdocid = reader->get_docid();
     737                    reader->next();
     738                    if (!reader->at_end()) {
     739                        tags.push(reader.release());
     740                    }
     741                }
     742                if (!tag.empty()) {
     743                    pack_bool(tagstart, true); // last chunk
     744                    pack_uint(tagstart, prevdocid - firstdocid);
     745                    out->add(key, tagstart + tag);
     746                    tag.resize(0);
     747                }
     748            }
     749            Assert(tags.empty());
     750            if (cur == NULL) break;
     751            tf = cf = 0;
     752            last_key = cur->key;
     753        }
     754        tf += cur->tf;
     755        cf += cur->cf;
     756        tags.push(new PostlistChunkReader(cur->firstdid, cur->tag));
     757        if (cur->next()) {
     758            pq.push(cur);
     759        } else {
     760            delete cur;
     761        }
     762    }
     763}
     764
    434765struct MergeCursor : public ChertCursor {
    435766    MergeCursor(ChertTable *in) : ChertCursor(in) {
    436767        find_entry(string());
     
    7981129static void
    7991130multimerge_postlists(ChertTable * out, const char * tmpdir,
    8001131                     Xapian::docid tot_off,
    801                      vector<string> tmp, vector<Xapian::docid> off)
     1132                     vector<string> tmp, vector<Xapian::docid> off,
     1133                     bool rebuild_chunks)
    8021134{
    8031135    unsigned int c = 0;
    8041136    while (tmp.size() > 3) {
     
    8211153            // Use maximum blocksize for temporary tables.
    8221154            tmptab.create_and_open(65536);
    8231155
    824             merge_postlists(&tmptab, off.begin() + i, tmp.begin() + i, tmp.begin() + j, 0);
     1156            merge_postlists(&tmptab, off.begin() + i, tmp.begin() + i, tmp.begin() + j, 0,
     1157                            rebuild_chunks);
    8251158            if (c > 0) {
    8261159                for (unsigned int k = i; k < j; ++k) {
    8271160                    unlink((tmp[k] + "DB").c_str());
     
    8371170        swap(off, newoff);
    8381171        ++c;
    8391172    }
    840     merge_postlists(out, off.begin(), tmp.begin(), tmp.end(), tot_off);
     1173    merge_postlists(out, off.begin(), tmp.begin(), tmp.end(), tot_off,
     1174                    rebuild_chunks);
    8411175    if (c > 0) {
    8421176        for (size_t k = 0; k < tmp.size(); ++k) {
    8431177            unlink((tmp[k] + "DB").c_str());
     
    8981232compact_chert(const char * destdir, const vector<string> & sources,
    8991233              const vector<Xapian::docid> & offset, size_t block_size,
    9001234              compaction_level compaction, bool multipass,
    901               Xapian::docid tot_off) {
     1235              Xapian::docid tot_off, bool rebuild_chunks) {
    9021236    enum table_type {
    9031237        POSTLIST, RECORD, TERMLIST, POSITION, VALUE, SPELLING, SYNONYM
    9041238    };
     
    9991333            case POSTLIST:
    10001334                if (multipass && inputs.size() > 3) {
    10011335                    multimerge_postlists(&out, destdir, tot_off,
    1002                                          inputs, offset);
     1336                                         inputs, offset, rebuild_chunks);
    10031337                } else {
    10041338                    merge_postlists(&out, offset.begin(),
    10051339                                    inputs.begin(), inputs.end(),
    1006                                     tot_off);
     1340                                    tot_off, rebuild_chunks);
    10071341                }
    10081342                break;
    10091343            case SPELLING:
  • bin/xapian-compact-brass.cc

     
    898898compact_brass(const char * destdir, const vector<string> & sources,
    899899              const vector<Xapian::docid> & offset, size_t block_size,
    900900              compaction_level compaction, bool multipass,
    901               Xapian::docid tot_off) {
     901              Xapian::docid tot_off, bool rebuild_chunks) {
     902    if (rebuild_chunks) {
     903        throw "--rebuild-chunks is not currently supported for brass databases";
     904    }
    902905    enum table_type {
    903906        POSTLIST, RECORD, TERMLIST, POSITION, VALUE, SPELLING, SYNONYM
    904907    };
  • bin/xapian-compact-flint.cc

     
    720720compact_flint(const char * destdir, const vector<string> & sources,
    721721              const vector<Xapian::docid> & offset, size_t block_size,
    722722              compaction_level compaction, bool multipass,
    723               Xapian::docid tot_off) {
     723              Xapian::docid tot_off, bool rebuild_chunks) {
     724    if (rebuild_chunks) {
     725        throw "--rebuild-chunks is not currently supported for flint databases";
     726    }
    724727    enum table_type {
    725728        POSTLIST, RECORD, TERMLIST, POSITION, VALUE, SPELLING, SYNONYM
    726729    };