예제 #1
0
  public void remove(OIdentifiable identifiable) {
    if (removeFromNewEntries(identifiable)) {
      if (size >= 0) size--;
    } else {
      final Change counter = changes.get(identifiable);
      if (counter == null) {
        // Not persistent keys can only be in changes or newEntries
        if (identifiable.getIdentity().isPersistent()) {
          changes.put(identifiable, new DiffChange(-1));
          size = -1;
        } else
          // Return immediately to prevent firing of event
          return;
      } else {
        counter.decrement();

        if (size >= 0)
          if (counter.isUndefined()) size = -1;
          else size--;
      }
    }

    if (this.owner != null) ORecordInternal.unTrack(this.owner, identifiable);

    if (updateOwner)
      fireCollectionChangedEvent(
          new OMultiValueChangeEvent<OIdentifiable, OIdentifiable>(
              OMultiValueChangeEvent.OChangeType.REMOVE, identifiable, null, identifiable, false));
  }
예제 #2
0
  public void add(final OIdentifiable identifiable) {
    if (identifiable == null)
      throw new NullPointerException("Impossible to add a null identifiable in a ridbag");
    if (identifiable.getIdentity().isValid()) {
      Change counter = changes.get(identifiable);
      if (counter == null) changes.put(identifiable, new DiffChange(1));
      else {
        if (counter.isUndefined()) {
          counter = getAbsoluteValue(identifiable);
          changes.put(identifiable, counter);
        }
        counter.increment();
      }
    } else {
      final OModifiableInteger counter = newEntries.get(identifiable);
      if (counter == null) newEntries.put(identifiable, new OModifiableInteger(1));
      else counter.increment();
    }

    if (size >= 0) size++;

    if (this.owner != null) ORecordInternal.track(this.owner, identifiable);

    if (updateOwner)
      fireCollectionChangedEvent(
          new OMultiValueChangeEvent<OIdentifiable, OIdentifiable>(
              OMultiValueChangeEvent.OChangeType.ADD, identifiable, identifiable, null, false));
  }
예제 #3
0
  private Map.Entry<OIdentifiable, Integer> nextChangedNotRemovedSBTreeEntry(
      Iterator<Map.Entry<OIdentifiable, Integer>> iterator) {
    while (iterator.hasNext()) {
      final Map.Entry<OIdentifiable, Integer> entry = iterator.next();
      final Change change = changes.get(entry.getKey());
      if (change == null) return entry;

      final int newValue = change.applyTo(entry.getValue());

      if (newValue > 0)
        return new Map.Entry<OIdentifiable, Integer>() {
          @Override
          public OIdentifiable getKey() {
            return entry.getKey();
          }

          @Override
          public Integer getValue() {
            return newValue;
          }

          @Override
          public Integer setValue(Integer value) {
            throw new UnsupportedOperationException();
          }
        };
    }

    return null;
  }
예제 #4
0
  private AbsoluteChange getAbsoluteValue(OIdentifiable identifiable) {
    final OSBTreeBonsai<OIdentifiable, Integer> tree = loadTree();
    try {
      Integer oldValue;

      if (tree == null) oldValue = 0;
      else oldValue = tree.get(identifiable);

      if (oldValue == null) oldValue = 0;

      final Change change = changes.get(identifiable);

      return new AbsoluteChange(change == null ? oldValue : change.applyTo(oldValue));
    } finally {
      releaseTree();
    }
  }
예제 #5
0
    @Override
    public void remove() {
      if (currentRemoved)
        throw new IllegalStateException("Current element has already been removed");

      if (currentValue == null)
        throw new IllegalStateException("Next method was not called for given iterator");

      if (removeFromNewEntries(currentValue)) {
        if (size >= 0) size--;
      } else {
        Change counter = changedValues.get(currentValue);
        if (counter != null) {
          counter.decrement();
          if (size >= 0)
            if (counter.isUndefined()) size = -1;
            else size--;
        } else {
          if (nextChange != null) {
            changedValues.put(currentValue, new DiffChange(-1));
            changedValuesIterator =
                changedValues.tailMap(nextChange.getKey(), false).entrySet().iterator();
          } else {
            changedValues.put(currentValue, new DiffChange(-1));
          }

          size = -1;
        }
      }

      if (OSBTreeRidBag.this.owner != null)
        ORecordInternal.unTrack(OSBTreeRidBag.this.owner, currentValue);

      if (updateOwner)
        fireCollectionChangedEvent(
            new OMultiValueChangeEvent<OIdentifiable, OIdentifiable>(
                OMultiValueChangeEvent.OChangeType.REMOVE,
                currentValue,
                null,
                currentValue,
                false));
      currentRemoved = true;
    }
예제 #6
0
  @Override
  public boolean contains(OIdentifiable identifiable) {
    if (newEntries.containsKey(identifiable)) return true;

    Change counter = changes.get(identifiable);

    if (counter != null) {
      AbsoluteChange absoluteValue = getAbsoluteValue(identifiable);

      if (counter.isUndefined()) {
        changes.put(identifiable, absoluteValue);
      }

      counter = absoluteValue;
    } else {
      counter = getAbsoluteValue(identifiable);
    }

    return counter.applyTo(0) > 0;
  }
예제 #7
0
  /**
   * Recalculates real bag size.
   *
   * @return real size
   */
  private int updateSize() {
    int size = 0;
    if (collectionPointer != null) {
      final OSBTreeBonsai<OIdentifiable, Integer> tree = loadTree();
      try {
        size = tree.getRealBagSize(changes);
      } finally {
        releaseTree();
      }
    } else {
      for (Change change : changes.values()) {
        size += change.applyTo(0);
      }
    }

    for (OModifiableInteger diff : newEntries.values()) {
      size += diff.getValue();
    }

    this.size = size;
    return size;
  }
예제 #8
0
  @Override
  public int serialize(byte[] stream, int offset, UUID ownerUuid) {
    for (Map.Entry<OIdentifiable, OModifiableInteger> entry : newEntries.entrySet()) {
      OIdentifiable identifiable = entry.getKey();
      assert identifiable instanceof ORecord;
      Change c = changes.get(identifiable);

      final int delta = entry.getValue().intValue();
      if (c == null) changes.put(identifiable, new DiffChange(delta));
      else c.applyDiff(delta);
    }
    newEntries.clear();

    final ORecordSerializationContext context;
    boolean remoteMode =
        ODatabaseRecordThreadLocal.INSTANCE.get().getStorage() instanceof OStorageProxy;
    if (remoteMode) {
      context = null;
    } else context = ORecordSerializationContext.getContext();

    // make sure that we really save underlying record.
    if (collectionPointer == null) {
      if (context != null) {
        final int clusterId = getHighLevelDocClusterId();
        assert clusterId > -1;
        collectionPointer =
            ODatabaseRecordThreadLocal.INSTANCE
                .get()
                .getSbTreeCollectionManager()
                .createSBTree(clusterId, ownerUuid);
      }
    }

    OBonsaiCollectionPointer collectionPointer;
    if (this.collectionPointer != null) collectionPointer = this.collectionPointer;
    else {
      collectionPointer = OBonsaiCollectionPointer.INVALID;
    }

    OLongSerializer.INSTANCE.serializeLiteral(collectionPointer.getFileId(), stream, offset);
    offset += OLongSerializer.LONG_SIZE;

    OBonsaiBucketPointer rootPointer = collectionPointer.getRootPointer();
    OLongSerializer.INSTANCE.serializeLiteral(rootPointer.getPageIndex(), stream, offset);
    offset += OLongSerializer.LONG_SIZE;

    OIntegerSerializer.INSTANCE.serializeLiteral(rootPointer.getPageOffset(), stream, offset);
    offset += OIntegerSerializer.INT_SIZE;

    // Keep this section for binary compatibility with versions older then 1.7.5
    OIntegerSerializer.INSTANCE.serializeLiteral(size, stream, offset);
    offset += OIntegerSerializer.INT_SIZE;

    if (context == null) {
      ChangeSerializationHelper.INSTANCE.serializeChanges(
          changes, OLinkSerializer.INSTANCE, stream, offset);
    } else {
      context.push(new ORidBagUpdateSerializationOperation(changes, collectionPointer));

      // 0-length serialized list of changes
      OIntegerSerializer.INSTANCE.serializeLiteral(0, stream, offset);
      offset += OIntegerSerializer.INT_SIZE;
    }

    return offset;
  }