Package com.orientechnologies.orient.core.cache

Source Code of com.orientechnologies.orient.core.cache.OAbstractRecordCache

/*
* Copyright 1999-2010 Luca Garulli (l.garulli--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.
*/
package com.orientechnologies.orient.core.cache;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import com.orientechnologies.common.concur.resource.OSharedResourceAbstract;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.common.profiler.OProfiler;
import com.orientechnologies.common.profiler.OProfiler.OProfilerHookValue;
import com.orientechnologies.orient.core.OMemoryWatchDog.Listener;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.record.ORecordInternal;

/**
* Cache of documents.
*
* @author Luca Garulli
*
*/
public abstract class OAbstractRecordCache extends OSharedResourceAbstract {
  protected boolean        enabled  = true;
  protected int            maxSize;
  protected ORecordCache  entries;

  protected Listener      watchDogListener;
  protected String        profilerPrefix;

  /**
   * Create the cache of iMaxSize size.
   *
   * @param iMaxSize
   *          Maximum number of elements for the cache
   */
  public OAbstractRecordCache(final String iProfilerPrefix, final int iMaxSize) {
    profilerPrefix = iProfilerPrefix;
    maxSize = iMaxSize;

    final int initialSize = maxSize > -1 ? maxSize + 1 : 1000;
    entries = new ORecordCache(maxSize, initialSize, 0.75f);
  }

  public boolean isEnabled() {
    return enabled;
  }

  public void setEnable(final boolean iValue) {
    enabled = iValue;
    if (!iValue)
      entries.clear();
  }

  public ORecordInternal<?> findRecord(final ORID iRid) {
    return null;
  }


  public ORecordInternal<?> freeRecord(final ORID iRID) {
    if (!enabled)
      // PRECONDITIONS
      return null;

    acquireExclusiveLock();
    try {
      return entries.remove(iRID);
    } finally {
      releaseExclusiveLock();
    }
  }

  public void freeCluster(final int clusterId) {
    if (!enabled)
      // PRECONDITIONS
      return;

    acquireExclusiveLock();
    final Set<ORID> toRemove = new HashSet<ORID>();
    try {
      for (ORID entry : entries.keySet()) {
        if (entry.getClusterId() == clusterId) {
          toRemove.add(entry);
        }
      }
      for (ORID ridToRemove : toRemove) {
        entries.remove(ridToRemove);
      }
    } finally {
      toRemove.clear();
      releaseExclusiveLock();
    }
  }

  /**
   * Remove multiple records from the cache in one shot.
   *
   * @param iRecords
   *          List of RIDs as RecordID instances
   */
  public void removeRecords(final Collection<ORID> iRecords) {
    if (!enabled)
      // PRECONDITIONS
      return;

    acquireExclusiveLock();
    try {
      for (ORID id : iRecords)
        entries.remove(id);
    } finally {
      releaseExclusiveLock();
    }
  }

  /**
   * Delete a record entry from both database and storage caches.
   *
   * @param iRecord
   *          Record to remove
   */
  public void deleteRecord(final ORID iRecord) {
    if (!enabled)
      // PRECONDITIONS
      return;

    acquireExclusiveLock();
    try {
      entries.remove(iRecord);
    } finally {
      releaseExclusiveLock();
    }
  }

  public boolean existsRecord(final ORID iRID) {
    if (!enabled)
      // PRECONDITIONS
      return false;

    acquireSharedLock();
    try {
      return entries.containsKey(iRID);
    } finally {
      releaseSharedLock();
    }
  }

  /**
   * Clear the entire cache by removing all the entries.
   */
  public void clear() {
    if (!enabled)
      // PRECONDITIONS
      return;

    acquireExclusiveLock();
    try {
      entries.clear();

    } finally {
      releaseExclusiveLock();
    }
  }

  /**
   * Return the total cached entries.
   *
   * @return
   */
  public int getSize() {
    acquireSharedLock();
    try {
      return entries.size();

    } finally {
      releaseSharedLock();
    }
  }

  public int getMaxSize() {
    acquireSharedLock();
    try {
      return maxSize;

    } finally {
      releaseSharedLock();
    }
  }

  public void shutdown() {
    acquireExclusiveLock();

    try {
      entries.clear();
      Orient.instance().getMemoryWatchDog().removeListener(watchDogListener);
      watchDogListener = null;

    } finally {
      releaseExclusiveLock();
    }
  }

  public void setMaxSize(final int iMaxSize) {
    maxSize = iMaxSize;
  }

  public void startup() {
    watchDogListener = Orient.instance().getMemoryWatchDog().addListener(new Listener() {
      /**
       * Auto reduce cache size of 50%
       */
      public void memoryUsageLow(TYPE iType, final long usedMemory, final long maxMemory) {
        if (iType == TYPE.JVM) {
          acquireExclusiveLock();
          try {
            final int oldSize = entries.size();
            if (oldSize == 0)
              // UNACTIVE
              return;

            final int threshold = (int) (oldSize * 0.9f);

            entries.removeEldestItems(threshold);

            OLogManager.instance().debug(this, "Low memory: auto reduce the record cache size from %d to %d", oldSize, threshold);
          } catch (Exception e) {
            OLogManager.instance().error(this, "Error while freeing resources", e);
          } finally {
            releaseExclusiveLock();
          }
        }
      }

      /**
       * Free the entire cache
       */
      public void memoryUsageCritical(TYPE iType, final long usedMemory, final long maxMemory) {
        if (iType == TYPE.JVM) {
          acquireExclusiveLock();
          try {
            OLogManager.instance().debug(this, "Clearing %d resources", entries.size());
            entries.clear();
          } catch (Exception e) {
            OLogManager.instance().error(this, "Error while freeing resources", e);
          } finally {
            releaseExclusiveLock();
          }
        }
      }
    });

    OProfiler.getInstance().registerHookValue(profilerPrefix + ".cache.enabled", new OProfilerHookValue() {
      public Object getValue() {
        return enabled;
      }
    });

    OProfiler.getInstance().registerHookValue(profilerPrefix + ".cache.current", new OProfilerHookValue() {
      public Object getValue() {
        acquireSharedLock();
        try {
          return entries.size();
        } finally {
          releaseSharedLock();
        }
      }
    });

    OProfiler.getInstance().registerHookValue(profilerPrefix + ".cache.max", new OProfilerHookValue() {
      public Object getValue() {
        return maxSize;
      }
    });
  }
}
TOP

Related Classes of com.orientechnologies.orient.core.cache.OAbstractRecordCache

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.