Skip to content

Commit

Permalink
refactor: simplified index logic
Browse files Browse the repository at this point in the history
  • Loading branch information
tglman committed Dec 20, 2023
1 parent ff34dd0 commit aff3177
Show file tree
Hide file tree
Showing 39 changed files with 535 additions and 383 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
* @author Luca Garulli (l.garulli--(at)--orientdb.com)
*/
public interface OIndex extends Comparable<OIndex> {
String MERGE_KEYS = "mergeKeys";

OIndex create(OIndexMetadata metadata, boolean rebuild, OProgressListener progressListener);

String getDatabaseName();

/**
Expand Down Expand Up @@ -298,7 +294,5 @@ OIndexCursor iterateEntriesBetween(

boolean supportsOrderedIterations();

int getIndexId();

boolean isUnique();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
package com.orientechnologies.orient.core.index;

import com.orientechnologies.common.listener.OProgressListener;
import com.orientechnologies.common.util.ORawPair;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
Expand Down Expand Up @@ -60,6 +61,7 @@ public interface OIndexInternal extends OIndex {
String INDEX_DEFINITION_CLASS = "indexDefinitionClass";
String INDEX_VERSION = "indexVersion";
String METADATA = "metadata";
String MERGE_KEYS = "mergeKeys";

Object getCollatingValue(final Object key);

Expand Down Expand Up @@ -353,4 +355,8 @@ boolean doRemove(OAbstractPaginatedStorage storage, Object key)
throws OInvalidIndexEngineIdException;

Stream<ORID> getRidsIgnoreTx(Object key);

OIndex create(OIndexMetadata metadata, boolean rebuild, OProgressListener progressListener);

int getIndexId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -434,11 +434,6 @@ public OIdentifiable setValue(OIdentifiable value) {
};
}

@Override
public int getIndexId() {
throw new UnsupportedOperationException("getIndexId");
}

@Override
public OIndexCursor cursor() {
final OInternalResultSet copy = new OInternalResultSet(); // TODO a raw array instead...?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@

import com.orientechnologies.orient.core.exception.OInvalidIndexEngineIdException;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.index.engine.OBaseIndexEngine;
import com.orientechnologies.orient.core.storage.ORecordDuplicatedException;
import com.orientechnologies.orient.core.index.engine.IndexEngineValidator;
import com.orientechnologies.orient.core.index.engine.UniqueIndexEngineValidator;
import com.orientechnologies.orient.core.storage.OStorage;
import com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage;
import com.orientechnologies.orient.core.tx.OTransactionIndexChangesPerKey;
Expand All @@ -34,32 +34,8 @@
*/
public class OIndexUnique extends OIndexOneValue {

private final OBaseIndexEngine.Validator<Object, ORID> uniqueValidator =
(key, oldValue, newValue) -> {
if (oldValue != null) {
// CHECK IF THE ID IS THE SAME OF CURRENT: THIS IS THE UPDATE CASE
if (!oldValue.equals(newValue)) {
final Boolean mergeSameKey =
metadata != null ? (Boolean) metadata.field(OIndex.MERGE_KEYS) : Boolean.FALSE;
if (mergeSameKey == null || !mergeSameKey) {
throw new ORecordDuplicatedException(
String.format(
"Cannot index record %s: found duplicated key '%s' in index '%s' previously assigned to the record %s",
newValue.getIdentity(), key, getName(), oldValue.getIdentity()),
getName(),
oldValue.getIdentity(),
key);
}
} else {
return OBaseIndexEngine.Validator.IGNORE;
}
}

if (!newValue.getIdentity().isPersistent()) {
newValue = newValue.getRecord().getIdentity();
}
return newValue.getIdentity();
};
private final IndexEngineValidator<Object, ORID> uniqueValidator =
new UniqueIndexEngineValidator(this);

public OIndexUnique(OIndexMetadata im, final OStorage storage) {
super(im, storage);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.orientechnologies.orient.core.index.engine;

/**
* Put operation validator.
*
* @param <K> the key type.
* @param <V> the value type.
*/
public interface IndexEngineValidator<K, V> {

/**
* Indicates that a put request should be silently ignored by the store.
*
* @see #validate(Object, Object, Object)
*/
Object IGNORE = new Object();

/**
* Validates the put operation for the given key, the old value and the new value. May throw an
* exception to abort the current put operation with an error.
*
* @param key the put operation key.
* @param oldValue the old value or {@code null} if no value is currently stored.
* @param newValue the new value passed to validatedPut(Object, OIdentifiable, Validator).
* @return the new value to store, may differ from the passed one, or the special {@link #IGNORE}
* value to silently ignore the put operation request being processed.
*/
Object validate(K key, V oldValue, V newValue);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.orientechnologies.orient.core.index.engine;

import com.orientechnologies.orient.core.id.ORID;
import java.util.Collection;

public interface IndexEngineValuesTransformer {
Collection<ORID> transformFromValue(Object value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.stream.Stream;

Expand Down Expand Up @@ -49,24 +48,27 @@ Stream<ORawPair<Object, ORID>> iterateEntriesBetween(
Object rangeTo,
boolean toInclusive,
boolean ascSortOrder,
ValuesTransformer transformer);
IndexEngineValuesTransformer transformer);

Stream<ORawPair<Object, ORID>> iterateEntriesMajor(
Object fromKey, boolean isInclusive, boolean ascSortOrder, ValuesTransformer transformer);
Object fromKey,
boolean isInclusive,
boolean ascSortOrder,
IndexEngineValuesTransformer transformer);

Stream<ORawPair<Object, ORID>> iterateEntriesMinor(
final Object toKey,
final boolean isInclusive,
boolean ascSortOrder,
ValuesTransformer transformer);
IndexEngineValuesTransformer transformer);

Stream<ORawPair<Object, ORID>> stream(ValuesTransformer valuesTransformer);
Stream<ORawPair<Object, ORID>> stream(IndexEngineValuesTransformer valuesTransformer);

Stream<ORawPair<Object, ORID>> descStream(ValuesTransformer valuesTransformer);
Stream<ORawPair<Object, ORID>> descStream(IndexEngineValuesTransformer valuesTransformer);

Stream<Object> keyStream();

long size(ValuesTransformer transformer);
long size(IndexEngineValuesTransformer transformer);

boolean hasRangeQuerySupport();

Expand Down Expand Up @@ -98,36 +100,4 @@ Stream<ORawPair<Object, ORID>> iterateEntriesMinor(
default boolean hasRidBagTreesSupport() {
return false;
}

interface ValuesTransformer {
Collection<ORID> transformFromValue(Object value);
}

/**
* Put operation validator.
*
* @param <K> the key type.
* @param <V> the value type.
*/
interface Validator<K, V> {

/**
* Indicates that a put request should be silently ignored by the store.
*
* @see #validate(Object, Object, Object)
*/
Object IGNORE = new Object();

/**
* Validates the put operation for the given key, the old value and the new value. May throw an
* exception to abort the current put operation with an error.
*
* @param key the put operation key.
* @param oldValue the old value or {@code null} if no value is currently stored.
* @param newValue the new value passed to validatedPut(Object, OIdentifiable, Validator).
* @return the new value to store, may differ from the passed one, or the special {@link
* #IGNORE} value to silently ignore the put operation request being processed.
*/
Object validate(K key, V oldValue, V newValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,11 @@

package com.orientechnologies.orient.core.index.engine;

import com.orientechnologies.common.serialization.types.OBinarySerializer;
import com.orientechnologies.orient.core.encryption.OEncryption;
import com.orientechnologies.orient.core.config.IndexEngineData;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.index.OIndexKeyUpdater;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation;
import java.io.IOException;
import java.util.Map;

/**
* @author Andrey Lomakin (a.lomakin-at-orientdb.com)
Expand All @@ -54,25 +51,19 @@ void update(OAtomicOperation atomicOperation, Object key, OIndexKeyUpdater<Objec
* @param value the value to put.
* @param validator the operation validator.
* @return {@code true} if the validator allowed the put, {@code false} otherwise.
* @see Validator#validate(Object, Object, Object)
* @see IndexEngineValidator#validate(Object, Object, Object)
*/
boolean validatedPut(
OAtomicOperation atomicOperation, Object key, ORID value, Validator<Object, ORID> validator)
OAtomicOperation atomicOperation,
Object key,
ORID value,
IndexEngineValidator<Object, ORID> validator)
throws IOException;

@Override
default int getEngineAPIVersion() {
return VERSION;
}

void load(
String indexName,
OBinarySerializer valueSerializer,
boolean isAutomatic,
OBinarySerializer keySerializer,
OType[] keyTypes,
boolean nullPointerSupport,
int keySize,
Map<String, String> engineProperties,
OEncryption encryption);
void load(IndexEngineData data);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

public interface OSingleValueIndexEngine extends OV1IndexEngine {
boolean validatedPut(
OAtomicOperation atomicOperation, Object key, ORID value, Validator<Object, ORID> validator);
OAtomicOperation atomicOperation,
Object key,
ORID value,
IndexEngineValidator<Object, ORID> validator);

boolean remove(OAtomicOperation atomicOperation, Object key) throws IOException;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.orientechnologies.orient.core.index.engine;

import com.orientechnologies.common.serialization.types.OBinarySerializer;
import com.orientechnologies.orient.core.config.IndexEngineData;
import com.orientechnologies.orient.core.encryption.OEncryption;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.metadata.schema.OType;
Expand All @@ -19,6 +20,8 @@ default int getEngineAPIVersion() {
return API_VERSION;
}

void load(IndexEngineData data);

void load(
final String name,
final int keySize,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.orientechnologies.orient.core.index.engine;

import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.index.OIndexInternal;
import com.orientechnologies.orient.core.index.OIndexUnique;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.storage.ORecordDuplicatedException;

public class UniqueIndexEngineValidator implements IndexEngineValidator<Object, ORID> {

/** */
private final OIndexUnique indexUnique;

/** @param oIndexUnique */
public UniqueIndexEngineValidator(OIndexUnique oIndexUnique) {
indexUnique = oIndexUnique;
}

@Override
public Object validate(Object key, ORID oldValue, ORID newValue) {
if (oldValue != null) {
ODocument metadata = indexUnique.getMetadata();
// CHECK IF THE ID IS THE SAME OF CURRENT: THIS IS THE UPDATE CASE
if (!oldValue.equals(newValue)) {
final Boolean mergeSameKey =
metadata != null ? (Boolean) metadata.field(OIndexInternal.MERGE_KEYS) : Boolean.FALSE;
if (mergeSameKey == null || !mergeSameKey) {
throw new ORecordDuplicatedException(
String.format(
"Cannot index record %s: found duplicated key '%s' in index '%s' previously assigned to the record %s",
newValue.getIdentity(), key, indexUnique.getName(), oldValue.getIdentity()),
indexUnique.getName(),
oldValue.getIdentity(),
key);
}
} else {
return IndexEngineValidator.IGNORE;
}
}

if (!newValue.getIdentity().isPersistent()) {
newValue = newValue.getRecord().getIdentity();
}
return newValue.getIdentity();
}
}
Loading

0 comments on commit aff3177

Please sign in to comment.