Ticket #250: patch_kan_ru_2.patch

File patch_kan_ru_2.patch, 7.9 KB (added by richard, 8 months 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