Пример #1
0
  public void set(E value) {

    if (dataObject == null) {
      throw new IllegalStateException();
    }
    if (!coll.hasValues()) {
      throw new UnsupportedOperationException();
    }
    DataCursor cursor = null;
    boolean doAutoCommit = coll.beginAutoCommit();
    try {
      cursor = new DataCursor(coll.view, writeAllowed);
      if (moveCursor(dataIndex, cursor)) {
        cursor.putCurrent(value);
        setSlot(dataIndex, cursor);
        coll.closeCursor(cursor);
        coll.commitAutoCommit(doAutoCommit);
      } else {
        throw new IllegalStateException();
      }
    } catch (Exception e) {
      coll.closeCursor(cursor);
      throw coll.handleException(e, doAutoCommit);
    }
  }
Пример #2
0
  /** Sets a given slot using the data in the given cursor. */
  private void setSlot(int i, DataCursor cursor) {

    keys[i] = KeyRange.getByteArray(cursor.getKeyThang());

    if (keys != priKeys) {
      priKeys[i] = KeyRange.getByteArray(cursor.getPrimaryKeyThang());
    }

    values[i] = KeyRange.getByteArray(cursor.getValueThang());
  }
Пример #3
0
  /**
   * Returns true if this set contains the specified element. This method conforms to the {@link
   * Set#contains} interface.
   *
   * @param mapEntry is a {@link java.util.Map.Entry} instance to be checked.
   * @return true if the key-value pair is present in the set, or false if the mapEntry is not a
   *     {@link java.util.Map.Entry} instance or is not present in the set.
   * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is thrown.
   */
  public boolean contains(Object mapEntry) {

    if (!(mapEntry instanceof Map.Entry)) {
      return false;
    }
    Map.Entry entry = (Map.Entry) mapEntry;
    DataCursor cursor = null;
    try {
      cursor = new DataCursor(view, false);
      OperationStatus status = cursor.findBoth(entry.getKey(), entry.getValue(), false);
      return (status == OperationStatus.SUCCESS);
    } catch (Exception e) {
      throw StoredContainer.convertException(e);
    } finally {
      closeCursor(cursor);
    }
  }
Пример #4
0
  /** Closes the given cursor if non-null. */
  private void closeCursor(DataCursor cursor) {

    if (cursor != null) {
      try {
        cursor.close();
      } catch (DatabaseException e) {
        throw StoredContainer.convertException(e);
      }
    }
  }
Пример #5
0
  public final boolean moveToIndex(int index) {

    DataCursor cursor = null;
    try {
      cursor = new DataCursor(coll.view, writeAllowed);
      OperationStatus status = cursor.getSearchKey(Integer.valueOf(index), null, false);
      if (status == OperationStatus.SUCCESS) {
        clearSlots();
        setSlot(0, cursor);
        nextIndex = 0;
        return true;
      } else {
        return false;
      }
    } catch (DatabaseException e) {
      throw StoredContainer.convertException(e);
    } finally {
      closeCursor(cursor);
    }
  }
Пример #6
0
  /** Returns the record number at the given slot position. */
  private int getRecordNumber(int i) {

    if (coll.view.btreeRecNumDb) {
      DataCursor cursor = null;
      try {
        cursor = new DataCursor(coll.view, false);
        if (moveCursor(i, cursor)) {
          return cursor.getCurrentRecordNumber();
        } else {
          throw new IllegalStateException();
        }
      } catch (DatabaseException e) {
        throw StoredContainer.convertException(e);
      } finally {
        closeCursor(cursor);
      }
    } else {
      DatabaseEntry entry = new DatabaseEntry(keys[i]);
      return DbCompat.getRecordNumber(entry);
    }
  }
Пример #7
0
  /** Clones a cursor preserving the current position. */
  DataCursor cloneCursor() throws DatabaseException {

    checkNoJoinCursor();

    DataCursor o;
    try {
      o = (DataCursor) super.clone();
    } catch (CloneNotSupportedException neverHappens) {
      return null;
    }

    o.initThangs();
    KeyRange.copy(keyThang, o.keyThang);
    KeyRange.copy(valueThang, o.valueThang);
    if (primaryKeyThang != keyThang) {
      KeyRange.copy(primaryKeyThang, o.primaryKeyThang);
    }

    o.cursor = cursor.dup(true);
    return o;
  }
Пример #8
0
  /**
   * Removes the specified element from this set if it is present (optional operation). This method
   * conforms to the {@link Set#remove} interface.
   *
   * @param mapEntry is a {@link java.util.Map.Entry} instance to be removed.
   * @return true if the key-value pair was removed from the set, or false if the mapEntry is not a
   *     {@link java.util.Map.Entry} instance or is not present in the set.
   * @throws UnsupportedOperationException if the collection is read-only.
   * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is thrown.
   */
  public boolean remove(Object mapEntry) {

    if (!(mapEntry instanceof Map.Entry)) {
      return false;
    }
    Map.Entry entry = (Map.Entry) mapEntry;
    DataCursor cursor = null;
    boolean doAutoCommit = beginAutoCommit();
    try {
      cursor = new DataCursor(view, true);
      OperationStatus status = cursor.findBoth(entry.getKey(), entry.getValue(), true);
      if (status == OperationStatus.SUCCESS) {
        cursor.delete();
      }
      closeCursor(cursor);
      commitAutoCommit(doAutoCommit);
      return (status == OperationStatus.SUCCESS);
    } catch (Exception e) {
      closeCursor(cursor);
      throw handleException(e, doAutoCommit);
    }
  }
Пример #9
0
  public void add(E value) {

    /*
     * The checkIterAddAllowed method ensures that one of the following two
     * conditions holds and throws UnsupportedOperationException otherwise:
     * 1- This is a list iterator for a recno-renumber database.
     * 2- This is a collection iterator for a duplicates database.
     */
    coll.checkIterAddAllowed();
    OperationStatus status = OperationStatus.SUCCESS;
    DataCursor cursor = null;
    boolean doAutoCommit = coll.beginAutoCommit();
    try {
      if (coll.view.keysRenumbered || !coll.areDuplicatesOrdered()) {

        /*
         * This is a recno-renumber database or a btree/hash database
         * with unordered duplicates.
         */
        boolean hasPrev = hasPrevious();
        if (!hasPrev && !hasNext()) {

          /* The collection is empty. */
          if (coll.view.keysRenumbered) {

            /* Append to an empty recno-renumber database. */
            status = coll.view.append(value, null, null);

          } else if (coll.view.dupsAllowed && coll.view.range.isSingleKey()) {

            /*
             * When inserting a duplicate into a single-key range,
             * the main key is fixed, so we can always insert into
             * an empty collection.
             */
            cursor = new DataCursor(coll.view, writeAllowed);
            cursor.useRangeKey();
            status = cursor.putNoDupData(null, value, null, true);
            coll.closeCursor(cursor);
            cursor = null;
          } else {
            throw new IllegalStateException("Collection is empty, cannot add() duplicate");
          }

          /*
           * Move past the record just inserted (the cursor should be
           * closed above to prevent multiple open cursors in certain
           * DB core modes).
           */
          if (status == OperationStatus.SUCCESS) {
            next();
            dataIndex = nextIndex - 1;
          }
        } else {

          /*
           * The collection is non-empty.  If hasPrev is true then
           * the element at (nextIndex - 1) is available; otherwise
           * the element at nextIndex is available.
           */
          cursor = new DataCursor(coll.view, writeAllowed);
          int insertIndex = hasPrev ? (nextIndex - 1) : nextIndex;

          if (!moveCursor(insertIndex, cursor)) {
            throw new IllegalStateException();
          }

          /*
           * For a recno-renumber database or a database with
           * unsorted duplicates, insert before the iterator 'next'
           * position, or after the 'prev' position.  Then adjust
           * the slots to account for the inserted record.
           */
          status = hasPrev ? cursor.putAfter(value) : cursor.putBefore(value);
          if (status == OperationStatus.SUCCESS) {
            insertSlot(nextIndex, cursor);
          }
        }
      } else {
        /* This is a btree/hash database with ordered duplicates. */
        cursor = new DataCursor(coll.view, writeAllowed);

        if (coll.view.range.isSingleKey()) {

          /*
           * When inserting a duplicate into a single-key range,
           * the main key is fixed.
           */
          cursor.useRangeKey();
        } else {

          /*
           * When inserting into a multi-key range, the main key
           * is the last dataIndex accessed by next(), previous()
           * or add().
           */
          if (dataIndex < 0 || !moveCursor(dataIndex, cursor)) {
            throw new IllegalStateException();
          }
        }

        /*
         * For a hash/btree with duplicates, insert the duplicate,
         * put the new record in slot zero, and set the next index
         * to slot one (past the new record).
         */
        status = cursor.putNoDupData(null, value, null, true);
        if (status == OperationStatus.SUCCESS) {
          clearSlots();
          setSlot(0, cursor);
          dataIndex = 0;
          nextIndex = 1;
        }
      }

      if (status == OperationStatus.KEYEXIST) {
        throw new IllegalArgumentException("Duplicate value");
      } else if (status != OperationStatus.SUCCESS) {
        throw new IllegalArgumentException("Could not insert: " + status);
      }

      /* Prevent subsequent set() or remove() call. */
      dataObject = null;

      coll.closeCursor(cursor);
      coll.commitAutoCommit(doAutoCommit);
    } catch (Exception e) {
      /* Catch RuntimeExceptions too. */
      coll.closeCursor(cursor);
      throw coll.handleException(e, doAutoCommit);
    }
  }
Пример #10
0
  public void remove() {

    if (dataObject == null) {
      throw new IllegalStateException();
    }
    DataCursor cursor = null;
    boolean doAutoCommit = coll.beginAutoCommit();
    try {
      cursor = new DataCursor(coll.view, writeAllowed);
      if (moveCursor(dataIndex, cursor)) {
        cursor.delete();
        deleteSlot(dataIndex);
        dataObject = null;

        /*
         * Repopulate the block after removing all records, using the
         * cursor position of the deleted record as a starting point.
         * First try moving forward, since the user was moving forward.
         * (It is possible to delete all records in the block only by
         * moving forward, i.e, when nextIndex is greater than
         * dataIndex.)
         */
        if (nextIndex == 0 && keys[0] == null) {
          OperationStatus status;
          for (int i = 0; i < keys.length; i += 1) {
            status = coll.iterateDuplicates() ? cursor.getNext(false) : cursor.getNextNoDup(false);
            if (status == OperationStatus.SUCCESS) {
              setSlot(i, cursor);
            } else {
              break;
            }
          }

          /*
           * If no records are found past the cursor position, try
           * moving backward.  If no records are found before the
           * cursor position, leave nextIndex set to keys.length,
           * which is the same as the initial iterator state and is
           * appropriate for an empty key range.
           */
          if (keys[0] == null) {
            nextIndex = keys.length;
            for (int i = nextIndex - 1; i >= 0; i -= 1) {
              status =
                  coll.iterateDuplicates() ? cursor.getPrev(false) : cursor.getPrevNoDup(false);
              if (status == OperationStatus.SUCCESS) {
                setSlot(i, cursor);
              } else {
                break;
              }
            }
          }
        }
        coll.closeCursor(cursor);
        coll.commitAutoCommit(doAutoCommit);
      } else {
        throw new IllegalStateException();
      }
    } catch (Exception e) {
      coll.closeCursor(cursor);
      throw coll.handleException(e, doAutoCommit);
    }
  }
Пример #11
0
  public boolean hasPrevious() {

    if (isPrevAvailable()) {
      return true;
    }
    if (!isNextAvailable()) {
      return false;
    }
    DataCursor cursor = null;
    try {
      cursor = new DataCursor(coll.view, writeAllowed);
      int last = keys.length - 1;
      int next = nextIndex;
      boolean found = false;

      /* Reposition to the last known key/data pair. */
      int repos = cursor.repositionRange(keys[next], priKeys[next], values[next], false);

      if (repos == DataCursor.REPOS_EXACT || repos == DataCursor.REPOS_NEXT) {

        /*
         * The last known key/data pair, or the record following it,
         * was found and will now be in the last slot.
         */
        found = true;
        nextIndex = last;

        /* The data object is now in the last slot or not available. */
        if (dataIndex == next && repos == DataCursor.REPOS_EXACT) {
          dataIndex = last;
        } else {
          dataIndex = -1;
          dataObject = null;
        }
      } else {
        if (repos != DataCursor.REPOS_EOF) {
          throw new IllegalStateException();
        }
      }

      if (found) {
        /* Clear all slots first in case an exception occurs below. */
        clearSlots();

        /* Attempt to fill all slots with records. */
        int i = last;
        boolean done = false;
        while (!done) {
          setSlot(i, cursor);
          i -= 1;
          if (i >= 0) {
            OperationStatus status =
                coll.iterateDuplicates() ? cursor.getPrev(false) : cursor.getPrevNoDup(false);
            if (status != OperationStatus.SUCCESS) {
              done = true;
            }
          } else {
            done = true;
          }
        }
      }

      /*
       * Make sure we retrieved the preceding record after the reposition
       * above.
       */
      return isPrevAvailable();
    } catch (DatabaseException e) {
      throw StoredContainer.convertException(e);
    } finally {
      closeCursor(cursor);
    }
  }
Пример #12
0
  public boolean hasNext() {

    if (isNextAvailable()) {
      return true;
    }
    DataCursor cursor = null;
    try {
      cursor = new DataCursor(coll.view, writeAllowed);
      int prev = nextIndex - 1;
      boolean found = false;

      if (keys[prev] == null) {
        /* Get the first record for an uninitialized iterator. */
        OperationStatus status = cursor.getFirst(false);
        if (status == OperationStatus.SUCCESS) {
          found = true;
          nextIndex = 0;
        }
      } else {
        /* Reposition to the last known key/data pair. */
        int repos = cursor.repositionRange(keys[prev], priKeys[prev], values[prev], false);

        if (repos == DataCursor.REPOS_EXACT) {

          /*
           * The last known key/data pair was found and will now be
           * in slot zero.
           */
          found = true;
          nextIndex = 1;

          /* The data object is now in slot zero or not available. */
          if (dataIndex == prev) {
            dataIndex = 0;
          } else {
            dataIndex = -1;
            dataObject = null;
          }
        } else if (repos == DataCursor.REPOS_NEXT) {

          /*
           * The last known key/data pair was not found, but the
           * following record was found and it will be in slot zero.
           */
          found = true;
          nextIndex = 0;

          /* The data object is no longer available. */
          dataIndex = -1;
          dataObject = null;
        } else {
          if (repos != DataCursor.REPOS_EOF) {
            throw new IllegalStateException();
          }
        }
      }

      if (found) {
        /* Clear all slots first in case an exception occurs below. */
        clearSlots();

        /* Attempt to fill all slots with records. */
        int i = 0;
        boolean done = false;
        while (!done) {
          setSlot(i, cursor);
          i += 1;
          if (i < keys.length) {
            OperationStatus status =
                coll.iterateDuplicates() ? cursor.getNext(false) : cursor.getNextNoDup(false);
            if (status != OperationStatus.SUCCESS) {
              done = true;
            }
          } else {
            done = true;
          }
        }
      }

      /*
       * If REPOS_EXACT was returned above, make sure we retrieved
       * the following record.
       */
      return isNextAvailable();
    } catch (DatabaseException e) {
      throw StoredContainer.convertException(e);
    } finally {
      closeCursor(cursor);
    }
  }
Пример #13
0
  /**
   * Moves the cursor to the key/data at the given slot, and returns false if the reposition
   * (search) fails.
   */
  private boolean moveCursor(int i, DataCursor cursor) throws DatabaseException {

    return cursor.repositionExact(keys[i], priKeys[i], values[i], false);
  }