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

bool FlintTable::add ( const string &  key,
string  tag 
)

Add a key/tag pair to the table, replacing any existing pair with the same key.

If an error occurs during the operation, this will be signalled by a return value of false. All modifications since the previous commit() will be lost.

If key is empty, then the null item is replaced. If key.length() exceeds the the limit on key size, false is returned.

e.g. ok = btree.add("TODAY", "Mon 9 Oct 2000");

Parameters:
key The key to store in the table.
tag The tag to store in the table.
Returns:
true if the operation completed successfully, false otherwise.

Definition at line 1038 of file flint_table.cc.

References add_kt(), block_size, Btree_modified, find(), full_compaction, item_count, kt, max_item_size, and writable.

Referenced by PostlistChunkWriter::flush().

{
    DEBUGCALL(DB, bool, "FlintTable::add", key << ", " << tag);
    Assert(writable);

    if (key.size() > FLINT_BTREE_MAX_KEY_LEN) {
      throw Xapian::InvalidArgumentError(
            "Key_ too long: length was " +
            om_tostring(key.size()) +
            " bytes, maximum length of a key is " +
            STRINGIZE(FLINT_BTREE_MAX_KEY_LEN) + " bytes");
    }

    form_key(key);

    // sort of matching kt.append_chunk(), but setting the chunk
    const size_t cd = kt.key().length() + K1 + I2 + C2 + C2;  // offset to the tag data
    const size_t L = max_item_size - cd; // largest amount of tag data for any chunk
    size_t first_L = L;                  // - amount for tag1
    bool found = find(C);
    if (!found) {
      byte * p = C[0].p;
      size_t n = TOTAL_FREE(p) % (max_item_size + D2);
      if (n > D2 + cd) {
          n -= (D2 + cd);
          // if n >= last then fully filling this block won't produce
          // an extra item, so we might as well do this even if
          // full_compaction isn't active.
          //
          // In the full_compaction case, it turns out we shouldn't always
          // try to fill every last byte.  Doing so can actually increase the
          // total space required (I believe this effect is due to longer
          // dividing keys being required in the index blocks).  Empirically,
          // n >= key.size() + K appears a good criterion for K ~= 34.  This
          // seems to save about 0.2% in total database size over always
          // splitting the tag.  It'll also give be slightly faster retrieval
          // as we can avoid reading an extra block occasionally.
          size_t last = tag.length() % L;
          if (n >= last || (full_compaction && n >= key.size() + 34))
            first_L = n;
      }
    }

    // a null tag must be added in of course
    int m = tag.empty() ? 1 : (tag.length() - first_L + L - 1) / L + 1;
                              // there are m items to add
    /* FIXME: sort out this error higher up and turn this into
     * an assert.
     */
    if (m >= BYTE_PAIR_RANGE) RETURN(false);

    int n = 0; // initialise to shut off warning
                              // - and there will be n to delete
    int o = 0;                        // Offset into the tag
    size_t residue = tag.length();    // Bytes of the tag remaining to add in
    int replacement = false;          // Has there been a replacement ?
    int i;
    kt.set_components_of(m);
    for (i = 1; i <= m; i++) {
      size_t l = (i == m ? residue : (i == 1 ? first_L : L));
      Assert(cd + l <= block_size);
      Assert(string::size_type(o + l) <= tag.length());
      kt.set_tag(cd, tag.data() + o, l);
      kt.set_component_of(i);
      
      o += l;
      residue -= l;

      if (i > 1) found = find(C);
      n = add_kt(found);
      if (n > 0) replacement = true;
    }
    /* o == tag.length() here, and n may be zero */
    for (i = m + 1; i <= n; i++) {
      kt.set_component_of(i);
      delete_kt();
    }
    if (!replacement) ++item_count;
    Btree_modified = true;
    RETURN(true);
}


Generated by  Doxygen 1.6.0   Back to index