Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
*
* * Copyright 2010-2016 OrientDB LTD (http://orientdb.com)
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
* *
* * For more information: http://orientdb.com
*
*/
package com.orientechnologies.orient.core.index;
import com.orientechnologies.common.concur.lock.OOneEntryPerKeyLockManager;
import com.orientechnologies.common.concur.lock.OPartitionedLockManager;
import com.orientechnologies.common.exception.OException;
import com.orientechnologies.common.listener.OProgressListener;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.common.serialization.types.OBinarySerializer;
import com.orientechnologies.common.util.ORawPair;
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.exception.OCommandExecutionException;
import com.orientechnologies.orient.core.exception.OConfigurationException;
import com.orientechnologies.orient.core.exception.OInvalidIndexEngineIdException;
import com.orientechnologies.orient.core.exception.OManualIndexesAreProhibited;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.index.engine.OBaseIndexEngine;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.record.impl.ODocumentInternal;
import com.orientechnologies.orient.core.storage.OStorage;
import com.orientechnologies.orient.core.storage.cache.OReadCache;
import com.orientechnologies.orient.core.storage.cache.OWriteCache;
import com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage;
import com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation;
import com.orientechnologies.orient.core.storage.ridbag.sbtree.OIndexRIDContainer;
import com.orientechnologies.orient.core.tx.OTransactionIndexChanges;
import com.orientechnologies.orient.core.tx.OTransactionIndexChanges.OPERATION;
import com.orientechnologies.orient.core.tx.OTransactionIndexChangesPerKey;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Stream;
/**
* Handles indexing when records change. The underlying lock manager for keys can be the {@link
* OPartitionedLockManager}, the default one, or the {@link OOneEntryPerKeyLockManager} in case of
* distributed. This is to avoid deadlock situation between nodes where keys have the same hash
* code.
*
* @author Luca Garulli (l.garulli--(at)--orientdb.com)
*/
public abstract class OIndexAbstract implements OIndexInternal {
private static final OAlwaysLessKey ALWAYS_LESS_KEY = new OAlwaysLessKey();
private static final OAlwaysGreaterKey ALWAYS_GREATER_KEY = new OAlwaysGreaterKey();
protected static final String CONFIG_MAP_RID = "mapRid";
private static final String CONFIG_CLUSTERS = "clusters";
protected final String type;
protected final ODocument metadata;
protected final OAbstractPaginatedStorage storage;
private final String databaseName;
private final String name;
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final AtomicLong rebuildVersion = new AtomicLong();
private final int version;
protected volatile String valueContainerAlgorithm;
protected volatile int indexId = -1;
protected volatile int apiVersion = -1;
protected Set clustersToIndex = new HashSet<>();
private String algorithm;
private volatile OIndexDefinition indexDefinition;
private final Map engineProperties = new HashMap<>();
protected final int binaryFormatVersion;
public OIndexAbstract(
String name,
final String type,
final String algorithm,
final String valueContainerAlgorithm,
final ODocument metadata,
final int version,
final OStorage storage,
int binaryFormatVersion) {
this.binaryFormatVersion = binaryFormatVersion;
acquireExclusiveLock();
try {
databaseName = storage.getName();
this.version = version;
this.name = name;
this.type = type;
this.algorithm = algorithm;
this.metadata = metadata;
this.valueContainerAlgorithm = valueContainerAlgorithm;
this.storage = (OAbstractPaginatedStorage) storage;
} finally {
releaseExclusiveLock();
}
}
public static OIndexMetadata loadMetadataInternal(
final ODocument config,
final String type,
final String algorithm,
final String valueContainerAlgorithm) {
final String indexName = config.field(OIndexInternal.CONFIG_NAME);
final ODocument indexDefinitionDoc = config.field(OIndexInternal.INDEX_DEFINITION);
OIndexDefinition loadedIndexDefinition = null;
if (indexDefinitionDoc != null) {
try {
final String indexDefClassName = config.field(OIndexInternal.INDEX_DEFINITION_CLASS);
final Class indexDefClass = Class.forName(indexDefClassName);
loadedIndexDefinition =
(OIndexDefinition) indexDefClass.getDeclaredConstructor().newInstance();
loadedIndexDefinition.fromStream(indexDefinitionDoc);
} catch (final ClassNotFoundException
| IllegalAccessException
| InstantiationException
| InvocationTargetException
| NoSuchMethodException e) {
throw OException.wrapException(
new OIndexException("Error during deserialization of index definition"), e);
}
} else {
// @COMPATIBILITY 1.0rc6 new index model was implemented
final Boolean isAutomatic = config.field(OIndexInternal.CONFIG_AUTOMATIC);
OIndexFactory factory = OIndexes.getFactory(type, algorithm);
if (Boolean.TRUE.equals(isAutomatic)) {
final int pos = indexName.lastIndexOf('.');
if (pos < 0)
throw new OIndexException(
"Cannot convert from old index model to new one. "
+ "Invalid index name. Dot (.) separator should be present");
final String className = indexName.substring(0, pos);
final String propertyName = indexName.substring(pos + 1);
final String keyTypeStr = config.field(OIndexInternal.CONFIG_KEYTYPE);
if (keyTypeStr == null)
throw new OIndexException(
"Cannot convert from old index model to new one. " + "Index key type is absent");
final OType keyType = OType.valueOf(keyTypeStr.toUpperCase(Locale.ENGLISH));
loadedIndexDefinition = new OPropertyIndexDefinition(className, propertyName, keyType);
config.removeField(OIndexInternal.CONFIG_AUTOMATIC);
config.removeField(OIndexInternal.CONFIG_KEYTYPE);
} else if (config.field(OIndexInternal.CONFIG_KEYTYPE) != null) {
final String keyTypeStr = config.field(OIndexInternal.CONFIG_KEYTYPE);
final OType keyType = OType.valueOf(keyTypeStr.toUpperCase(Locale.ENGLISH));
loadedIndexDefinition = new OSimpleKeyIndexDefinition(keyType);
config.removeField(OIndexInternal.CONFIG_KEYTYPE);
}
}
final Set clusters = new HashSet<>(config.field(CONFIG_CLUSTERS, OType.EMBEDDEDSET));
return new OIndexMetadata(
indexName,
loadedIndexDefinition,
clusters,
type,
algorithm,
valueContainerAlgorithm,
config.field(OIndexInternal.METADATA));
}
@Override
public boolean hasRangeQuerySupport() {
acquireSharedLock();
try {
while (true)
try {
return storage.hasIndexRangeQuerySupport(indexId);
} catch (OInvalidIndexEngineIdException ignore) {
doReloadIndexEngine();
}
} finally {
releaseSharedLock();
}
}
/** Creates the index. */
public OIndexInternal create(
final OIndexMetadata indexMetadata,
boolean rebuild,
final OProgressListener progressListener) {
final OBinarySerializer valueSerializer = determineValueSerializer();
acquireExclusiveLock();
try {
Set clustersToIndex = indexMetadata.getClustersToIndex();
this.indexDefinition = indexMetadata.getIndexDefinition();
if (clustersToIndex != null) this.clustersToIndex = new HashSet<>(clustersToIndex);
else this.clustersToIndex = new HashSet<>();
// do not remove this, it is needed to remove index garbage if such one exists
try {
if (apiVersion == 0) {
removeValuesContainer();
}
} catch (Exception e) {
OLogManager.instance().error(this, "Error during deletion of index '%s'", e, name);
}
// this property is used for autosharded index
if (metadata != null && metadata.containsField("partitions")) {
engineProperties.put("partitions", metadata.field("partitions"));
} else {
engineProperties.put("partitions", Integer.toString(clustersToIndex.size()));
}
indexId = storage.addIndexEngine(indexMetadata, valueSerializer, version, engineProperties);
apiVersion = OAbstractPaginatedStorage.extractEngineAPIVersion(indexId);
assert indexId >= 0;
assert apiVersion >= 0;
onIndexEngineChange(indexId);
if (rebuild) fillIndex(progressListener, false);
updateConfiguration();
} catch (Exception e) {
OLogManager.instance().error(this, "Exception during index '%s' creation", e, name);
// index is created inside of storage
if (indexId >= 0) {
doDelete();
}
throw OException.wrapException(
new OIndexException("Cannot create the index '" + name + "'"), e);
} finally {
releaseExclusiveLock();
}
return this;
}
protected void doReloadIndexEngine() {
indexId = storage.loadIndexEngine(name);
apiVersion = OAbstractPaginatedStorage.extractEngineAPIVersion(indexId);
if (indexId < 0) {
throw new IllegalStateException("Index " + name + " can not be loaded");
}
}
public boolean loadFromConfiguration(final ODocument config) {
acquireExclusiveLock();
try {
clustersToIndex.clear();
final OIndexMetadata indexMetadata = loadMetadata(config);
indexDefinition = indexMetadata.getIndexDefinition();
clustersToIndex.addAll(indexMetadata.getClustersToIndex());
algorithm = indexMetadata.getAlgorithm();
valueContainerAlgorithm = indexMetadata.getValueContainerAlgorithm();
try {
indexId = storage.loadIndexEngine(name);
apiVersion = OAbstractPaginatedStorage.extractEngineAPIVersion(indexId);
if (indexId == -1) {
indexId =
storage.loadExternalIndexEngine(
indexMetadata, determineValueSerializer(), version, 1, engineProperties);
apiVersion = OAbstractPaginatedStorage.extractEngineAPIVersion(indexId);
}
if (indexId == -1) {
return false;
}
onIndexEngineChange(indexId);
} catch (Exception e) {
OLogManager.instance()
.error(
this,
"Error during load of index '%s'",
e,
Optional.ofNullable(name).orElse("null"));
if (isAutomatic()) {
// AUTOMATIC REBUILD IT
OLogManager.instance().warn(this, "Cannot load index '%s' rebuilt it from scratch", name);
try {
rebuild();
} catch (Exception t) {
OLogManager.instance()
.error(
this,
"Cannot rebuild index '%s' because '"
+ t
+ "'. The index will be removed in configuration",
e,
name);
// REMOVE IT
return false;
}
}
}
return true;
} finally {
releaseExclusiveLock();
}
}
private Map getEngineProperties() {
return engineProperties;
}
@Override
public OIndexMetadata loadMetadata(final ODocument config) {
return loadMetadataInternal(config, type, algorithm, valueContainerAlgorithm);
}
/** {@inheritDoc} */
public long rebuild() {
return rebuild(new OIndexRebuildOutputListener(this));
}
@Override
public void close() {}
/** @return number of entries in the index. */
@Deprecated
public long getSize() {
return size();
}
/** Counts the entries for the key. */
@Deprecated
public long count(Object iKey) {
try (Stream> stream =
streamEntriesBetween(iKey, true, iKey, true, true)) {
return stream.count();
}
}
/** @return Number of keys in index */
@Deprecated
public long getKeySize() {
try (Stream