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

com.orientechnologies.orient.core.metadata.OMetadataDefault 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.metadata;

import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.common.profiler.OProfilerMBean;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.db.ODatabase;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.exception.OSecurityException;
import com.orientechnologies.orient.core.index.OIndexManager;
import com.orientechnologies.orient.core.index.OIndexManagerProxy;
import com.orientechnologies.orient.core.index.OIndexManagerRemote;
import com.orientechnologies.orient.core.index.OIndexManagerShared;
import com.orientechnologies.orient.core.metadata.function.OFunctionLibrary;
import com.orientechnologies.orient.core.metadata.function.OFunctionLibraryImpl;
import com.orientechnologies.orient.core.metadata.function.OFunctionLibraryProxy;
import com.orientechnologies.orient.core.metadata.schema.OImmutableSchema;
import com.orientechnologies.orient.core.metadata.schema.OSchema;
import com.orientechnologies.orient.core.metadata.schema.OSchemaProxy;
import com.orientechnologies.orient.core.metadata.schema.OSchemaShared;
import com.orientechnologies.orient.core.metadata.security.OSecurity;
import com.orientechnologies.orient.core.metadata.security.OSecurityProxy;
import com.orientechnologies.orient.core.metadata.security.OSecurityShared;
import com.orientechnologies.orient.core.schedule.OSchedulerListener;
import com.orientechnologies.orient.core.schedule.OSchedulerListenerImpl;
import com.orientechnologies.orient.core.schedule.OSchedulerListenerProxy;
import com.orientechnologies.orient.core.storage.OStorageProxy;

import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;

public class OMetadataDefault implements OMetadataInternal {
  public static final String                           CLUSTER_INTERNAL_NAME     = "internal";
  public static final String                           CLUSTER_INDEX_NAME        = "index";
  public static final String                           CLUSTER_MANUAL_INDEX_NAME = "manindex";

  protected int                                        schemaClusterId;

  protected OSchemaProxy                               schema;
  protected OSecurity                                  security;
  protected OIndexManagerProxy                         indexManager;
  protected OFunctionLibraryProxy                      functionLibrary;
  protected OSchedulerListenerProxy                    scheduler;
  protected static final OProfilerMBean                PROFILER                  = Orient.instance().getProfiler();

  private final AtomicReference      schemaCache               = new AtomicReference();

  private final ThreadLocal threadLocalSchemaSnapshot = new ThreadLocal();

  public OMetadataDefault() {
  }

  public void load() {
    final long timer = PROFILER.startChrono();

    try {
      init(true);

      if (schemaClusterId == -1 || getDatabase().countClusterElements(CLUSTER_INTERNAL_NAME) == 0)
        return;

    } finally {
      PROFILER.stopChrono(PROFILER.getDatabaseMetric(getDatabase().getName(), "metadata.load"), "Loading of database metadata",
          timer, "db.*.metadata.load");
    }
  }

  public void create() throws IOException {
    init(false);

    schema.create();
    indexManager.create();
    security.create();
    functionLibrary.create();
    security.createClassTrigger();
    scheduler.create();
  }

  public OSchemaProxy getSchema() {
    return schema;
  }

  @Override
  public void makeThreadLocalSchemaSnapshot() {
    ThreadLocalSchemaSnapshot schemaSnapshot = threadLocalSchemaSnapshot.get();

    if (schemaSnapshot == null) {
      final OImmutableSchema immutableSchema = getImmutableSchemaSnapshot();
      schemaSnapshot = new ThreadLocalSchemaSnapshot(immutableSchema);

      threadLocalSchemaSnapshot.set(schemaSnapshot);
      return;
    }

    schemaSnapshot.snapshotCounter++;
  }

  @Override
  public void clearThreadLocalSchemaSnapshot() {
    ThreadLocalSchemaSnapshot schemaSnapshot = threadLocalSchemaSnapshot.get();
    if (schemaSnapshot != null) {
      if (schemaSnapshot.snapshotCounter <= 0)
        throw new IllegalStateException("Thread local schema snapshot is cleared more times than it is done");

      schemaSnapshot.snapshotCounter--;

      if (schemaSnapshot.snapshotCounter == 0)
        threadLocalSchemaSnapshot.set(null);
    }
  }

  @Override
  public OImmutableSchema getImmutableSchemaSnapshot() {
    final ThreadLocalSchemaSnapshot schemaSnapshot = threadLocalSchemaSnapshot.get();

    OImmutableSchema immutableSchema = null;
    if (schemaSnapshot != null)
      immutableSchema = schemaSnapshot.schema;

    if (immutableSchema != null)
      return immutableSchema;

    if (schema == null)
      return null;

    OImmutableSchema newSchema;
    do {
      immutableSchema = schemaCache.get();
      if (immutableSchema != null && immutableSchema.version == schema.getVersion()) {
        newSchema = immutableSchema;
        break;
      }

      newSchema = schema.makeSnapshot();
    } while (!schemaCache.compareAndSet(immutableSchema, newSchema));

    return newSchema;
  }

  public OSecurity getSecurity() {
    return security;
  }

  public OIndexManagerProxy getIndexManager() {
    return indexManager;
  }

  public int getSchemaClusterId() {
    return schemaClusterId;
  }

  private void init(final boolean iLoad) {
    final ODatabaseDocumentInternal database = getDatabase();
    schemaClusterId = database.getClusterIdByName(CLUSTER_INTERNAL_NAME);

    schema = new OSchemaProxy(database.getStorage().getResource(OSchema.class.getSimpleName(), new Callable() {
      public OSchemaShared call() {
        ODatabaseDocumentInternal database = getDatabase();
        final OSchemaShared instance = new OSchemaShared(database.getStorageVersions().classesAreDetectedByClusterId());
        if (iLoad)
          instance.load();
        return instance;
      }
    }), database);

    indexManager = new OIndexManagerProxy(database.getStorage().getResource(OIndexManager.class.getSimpleName(),
        new Callable() {
          public OIndexManager call() {
            OIndexManager instance;
            if (database.getStorage() instanceof OStorageProxy)
              instance = new OIndexManagerRemote(database);
            else
              instance = new OIndexManagerShared(database);

            if (iLoad)
              try {
                instance.load();
              } catch (Exception e) {
                OLogManager.instance().error(this, "[OMetadata] Error on loading index manager, reset index configuration", e);
                instance.create();
              }

            return instance;
          }
        }), database);

    security = new OSecurityProxy(database.getStorage().getResource(OSecurity.class.getSimpleName(),
        new Callable() {
          public OSecurityShared call() {
            final OSecurityShared instance = new OSecurityShared();
            if (iLoad) {
              security = instance;
              instance.load();
            }
            return instance;
          }
        }), database);

    final Class securityClass = (Class) database.getProperty(ODatabase.OPTIONS.SECURITY
        .toString());
    if (securityClass != null)
      // INSTALL CUSTOM WRAPPED SECURITY
      try {
        final OSecurity wrapped = security;
        security = securityClass.getDeclaredConstructor(OSecurity.class, ODatabaseDocumentInternal.class).newInstance(wrapped,
            database);
      } catch (Exception e) {
        throw new OSecurityException("Cannot install custom security implementation (" + securityClass + ")", e);
      }

    functionLibrary = new OFunctionLibraryProxy(database.getStorage().getResource(OFunctionLibrary.class.getSimpleName(),
        new Callable() {
          public OFunctionLibrary call() {
            final OFunctionLibraryImpl instance = new OFunctionLibraryImpl();
            if (iLoad)
              instance.load();
            return instance;
          }
        }), database);
    scheduler = new OSchedulerListenerProxy(database.getStorage().getResource(OSchedulerListener.class.getSimpleName(),
        new Callable() {
          public OSchedulerListener call() {
            final OSchedulerListenerImpl instance = new OSchedulerListenerImpl();
            if (iLoad)
              instance.load();
            return instance;
          }
        }), database);
  }

  /**
   * Reloads the internal objects.
   */
  public void reload() {
    if (schema != null)
      schema.reload();
    if (indexManager != null)
      indexManager.reload();
    if (security != null)
      security.load();
    if (functionLibrary != null)
      functionLibrary.load();
  }

  /**
   * Closes internal objects
   */
  public void close() {
    if (schema != null)
      schema.close();
    if (security != null)
      security.close(false);
  }

  protected ODatabaseDocumentInternal getDatabase() {
    return ODatabaseRecordThreadLocal.INSTANCE.get();
  }

  public OFunctionLibrary getFunctionLibrary() {
    return functionLibrary;
  }

  public OSchedulerListener getSchedulerListener() {
    return scheduler;
  }

  private final class ThreadLocalSchemaSnapshot {
    private final OImmutableSchema schema;
    private int                    snapshotCounter = 1;

    private ThreadLocalSchemaSnapshot(OImmutableSchema schema) {
      this.schema = schema;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy