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

ai.grakn.kb.internal.cache.Cache Maven / Gradle / Ivy

There is a newer version: 1.4.3
Show newest version
/*
 * GRAKN.AI - THE KNOWLEDGE GRAPH
 * Copyright (C) 2018 Grakn Labs Ltd
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */

package ai.grakn.kb.internal.cache;

import ai.grakn.concept.RelationshipType;
import ai.grakn.concept.Role;
import ai.grakn.kb.internal.concept.ConceptImpl;

import javax.annotation.Nullable;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 

* An internal cached element *

* *

* An internal cached object which hits the database only when it needs to. * This is used to cache the components of ontological concepts. i.e. the fields of {@link ai.grakn.concept.Type}, * {@link RelationshipType}, and {@link Role}. *

* * @param The object it is caching * * @author fppt * */ public class Cache { //If no cache can produce the data then the database is read private final Supplier databaseReader; //Use to copy the cached value safely private final Cacheable cacheable; //Transaction bound. If this is not set it does not yet exist in the scope of the transaction. private final ThreadLocal valueTx = new ThreadLocal<>(); //Globally bound value which has already been persisted and acts as a shared component cache private Optional valueGlobal = Optional.empty(); //Flag indicating if this Cache should be flushed into the Session cache upon being disposed of private final boolean isSessionCache; //Flag indicating if this Cache can be cleared. // If this is false then the owner object must be deleted and garabe collected for the cache to die private final boolean isClearable; private Cache(CacheOwner owner, Cacheable cacheable, boolean isSessionCache, boolean isClearable, Supplier databaseReader){ this.isSessionCache = isSessionCache; this.isClearable = isClearable; this.cacheable = cacheable; this.databaseReader = databaseReader; owner.registerCache(this); } /** * Creates a {@link Cache} that will only exist within the context of a Transaction */ public static Cache createTxCache(CacheOwner owner, Cacheable cacheable, Supplier databaseReader){ return new Cache(owner, cacheable, false, true, databaseReader); } /** * Creates a {@link Cache} that will only flush to a central shared cache then the Transaction is disposed off */ public static Cache createSessionCache(CacheOwner owner, Cacheable cacheable, Supplier databaseReader){ return new Cache(owner, cacheable, true, true, databaseReader); } /** * Creates a session level {@link Cache} which cannot be cleared. * When creating these types of {@link Cache}s the only way to get rid of them is to remove the owner {@link ConceptImpl} */ public static Cache createPersistentCache(CacheOwner owner, Cacheable cacheable, Supplier databaseReader) { return new Cache(owner, cacheable, true, false, databaseReader); } /** * Retrieves the object in the cache. If nothing is cached the database is read. * * @return The cached object. */ @Nullable public V get(){ V value = valueTx.get(); if(value != null) return value; if(valueGlobal.isPresent()) value = cacheable.copy(valueGlobal.get()); if(value == null) value = databaseReader.get(); if(value == null) return null; valueTx.set(value); return valueTx.get(); } /** * Clears the cache. */ public void clear(){ if(isClearable) { valueTx.remove(); } } /** * Explicitly set the cache to a provided value * * @param value the value to be cached */ public void set(@Nullable V value){ valueTx.set(value); } /** * * @return true if there is anything stored in the cache */ public boolean isPresent(){ return valueTx.get() != null || valueGlobal.isPresent(); } /** * Mutates the cached value if something is cached. Otherwise does nothing. * * @param modifier the mutator function. */ public void ifPresent(Consumer modifier){ if(isPresent()){ modifier.accept(get()); } } /** * Takes the current value in the transaction cache if it is present and puts it in the valueGlobal reference so * that it can be accessed via all transactions. */ public void flush(){ if(isSessionCache && isPresent()) { V newValue = get(); if(!valueGlobal.isPresent() || !valueGlobal.get().equals(newValue)) valueGlobal = Optional.of(get()); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy