Logo Search packages:      
Sourcecode: xapian-core version File versions  Download package

void QuartzWritableDatabase::replace_document ( Xapian::docid  did,
const Xapian::Document document 
) [private, virtual]

Replace a given document in the database.

See WritableDatabase::replace_document() for more information.

Reimplemented from Xapian::Database::Internal.

Definition at line 885 of file quartz_database.cc.

References QuartzTermList::at_end(), cancel(), changes_made, database_ro, doclens, freq_deltas, Xapian::Document::get_data(), get_doccount(), QuartzTermList::get_doclength(), QuartzTermList::get_termname(), Xapian::ValueIterator::get_valueno(), Xapian::TermIterator::get_wdf(), QuartzTermList::get_wdf(), lastdocid, mod_plists, QuartzTermList::next(), Xapian::TermIterator::positionlist_begin(), Xapian::TermIterator::positionlist_end(), QuartzDatabase::positionlist_table, QuartzDatabase::record_table, QuartzRecordTable::replace_record(), Xapian::Document::termlist_begin(), Xapian::Document::termlist_end(), QuartzDatabase::termlist_table, total_length, QuartzDatabase::value_table, Xapian::Document::values_begin(), and Xapian::Document::values_end().

{
    DEBUGCALL(DB, void, "QuartzWritableDatabase::replace_document", did << ", " << document);
    Assert(did != 0);

    try {
      if (did > lastdocid) {
          lastdocid = did;
          // If this docid is above the highwatermark, then we can't be
          // replacing an existing document.
          (void)add_document_(did, document);
          return;
      }

      // OK, now add entries to remove the postings in the underlying record.
      Xapian::Internal::RefCntPtr<const QuartzWritableDatabase> ptrtothis(this);
      QuartzTermList termlist(ptrtothis,
                        &database_ro.termlist_table,
                        did, get_doccount());

      termlist.next();
      while (!termlist.at_end()) {
          string tname = termlist.get_termname();
          termcount wdf = termlist.get_wdf();

          map<string, pair<termcount_diff, termcount_diff> >::iterator i;
          i = freq_deltas.find(tname);
          if (i == freq_deltas.end()) {
            freq_deltas.insert(make_pair(tname, make_pair(-1, -termcount_diff(wdf))));
          } else {
            --i->second.first;
            i->second.second -= wdf;
          }

          // Remove did from tname's postlist
          map<string, map<docid, pair<char, termcount> > >::iterator j;
          j = mod_plists.find(tname);
          if (j == mod_plists.end()) {
            map<docid, pair<char, termcount> > m;
            j = mod_plists.insert(make_pair(tname, m)).first;
          }

          map<docid, pair<char, termcount> >::iterator k;
          k = j->second.find(did);
          if (k == j->second.end()) {
            j->second.insert(make_pair(did, make_pair('D', 0u)));
          } else {
            // Modifying a document we added/modified since the last flush.
            k->second = make_pair('D', 0u);
          }

          termlist.next();
      }

      total_length -= termlist.get_doclength();

      // Replace the record
      database_ro.record_table.replace_record(document.get_data(), did);

      // FIXME: we read the values delete them and then replace in case
      // they come from where they're going!  Better to ask Document
      // nicely and shortcut in this case!
      {
          list<pair<string, Xapian::valueno> > tmp;
          Xapian::ValueIterator value = document.values_begin();
          Xapian::ValueIterator value_end = document.values_end();
          for ( ; value != value_end; ++value) {
            tmp.push_back(make_pair(*value, value.get_valueno()));
          }
//        database_ro.value_table.add_value(*value, did, value.get_valueno());

          // Replace the values.
          database_ro.value_table.delete_all_values(did);

          // Set the values.
          list<pair<string, Xapian::valueno> >::const_iterator i;
          for (i = tmp.begin(); i != tmp.end(); ++i) {
            database_ro.value_table.add_value(i->first, did, i->second);
          }
      }

      quartz_doclen_t new_doclen = 0;
      {
          Xapian::TermIterator term = document.termlist_begin();
          Xapian::TermIterator term_end = document.termlist_end();
          for ( ; term != term_end; ++term) {
            // Calculate the new document length
            termcount wdf = term.get_wdf();
            new_doclen += wdf;

            string tname = *term;
            map<string, pair<termcount_diff, termcount_diff> >::iterator i;
            i = freq_deltas.find(tname);
            if (i == freq_deltas.end()) {
                freq_deltas.insert(make_pair(tname, make_pair(1, termcount_diff(wdf))));
            } else {
                ++i->second.first;
                i->second.second += wdf;
            }

            // Add did to tname's postlist
            map<string, map<docid, pair<char, termcount> > >::iterator j;
            j = mod_plists.find(tname);
            if (j == mod_plists.end()) {
                map<docid, pair<char, termcount> > m;
                j = mod_plists.insert(make_pair(tname, m)).first;
            }
            map<docid, pair<char, termcount> >::iterator k;
            k = j->second.find(did);
            if (k != j->second.end()) {
                Assert(k->second.first == 'D');
                k->second.first = 'M';
                k->second.second = wdf;
            } else {
                j->second.insert(make_pair(did, make_pair('A', wdf)));
            }

            // FIXME : this might not work if we replace a positionlist
            // with itself (e.g. if a document is replaced with itself
            // with just the values changed)
            database_ro.positionlist_table.delete_positionlist(did, tname);
            if (term.positionlist_begin() != term.positionlist_end()) {
                database_ro.positionlist_table.set_positionlist(
                  did, tname,
                  term.positionlist_begin(), term.positionlist_end());
            }
          }
      }

      // Set the termlist
      database_ro.termlist_table.set_entries(did,
            document.termlist_begin(), document.termlist_end(),
            new_doclen, false);

      // Set the new document length
      doclens.insert(make_pair(did, new_doclen));
      total_length += new_doclen;
    } catch (const Xapian::DocNotFoundError &) {
      (void)add_document_(did, document);
      return;
    } catch (...) {
      // If an error occurs while replacing a document, or doing any other
      // transaction, the modifications so far must be cleared before
      // returning control to the user - otherwise partial modifications will
      // persist in memory, and eventually get written to disk.
      cancel();
      throw;
    }

    if (++changes_made >= flush_threshold && !transaction_active())
      do_flush_const();
}


Generated by  Doxygen 1.6.0   Back to index