package com.orientechnologies.orient.core.index; import com.orientechnologies.common.util.OSizeable; import com.orientechnologies.orient.core.db.record.OIdentifiable; import com.orientechnologies.orient.core.exception.OIndexIsRebuildingException; import java.util.Map; import java.util.Set; /** * Wrapper which is used to detect whether the cursor is working with index * which is being rebuilt at the moment. * <p> * If such situation is detected any call to any method throws {@link OIndexIsRebuildingException} * * @see OIndexAbstract#getRebuildVersion() */ public class OIndexChangesWrapper implements OIndexCursor { protected final OIndex<?> source; protected final OIndexCursor delegate; protected final long indexRebuildVersion; public OIndexChangesWrapper(OIndex<?> source, OIndexCursor delegate, long indexRebuildVersion) { this.source = source; this.delegate = delegate; this.indexRebuildVersion = indexRebuildVersion; } /** * Wraps courser only if it is not already wrapped. * * @param source Index which is used to create given cursor. * @param cursor Cursor to wrap. * @param indexRebuildVersion Rebuild version of index <b>before</b> cursor was created. * @return Wrapped cursor. * @see OIndex#getRebuildVersion() */ public static OIndexCursor wrap(OIndex<?> source, OIndexCursor cursor, long indexRebuildVersion) { if (cursor instanceof OIndexChangesWrapper) return cursor; if (cursor instanceof OSizeable) { return new OIndexChangesSizeable(source, cursor, indexRebuildVersion); } return new OIndexChangesWrapper(source, cursor, indexRebuildVersion); } /** * {@inheritDoc} */ @Override public void remove() { delegate.remove(); } /** * {@inheritDoc} */ @Override public Map.Entry<Object, OIdentifiable> nextEntry() { if (source.isRebuilding()) throwRebuildException(); final Map.Entry<Object, OIdentifiable> entry = delegate.nextEntry(); if (source.getRebuildVersion() != indexRebuildVersion) throwRebuildException(); return entry; } /** * {@inheritDoc} */ @Override public Set<OIdentifiable> toValues() { if (source.isRebuilding()) throwRebuildException(); final Set<OIdentifiable> values = delegate.toValues(); if (source.getRebuildVersion() != indexRebuildVersion) throwRebuildException(); return values; } /** * {@inheritDoc} */ @Override public Set<Map.Entry<Object, OIdentifiable>> toEntries() { if (source.isRebuilding()) throwRebuildException(); final Set<Map.Entry<Object, OIdentifiable>> entries = delegate.toEntries(); if (source.getRebuildVersion() != indexRebuildVersion) throwRebuildException(); return entries; } /** * {@inheritDoc} */ @Override public Set<Object> toKeys() { if (source.isRebuilding()) throwRebuildException(); final Set<Object> keys = delegate.toKeys(); if (source.getRebuildVersion() != indexRebuildVersion) throwRebuildException(); return keys; } /** * {@inheritDoc} */ @Override public void setPrefetchSize(int prefetchSize) { delegate.setPrefetchSize(prefetchSize); } /** * {@inheritDoc} */ @Override public boolean hasNext() { if (source.isRebuilding()) throwRebuildException(); final boolean isNext = delegate.hasNext(); if (source.getRebuildVersion() != indexRebuildVersion) throwRebuildException(); return isNext; } /** * {@inheritDoc} */ @Override public OIdentifiable next() { if (source.isRebuilding()) throwRebuildException(); final OIdentifiable next = delegate.next(); if (source.getRebuildVersion() != indexRebuildVersion) throwRebuildException(); return next; } protected void throwRebuildException() { throw new OIndexIsRebuildingException("Index " + source.getName() + " is rebuilding at the moment and can not be used"); } } /** * Adds support of {@link OSizeable} interface if index cursor implements it. */ class OIndexChangesSizeable extends OIndexChangesWrapper implements OSizeable { public OIndexChangesSizeable(OIndex<?> source, OIndexCursor delegate, long indexRebuildVersion) { super(source, delegate, indexRebuildVersion); } @Override public int size() { if (source.isRebuilding()) throwRebuildException(); final int size = ((OSizeable) delegate).size(); if (source.getRebuildVersion() != indexRebuildVersion) throwRebuildException(); return size; } }