All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.orientechnologies.orient.core.index.OIndexOneValue Maven / Gradle / Ivy

/*
 *
 *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.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://www.orientechnologies.com
 *
 */
package com.orientechnologies.orient.core.index;

import com.orientechnologies.common.comparator.ODefaultComparator;
import com.orientechnologies.common.listener.OProgressListener;
import com.orientechnologies.orient.core.db.ODatabase;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.serialization.serializer.stream.OStreamSerializer;
import com.orientechnologies.orient.core.serialization.serializer.stream.OStreamSerializerRID;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Abstract Index implementation that allows only one value for a key.
 * 
 * @author Luca Garulli
 * 
 */
public abstract class OIndexOneValue extends OIndexAbstract {
  public OIndexOneValue(final String type, String algorithm, OIndexEngine engine, String valueContainerAlgorithm,
      ODocument metadata) {
    super(type, algorithm, engine, valueContainerAlgorithm, metadata);
  }

  public OIdentifiable get(Object iKey) {
    checkForRebuild();

    iKey = getCollatingValue(iKey);

    final ODatabase database = getDatabase();
    final boolean txIsActive = database.getTransaction().isActive();
    if (!txIsActive)
      keyLockManager.acquireSharedLock(iKey);
    try {
      acquireSharedLock();
      try {
        return indexEngine.get(iKey);
      } finally {
        releaseSharedLock();
      }
    } finally {
      if (!txIsActive)
        keyLockManager.releaseSharedLock(iKey);
    }

  }

  public long count(Object iKey) {
    checkForRebuild();

    iKey = getCollatingValue(iKey);

    final ODatabase database = getDatabase();
    final boolean txIsActive = database.getTransaction().isActive();
    if (!txIsActive)
      keyLockManager.acquireSharedLock(iKey);

    try {
      acquireSharedLock();
      try {
        return indexEngine.contains(iKey) ? 1 : 0;
      } finally {
        releaseSharedLock();
      }
    } finally {
      if (!txIsActive)
        keyLockManager.releaseSharedLock(iKey);
    }
  }

  @Override
  public ODocument checkEntry(final OIdentifiable record, Object key) {
    checkForRebuild();

    key = getCollatingValue(key);

    final ODatabase database = getDatabase();
    final boolean txIsActive = database.getTransaction().isActive();

    if (!txIsActive)
      keyLockManager.acquireSharedLock(key);
    try {
      // CHECK IF ALREADY EXIST
      final OIdentifiable indexedRID = get(key);
      if (indexedRID != null && !indexedRID.getIdentity().equals(record.getIdentity())) {
        final Boolean mergeSameKey = metadata != null && (Boolean) metadata.field(OIndex.MERGE_KEYS);
        if (mergeSameKey != null && mergeSameKey)
          return (ODocument) indexedRID.getRecord();
        else
          throw new OIndexException("Cannot index record : " + record + " found duplicated key '" + key + "' in index " + getName()
              + " previously assigned to the record " + indexedRID);
      }
      return null;
    } finally {
      if (!txIsActive)
        keyLockManager.releaseSharedLock(key);
    }
  }

  public OIndexOneValue create(final String name, final OIndexDefinition indexDefinition, final String clusterIndexName,
      final Set clustersToIndex, boolean rebuild, final OProgressListener progressListener) {
    return (OIndexOneValue) super.create(name, indexDefinition, clusterIndexName, clustersToIndex, rebuild, progressListener,
        determineValueSerializer());
  }

  @Override
  public OIndexCursor iterateEntries(Collection keys, boolean ascSortOrder) {
    checkForRebuild();

    final List sortedKeys = new ArrayList(keys);
    final Comparator comparator;

    if (ascSortOrder)
      comparator = ODefaultComparator.INSTANCE;
    else
      comparator = Collections.reverseOrder(ODefaultComparator.INSTANCE);

    Collections.sort(sortedKeys, comparator);

    return new OIndexAbstractCursor() {
      private Iterator keysIterator = sortedKeys.iterator();

      @Override
      public Map.Entry nextEntry() {
        OIdentifiable result = null;
        Object key = null;
        while (keysIterator.hasNext() && result == null) {
          key = keysIterator.next();
          key = getCollatingValue(key);

          acquireSharedLock();
          try {
            result = indexEngine.get(key);
          } finally {
            releaseSharedLock();
          }
        }

        if (result == null)
          return null;

        final Object resultKey = key;
        final OIdentifiable resultValue = result;

        return new Map.Entry() {
          @Override
          public Object getKey() {
            return resultKey;
          }

          @Override
          public OIdentifiable getValue() {
            return resultValue;
          }

          @Override
          public OIdentifiable setValue(OIdentifiable value) {
            throw new UnsupportedOperationException("setValue");
          }
        };
      }
    };
  }

  @Override
  public OIndexCursor iterateEntriesBetween(Object fromKey, boolean fromInclusive, Object toKey, boolean toInclusive,
      boolean ascOrder) {
    checkForRebuild();

    fromKey = getCollatingValue(fromKey);
    toKey = getCollatingValue(toKey);

    acquireSharedLock();
    try {
      return indexEngine.iterateEntriesBetween(fromKey, fromInclusive, toKey, toInclusive, ascOrder, null);
    } finally {
      releaseSharedLock();
    }
  }

  @Override
  public OIndexCursor iterateEntriesMajor(Object fromKey, boolean fromInclusive, boolean ascOrder) {
    checkForRebuild();

    fromKey = getCollatingValue(fromKey);
    acquireSharedLock();
    try {
      return indexEngine.iterateEntriesMajor(fromKey, fromInclusive, ascOrder, null);
    } finally {
      releaseSharedLock();
    }
  }

  @Override
  public OIndexCursor iterateEntriesMinor(Object toKey, boolean toInclusive, boolean ascOrder) {
    checkForRebuild();

    toKey = getCollatingValue(toKey);
    acquireSharedLock();
    try {
      return indexEngine.iterateEntriesMinor(toKey, toInclusive, ascOrder, null);
    } finally {
      releaseSharedLock();
    }
  }

  public long getSize() {
    checkForRebuild();

    acquireSharedLock();
    try {
      return indexEngine.size(null);
    } finally {
      releaseSharedLock();
    }
  }

  public long getKeySize() {
    checkForRebuild();

    acquireSharedLock();
    try {
      return indexEngine.size(null);
    } finally {
      releaseSharedLock();
    }
  }

  @Override
  public OIndexCursor cursor() {
    checkForRebuild();

    acquireSharedLock();
    try {
      return indexEngine.cursor(null);
    } finally {
      releaseSharedLock();
    }
  }

  @Override
  public OIndexCursor descCursor() {
    checkForRebuild();

    acquireSharedLock();
    try {
      return indexEngine.descCursor(null);
    } finally {
      releaseSharedLock();
    }
  }

  @Override
  protected OStreamSerializer determineValueSerializer() {
    return OStreamSerializerRID.INSTANCE;
  }
}