/*MUST be called under the WriteLock*/ @NotNull private Map<Integer, SerializedStubTree> readOldData(final int key) throws StorageException { final Map<Integer, SerializedStubTree> result = new HashMap<Integer, SerializedStubTree>(); IndexStorage<Integer, SerializedStubTree> indexStorage = myStorage; if (indexStorage instanceof MemoryIndexStorage) { final MemoryIndexStorage<Integer, SerializedStubTree> memIndexStorage = (MemoryIndexStorage<Integer, SerializedStubTree>) indexStorage; if (!memIndexStorage.isBufferingEnabled()) { // if buffering is not enabled, use backend storage to make sure // the returned stub tree contains no data corresponding to unsaved documents. // This will ensure that correct set of old keys is used for update indexStorage = memIndexStorage.getBackendStorage(); } } try { final ValueContainer<SerializedStubTree> valueContainer = indexStorage.read(key); if (valueContainer.size() != 1) { LOG.assertTrue(valueContainer.size() == 0); return result; } result.put(key, valueContainer.getValueIterator().next()); return result; } catch (RuntimeException e) { final Throwable cause = e.getCause(); if (cause instanceof IOException) { throw new StorageException(cause); } throw e; } }
@Override protected void doPut(Key key, ValueContainer<Value> container) throws IOException { synchronized (myEnumerator) { ChangeTrackingValueContainer<Value> valueContainer = (ChangeTrackingValueContainer<Value>) container; if (!valueContainer.needsCompacting()) { final BufferExposingByteArrayOutputStream bytes = new BufferExposingByteArrayOutputStream(); //noinspection IOResourceOpenedButNotSafelyClosed final DataOutputStream _out = new DataOutputStream(bytes); final TIntHashSet set = valueContainer.getInvalidated(); if (set.size() > 0) { for (int inputId : set.toArray()) { ValueContainerExternalizer.saveInvalidateCommand(_out, inputId); } } final ValueContainer<Value> toRemove = valueContainer.getRemovedDelta(); if (toRemove.size() > 0) { myValueContainerExternalizer.saveAsRemoved(_out, toRemove); } final ValueContainer<Value> toAppend = valueContainer.getAddedDelta(); if (toAppend.size() > 0) { myValueContainerExternalizer.save(_out, toAppend); } appendData( key, new PersistentHashMap.ValueDataAppender() { public void append(final DataOutput out) throws IOException { out.write(bytes.getInternalBuffer(), 0, bytes.size()); } }); } else { // rewrite the value container for defragmentation super.doPut(key, valueContainer); } } }
private void saveImpl( final DataOutput out, final ValueContainer<T> container, final boolean asRemovedData) throws IOException { DataInputOutputUtil.writeSINT(out, container.size()); for (final Iterator<T> valueIterator = container.getValueIterator(); valueIterator.hasNext(); ) { final T value = valueIterator.next(); myExternalizer.save(out, value); final ValueContainer.IntIterator ids = container.getInputIdsIterator(value); if (ids != null) { DataInputOutputUtil.writeSINT(out, ids.size()); while (ids.hasNext()) { final int id = ids.next(); DataInputOutputUtil.writeSINT(out, asRemovedData ? -id : id); } } else { DataInputOutputUtil.writeSINT(out, 0); } } }