Ticket #250: patch_kan_ru_2.patch

File patch_kan_ru_2.patch, 7.9 KB (added by Richard Boulton, 15 years ago)

Slightly refactored version of the Kan-Ru's patch

  • backends/flint/flint_database.cc

     
    55 * Copyright 2002 Ananova Ltd
    66 * Copyright 2002,2003,2004,2005,2006,2007,2008,2009 Olly Betts
    77 * Copyright 2006,2008 Lemur Consulting Ltd
     8 * Copyright 2009 Kan-Ru Chen
    89 *
    910 * This program is free software; you can redistribute it and/or
    1011 * modify it under the terms of the GNU General Public License as
     
    12411242    }
    12421243}
    12431244
     1245/** Compare the positionlists for a term iterator and a termlist.
     1246 *
     1247 *  @return true if they're equal, false otherwise.
     1248 */
     1249static bool positionlists_equal(Xapian::TermIterator & termiter,
     1250                                FlintTermList & termlist)
     1251{
     1252    int new_count = termiter.positionlist_count();
     1253    int old_count = termlist.positionlist_count();
     1254    if (old_count != new_count)
     1255        return false;
     1256
     1257    PositionIterator it = termiter.positionlist_begin();
     1258    PositionIterator it_end = termiter.positionlist_end();
     1259    PositionIterator old = termlist.positionlist_begin();
     1260    return equal(it, it_end, old);
     1261}
     1262
    12441263void
    12451264FlintWritableDatabase::replace_document(Xapian::docid did,
    12461265                                        const Xapian::Document & document)
     
    12781297        }
    12791298 
    12801299        if (!modifying || document.internal->terms_modified()) {
    1281             // FIXME - in the case where there is overlap between the new
    1282             // termlist and the old termlist, it would be better to compare the
    1283             // two lists, and make the minimum set of modifications required.
    1284             // This would lead to smaller changesets for replication, and
    1285             // probably be faster overall.
    1286 
    1287             // First, add entries to remove the postings in the underlying record.
    12881300            Xapian::Internal::RefCntPtr<const FlintWritableDatabase> ptrtothis(this);
    12891301            FlintTermList termlist(ptrtothis, did);
     1302            Xapian::TermIterator term = document.termlist_begin();
     1303            Xapian::TermIterator term_end = document.termlist_end();
     1304            flint_doclen_t new_doclen = termlist.get_doclength();
     1305            string old_tname, new_tname;
    12901306
     1307            total_length -= new_doclen;
     1308
    12911309            termlist.next();
    1292             while (!termlist.at_end()) {
    1293                 string tname = termlist.get_termname();
    1294                 termcount wdf = termlist.get_wdf();
     1310            while (!termlist.at_end() || term != term_end) {
     1311                int cmp;
     1312                if (!termlist.at_end() && term != term_end) {
     1313                    old_tname = termlist.get_termname();
     1314                    new_tname = *term;
     1315                    cmp = old_tname.compare(new_tname);
    12951316
    1296                 map<string, pair<termcount_diff, termcount_diff> >::iterator i;
    1297                 i = freq_deltas.find(tname);
    1298                 if (i == freq_deltas.end()) {
    1299                     freq_deltas.insert(make_pair(tname, make_pair(-1, -termcount_diff(wdf))));
     1317                } else if (termlist.at_end()) {
     1318                    cmp = 1;
     1319                    new_tname = *term;
    13001320                } else {
    1301                     --i->second.first;
    1302                     i->second.second -= wdf;
     1321                    cmp = -1;
     1322                    old_tname = termlist.get_termname();
    13031323                }
    13041324
    1305                 // Remove did from tname's postlist
    1306                 map<string, map<docid, pair<char, termcount> > >::iterator j;
    1307                 j = mod_plists.find(tname);
    1308                 if (j == mod_plists.end()) {
    1309                     map<docid, pair<char, termcount> > m;
    1310                     j = mod_plists.insert(make_pair(tname, m)).first;
    1311                 }
     1325                if (cmp < 0) {
     1326                    const string& tname = old_tname;
     1327                    termcount wdf = termlist.get_wdf();
     1328                    new_doclen -= wdf;
    13121329
    1313                 map<docid, pair<char, termcount> >::iterator k;
    1314                 k = j->second.find(did);
    1315                 if (k == j->second.end()) {
    1316                     j->second.insert(make_pair(did, make_pair('D', 0u)));
    1317                 } else {
    1318                     // Modifying a document we added/modified since the last flush.
    1319                     k->second = make_pair('D', 0u);
    1320                 }
     1330                    map<string, pair<termcount_diff, termcount_diff> >::iterator i;
     1331                    i = freq_deltas.find(tname);
     1332                    if (i == freq_deltas.end()) {
     1333                        freq_deltas.insert(make_pair(tname, make_pair(-1, -termcount_diff(wdf))));
     1334                    } else {
     1335                        --i->second.first;
     1336                        i->second.second -= wdf;
     1337                    }
    13211338
    1322                 termlist.next();
    1323             }
     1339                    // Remove did from tname's postlist
     1340                    map<string, map<docid, pair<char, termcount> > >::iterator j;
     1341                    j = mod_plists.find(tname);
     1342                    if (j == mod_plists.end()) {
     1343                        map<docid, pair<char, termcount> > m;
     1344                        j = mod_plists.insert(make_pair(tname, m)).first;
     1345                    }
    13241346
    1325             total_length -= termlist.get_doclength();
     1347                    map<docid, pair<char, termcount> >::iterator k;
     1348                    k = j->second.find(did);
     1349                    if (k == j->second.end()) {
     1350                        j->second.insert(make_pair(did, make_pair('D', 0u)));
     1351                    } else {
     1352                        // Modifying a document we added/modified since the last flush.
     1353                        k->second = make_pair('D', 0u);
     1354                    }
     1355                } else if (cmp != 0 || !positionlists_equal(term, termlist)) {
     1356                    const string& tname = new_tname;
     1357                    termcount wdf = term.get_wdf();
     1358                    new_doclen += wdf;
    13261359
    1327             flint_doclen_t new_doclen = 0;
    1328             Xapian::TermIterator term = document.termlist_begin();
    1329             Xapian::TermIterator term_end = document.termlist_end();
    1330             for ( ; term != term_end; ++term) {
    1331                 // Calculate the new document length
    1332                 termcount wdf = term.get_wdf();
    1333                 new_doclen += wdf;
     1360                    if (cmp > 0) {
     1361                        if (tname.size() > MAX_SAFE_TERM_LENGTH)
     1362                            throw Xapian::InvalidArgumentError("Term too long (> "STRINGIZE(MAX_SAFE_TERM_LENGTH)"): " + tname);
     1363                        map<string, pair<termcount_diff, termcount_diff> >::iterator i;
     1364                        i = freq_deltas.find(tname);
     1365                        if (i == freq_deltas.end()) {
     1366                            freq_deltas.insert(make_pair(tname, make_pair(1, termcount_diff(wdf))));
     1367                        } else {
     1368                            ++i->second.first;
     1369                            i->second.second += wdf;
     1370                        }
    13341371
    1335                 string tname = *term;
    1336                 if (tname.size() > MAX_SAFE_TERM_LENGTH)
    1337                     throw Xapian::InvalidArgumentError("Term too long (> "STRINGIZE(MAX_SAFE_TERM_LENGTH)"): " + tname);
    1338                 map<string, pair<termcount_diff, termcount_diff> >::iterator i;
    1339                 i = freq_deltas.find(tname);
    1340                 if (i == freq_deltas.end()) {
    1341                     freq_deltas.insert(make_pair(tname, make_pair(1, termcount_diff(wdf))));
    1342                 } else {
    1343                     ++i->second.first;
    1344                     i->second.second += wdf;
    1345                 }
     1372                        // Add did to tname's postlist
     1373                        map<string, map<docid, pair<char, termcount> > >::iterator j;
     1374                        j = mod_plists.find(tname);
     1375                        if (j == mod_plists.end()) {
     1376                            map<docid, pair<char, termcount> > m;
     1377                            j = mod_plists.insert(make_pair(tname, m)).first;
     1378                        }
     1379                        map<docid, pair<char, termcount> >::iterator k;
     1380                        k = j->second.find(did);
     1381                        if (k != j->second.end()) {
     1382                            Assert(k->second.first == 'D');
     1383                            k->second.first = 'M';
     1384                            k->second.second = wdf;
     1385                        } else {
     1386                            j->second.insert(make_pair(did, make_pair('A', wdf)));
     1387                        }
     1388                    }
    13461389
    1347                 // Add did to tname's postlist
    1348                 map<string, map<docid, pair<char, termcount> > >::iterator j;
    1349                 j = mod_plists.find(tname);
    1350                 if (j == mod_plists.end()) {
    1351                     map<docid, pair<char, termcount> > m;
    1352                     j = mod_plists.insert(make_pair(tname, m)).first;
     1390                    PositionIterator it = term.positionlist_begin();
     1391                    PositionIterator it_end = term.positionlist_end();
     1392                    if (it != it_end) {
     1393                        position_table.set_positionlist(
     1394                                                        did, tname, it, it_end);
     1395                    } else {
     1396                        position_table.delete_positionlist(did, tname);
     1397                    }
    13531398                }
    1354                 map<docid, pair<char, termcount> >::iterator k;
    1355                 k = j->second.find(did);
    1356                 if (k != j->second.end()) {
    1357                     Assert(k->second.first == 'D');
    1358                     k->second.first = 'M';
    1359                     k->second.second = wdf;
    1360                 } else {
    1361                     j->second.insert(make_pair(did, make_pair('A', wdf)));
     1399                if (termlist.at_end())
     1400                    ++term;
     1401                else if (term == term_end)
     1402                    termlist.next();
     1403                else {
     1404                    if (cmp >= 0)
     1405                        ++term;
     1406                    if (cmp <= 0)
     1407                        termlist.next();
    13621408                }
     1409            }
    13631410
    1364                 PositionIterator it = term.positionlist_begin();
    1365                 PositionIterator it_end = term.positionlist_end();
    1366                 if (it != it_end) {
    1367                     position_table.set_positionlist(
    1368                         did, tname, it, it_end);
    1369                 } else {
    1370                     position_table.delete_positionlist(did, tname);
    1371                 }
    1372             }
    13731411            LOGLINE(DB, "Calculated doclen for replacement document " << did << " as " << new_doclen);
    13741412
    13751413            // Set the termlist