@Override public Object executeIndexQuery( OCommandContext iContext, OIndex<?> index, final INDEX_OPERATION_TYPE iOperationType, List<Object> keyParams, int fetchLimit) { final OIndexDefinition indexDefinition = index.getDefinition(); final OIndexInternal<?> internalIndex = index.getInternal(); if (!internalIndex.canBeUsedInEqualityOperators()) return null; final Object result; if (indexDefinition.getParamCount() == 1) { final Object key; if (indexDefinition instanceof OIndexDefinitionMultiValue) key = ((OIndexDefinitionMultiValue) indexDefinition).createSingleValue(keyParams.get(0)); else key = indexDefinition.createValue(keyParams); if (key == null) return null; final Object indexResult; if (iOperationType == INDEX_OPERATION_TYPE.GET) indexResult = index.get(key); else indexResult = index.count(key); result = convertIndexResult(indexResult); } else { // in case of composite keys several items can be returned in case of we perform search // using part of composite key stored in index. final OCompositeIndexDefinition compositeIndexDefinition = (OCompositeIndexDefinition) indexDefinition; final Object keyOne = compositeIndexDefinition.createSingleValue(keyParams); if (keyOne == null) return null; final Object keyTwo = compositeIndexDefinition.createSingleValue(keyParams); if (internalIndex.hasRangeQuerySupport()) { if (INDEX_OPERATION_TYPE.COUNT.equals(iOperationType)) { result = index.count(keyOne, true, keyTwo, true, fetchLimit); } else if (fetchLimit > -1) result = index.getValuesBetween(keyOne, true, keyTwo, true, fetchLimit); else result = index.getValuesBetween(keyOne, true, keyTwo, true); } else { if (indexDefinition.getParamCount() == keyParams.size()) { final Object indexResult; if (iOperationType == INDEX_OPERATION_TYPE.GET) indexResult = index.get(keyOne); else indexResult = index.count(keyOne); result = convertIndexResult(indexResult); } else return null; } } updateProfiler(iContext, index, keyParams, indexDefinition); return result; }
@Override protected void handleObject(OIndex<?> object) { indexName = object.getName(); OIndexDefinition indexDefinition = object.getDefinition(); if (indexDefinition != null) { String className = indexDefinition.getClassName(); if (className != null) classModel = new OClassModel(className); } }
/** * Make type conversion of keys for specific index. * * @param index - index for which keys prepared for. * @param keys - which should be prepared. * @return keys converted to necessary type. */ private Set<Comparable> prepareKeys(OIndex<?> index, Object keys) { final OIndexDefinition indexDefinition = index.getDefinition(); if (keys instanceof Collection) { final Set<Comparable> newKeys = new TreeSet<Comparable>(); for (Object o : ((Collection) keys)) { newKeys.add((Comparable) indexDefinition.createValue(o)); } return newKeys; } else { return Collections.singleton((Comparable) indexDefinition.createValue(keys)); } }
/** * Register statistic information about usage of index in {@link OProfilerStub}. * * @param index which usage is registering. */ private void updateStatistic(OIndex<?> index) { final OProfiler profiler = Orient.instance().getProfiler(); if (profiler.isRecording()) { Orient.instance() .getProfiler() .updateCounter( profiler.getDatabaseMetric(index.getDatabaseName(), "query.indexUsed"), "Used index in query", +1); final int paramCount = index.getDefinition().getParamCount(); if (paramCount > 1) { final String profiler_prefix = profiler.getDatabaseMetric(index.getDatabaseName(), "query.compositeIndexUsed"); profiler.updateCounter(profiler_prefix, "Used composite index in query", +1); profiler.updateCounter( profiler_prefix + "." + paramCount, "Used composite index in query with " + paramCount + " params", +1); } } }
private static boolean isComposite(OIndex<?> currentIndex) { return currentIndex.getDefinition().getParamCount() > 1; }
/** {@inheritDoc} */ public OIndexDefinition getDefinition() { return lastIndex.getDefinition(); }
public void commit() { checkTransaction(); status = TXSTATUS.COMMITTING; if (OScenarioThreadLocal.INSTANCE.get() != RUN_MODE.RUNNING_DISTRIBUTED && !(database.getStorage() instanceof OStorageEmbedded)) database.getStorage().commit(this, null); else { final List<String> involvedIndexes = getInvolvedIndexes(); if (involvedIndexes != null) Collections.sort(involvedIndexes); for (int retry = 1; retry <= autoRetries; ++retry) { try { // LOCK INVOLVED INDEXES List<OIndexAbstract<?>> lockedIndexes = null; try { if (involvedIndexes != null) for (String indexName : involvedIndexes) { final OIndexAbstract<?> index = (OIndexAbstract<?>) database.getMetadata().getIndexManager().getIndexInternal(indexName); if (lockedIndexes == null) lockedIndexes = new ArrayList<OIndexAbstract<?>>(); index.acquireModificationLock(); lockedIndexes.add(index); } if (!useSBTree) { // SEARCH FOR INDEX BASED ON DOCUMENT TOUCHED final Collection<? extends OIndex<?>> indexes = database.getMetadata().getIndexManager().getIndexes(); List<? extends OIndex<?>> indexesToLock = null; if (indexes != null) { indexesToLock = new ArrayList<OIndex<?>>(indexes); Collections.sort( indexesToLock, new Comparator<OIndex<?>>() { public int compare(final OIndex<?> indexOne, final OIndex<?> indexTwo) { return indexOne.getName().compareTo(indexTwo.getName()); } }); } if (indexesToLock != null && !indexesToLock.isEmpty()) { if (lockedIndexes == null) lockedIndexes = new ArrayList<OIndexAbstract<?>>(); for (OIndex<?> index : indexesToLock) { for (Entry<ORID, ORecordOperation> entry : recordEntries.entrySet()) { final ORecord<?> record = entry.getValue().record.getRecord(); if (record instanceof ODocument) { ODocument doc = (ODocument) record; if (!lockedIndexes.contains(index.getInternal()) && doc.getSchemaClass() != null && index.getDefinition() != null && doc.getSchemaClass() .isSubClassOf(index.getDefinition().getClassName())) { index.getInternal().acquireModificationLock(); lockedIndexes.add((OIndexAbstract<?>) index.getInternal()); } } } } for (OIndexAbstract<?> index : lockedIndexes) index.acquireExclusiveLock(); } } final Map<String, OIndex> indexes = new HashMap<String, OIndex>(); for (OIndex index : database.getMetadata().getIndexManager().getIndexes()) indexes.put(index.getName(), index); final Runnable callback = new Runnable() { @Override public void run() { final ODocument indexEntries = getIndexChanges(); if (indexEntries != null) { final Map<String, OIndexInternal<?>> indexesToCommit = new HashMap<String, OIndexInternal<?>>(); for (Entry<String, Object> indexEntry : indexEntries) { final OIndexInternal<?> index = indexes.get(indexEntry.getKey()).getInternal(); indexesToCommit.put(index.getName(), index.getInternal()); } for (OIndexInternal<?> indexInternal : indexesToCommit.values()) indexInternal.preCommit(); for (Entry<String, Object> indexEntry : indexEntries) { final OIndexInternal<?> index = indexesToCommit.get(indexEntry.getKey()).getInternal(); if (index == null) { OLogManager.instance() .error( this, "Index with name " + indexEntry.getKey() + " was not found."); throw new OIndexException( "Index with name " + indexEntry.getKey() + " was not found."); } else index.addTxOperation((ODocument) indexEntry.getValue()); } try { for (OIndexInternal<?> indexInternal : indexesToCommit.values()) indexInternal.commit(); } finally { for (OIndexInternal<?> indexInternal : indexesToCommit.values()) indexInternal.postCommit(); } } } }; final String storageType = database.getStorage().getType(); if (storageType.equals(OEngineLocal.NAME) || storageType.equals(OEngineLocalPaginated.NAME)) database.getStorage().commit(OTransactionOptimistic.this, callback); else { database .getStorage() .callInLock( new Callable<Object>() { @Override public Object call() throws Exception { database.getStorage().commit(OTransactionOptimistic.this, null); callback.run(); return null; } }, true); } // OK break; } finally { // RELEASE INDEX LOCKS IF ANY if (lockedIndexes != null) { if (!useSBTree) { for (OIndexAbstract<?> index : lockedIndexes) index.releaseExclusiveLock(); } for (OIndexAbstract<?> index : lockedIndexes) index.releaseModificationLock(); } } } catch (OTimeoutException e) { if (autoRetries == 0) { OLogManager.instance() .debug( this, "Caught timeout exception during commit, but no automatic retry has been set", e); throw e; } else if (retry == autoRetries) { OLogManager.instance() .debug( this, "Caught timeout exception during %d/%d. Retry limit is exceeded.", retry, autoRetries); throw e; } else { OLogManager.instance() .debug( this, "Caught timeout exception during commit retrying %d/%d...", retry, autoRetries); } } } } status = TXSTATUS.COMPLETED; }