コード例 #1
0
  @NotNull
  public ValueContainerImpl<Value> copy() {
    ValueContainerImpl<Value> container = new ValueContainerImpl<Value>();

    if (myInputIdMapping instanceof THashMap) {
      final THashMap<Value, Object> mapping = (THashMap<Value, Object>) myInputIdMapping;
      final THashMap<Value, Object> newMapping = new THashMap<Value, Object>(mapping.size());
      container.myInputIdMapping = newMapping;

      mapping.forEachEntry(
          new TObjectObjectProcedure<Value, Object>() {
            @Override
            public boolean execute(Value key, Object val) {
              if (val instanceof ChangeBufferingList) {
                newMapping.put(key, ((ChangeBufferingList) val).clone());
              } else {
                newMapping.put(key, val);
              }
              return true;
            }
          });
    } else {
      container.myInputIdMapping = myInputIdMapping;
      container.myInputIdMappingValue =
          myInputIdMappingValue instanceof ChangeBufferingList
              ? ((ChangeBufferingList) myInputIdMappingValue).clone()
              : myInputIdMappingValue;
    }
    return container;
  }
  @Override
  public boolean removeValue(int inputId, Value value) {
    ValueContainerImpl<Value> merged = myMerged;
    if (merged != null) {
      merged.removeValue(inputId, value);
    }
    ValueContainerImpl<Value> added = myAdded;
    if (added != null) added.removeValue(inputId, value);

    return true;
  }
  // need 'synchronized' to ensure atomic initialization of merged data
  // because several threads that acquired read lock may simultaneously execute the method
  private ValueContainerImpl<Value> getMergedData() {
    ValueContainerImpl<Value> merged = myMerged;
    if (merged != null) {
      return merged;
    }
    synchronized (myInitializer.getLock()) {
      merged = myMerged;
      if (merged != null) {
        return merged;
      }

      final ValueContainer<Value> fromDisk = myInitializer.compute();
      final ValueContainerImpl<Value> newMerged;

      if (fromDisk instanceof ValueContainerImpl) {
        newMerged = ((ValueContainerImpl<Value>) fromDisk).copy();
      } else {
        newMerged = ((ChangeTrackingValueContainer<Value>) fromDisk).getMergedData().copy();
      }

      TIntHashSet invalidated = myInvalidated;
      if (invalidated != null) {
        invalidated.forEach(
            new TIntProcedure() {
              @Override
              public boolean execute(int inputId) {
                newMerged.removeAssociatedValue(inputId);
                return true;
              }
            });
      }

      ValueContainerImpl<Value> added = myAdded;
      if (added != null) {
        added.forEach(
            new ContainerAction<Value>() {
              @Override
              public boolean perform(final int id, final Value value) {
                newMerged.removeAssociatedValue(
                    id); // enforcing "one-value-per-file for particular key" invariant
                newMerged.addValue(id, value);
                return true;
              }
            });
      }
      setNeedsCompacting(fromDisk.needsCompacting());

      myMerged = newMerged;
      return newMerged;
    }
  }
コード例 #4
0
 @Override
 public ValueContainerImpl<Value> clone() {
   try {
     final ValueContainerImpl clone = (ValueContainerImpl) super.clone();
     if (myInputIdMapping instanceof THashMap) {
       clone.myInputIdMapping = mapCopy((THashMap<Value, Object>) myInputIdMapping);
     } else if (myInputIdMappingValue instanceof ChangeBufferingList) {
       clone.myInputIdMappingValue = ((ChangeBufferingList) myInputIdMappingValue).clone();
     }
     return clone;
   } catch (CloneNotSupportedException e) {
     throw new RuntimeException(e);
   }
 }
 @Override
 public void addValue(int inputId, Value value) {
   ValueContainerImpl<Value> merged = myMerged;
   if (merged != null) {
     merged.addValue(inputId, value);
   }
   ValueContainerImpl<Value> added = myAdded;
   if (added == null) {
     myAdded = added = new ValueContainerImpl<Value>();
   }
   added.addValue(
       inputId,
       value); // will flush the changes & caller should ensure exclusiveness to avoid intermediate
               // visibility issues
 }
  @Override
  public void removeAssociatedValue(int inputId) {
    ValueContainerImpl<Value> merged = myMerged;
    if (merged != null) {
      merged.removeAssociatedValue(inputId);
    }

    ValueContainerImpl<Value> added = myAdded;
    if (added != null) added.removeAssociatedValue(inputId);

    TIntHashSet invalidated = myInvalidated;
    if (invalidated == null) {
      invalidated = new TIntHashSet(1);
    }
    invalidated.add(inputId);
    myInvalidated = invalidated; // volatile write
  }
コード例 #7
0
    public ValueContainerImpl<T> read(final DataInput in) throws IOException {
      DataInputStream stream = (DataInputStream) in;
      final ValueContainerImpl<T> valueContainer = new ValueContainerImpl<T>();

      while (stream.available() > 0) {
        final int valueCount = DataInputOutputUtil.readSINT(in);
        if (valueCount < 0) {
          valueContainer.removeAllValues(-valueCount);
          valueContainer.setNeedsCompacting(true);
        } else {
          for (int valueIdx = 0; valueIdx < valueCount; valueIdx++) {
            final T value = myExternalizer.read(in);
            final int idCount = DataInputOutputUtil.readSINT(in);
            for (int i = 0; i < idCount; i++) {
              final int id = DataInputOutputUtil.readSINT(in);
              if (id < 0) {
                valueContainer.removeValue(-id, value);
                valueContainer.setNeedsCompacting(true);
              } else {
                valueContainer.addValue(id, value);
              }
            }
          }
        }
      }
      return valueContainer;
    }
 public boolean isDirty() {
   return (myAdded != null && myAdded.size() > 0)
       || (myInvalidated != null && !myInvalidated.isEmpty())
       || needsCompacting();
 }