Skip to content

Commit

Permalink
Merge pull request #955 from jakewins/cypher-configurable-cache
Browse files Browse the repository at this point in the history
Added config setting for cypher query cache
  • Loading branch information
systay committed Oct 30, 2012
2 parents 029fe30 + 31780c5 commit 42fdff7
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 10 deletions.
25 changes: 19 additions & 6 deletions cypher/src/main/scala/org/neo4j/cypher/ExecutionEngine.scala
Expand Up @@ -25,9 +25,10 @@ import internal.LRUCache
import scala.collection.JavaConverters._
import java.lang.Error
import java.util.{Map => JavaMap}
import scala.deprecated
import scala.{Int, deprecated}
import org.neo4j.kernel.InternalAbstractGraphDatabase
import org.neo4j.graphdb.GraphDatabaseService
import org.neo4j.graphdb.factory.GraphDatabaseSettings

class ExecutionEngine(graph: GraphDatabaseService) {
checkScalaVersion()
Expand All @@ -38,9 +39,9 @@ class ExecutionEngine(graph: GraphDatabaseService) {

private def createCorrectParser() = if (graph.isInstanceOf[InternalAbstractGraphDatabase]) {
val database = graph.asInstanceOf[InternalAbstractGraphDatabase]
database.getConfig.getParams.asScala.get("cypher_parser_version") match {
case None => new CypherParser()
case Some(v) => new CypherParser(v)
database.getConfig.get(GraphDatabaseSettings.cypher_parser_version) match {
case v:String => new CypherParser(v)
case _ => new CypherParser()
}
}
else {
Expand All @@ -61,6 +62,9 @@ class ExecutionEngine(graph: GraphDatabaseService) {
def prepare(query: String): ExecutionPlan =
executionPlanCache.getOrElseUpdate(query, new ExecutionPlanImpl(parser.parse(query), graph))

def isPrepared(query : String) : Boolean =
executionPlanCache.containsKey(query)

@throws(classOf[SyntaxException])
@deprecated(message = "You should not parse queries manually any more. Use the execute(String) instead")
def execute(query: Query): ExecutionResult = execute(query, Map[String, Any]())
Expand All @@ -80,7 +84,16 @@ class ExecutionEngine(graph: GraphDatabaseService) {
}
}

private val cacheSize: Int = 100
private val executionPlanCache = new LRUCache[String, ExecutionPlan](cacheSize) {}
private val executionPlanCache = new LRUCache[String, ExecutionPlan]( getQueryCacheSize() ) {}

private def getQueryCacheSize() : Int = if (graph.isInstanceOf[InternalAbstractGraphDatabase]) {
val database = graph.asInstanceOf[InternalAbstractGraphDatabase]
database.getConfig.get(GraphDatabaseSettings.query_cache_size) match {
case v:java.lang.Integer => v
case _ => 100
}
} else {
100
}
}

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2002-2012 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.cypher

import org.scalatest.Assertions
import org.junit.Test
import org.neo4j.kernel.InternalAbstractGraphDatabase
import org.junit.Assert._
import java.util
import org.neo4j.graphdb.factory.GraphDatabaseSettings


class ConfigureQueryCacheTest extends GraphDatabaseTestBase with Assertions
{

@Test
def shouldBeAbleToChangeCacheSize()
{
// Given
val config: util.Map[String, String] = graph.asInstanceOf[InternalAbstractGraphDatabase].getConfig.getParams
config.put(GraphDatabaseSettings.query_cache_size.name(), "2");
graph.asInstanceOf[InternalAbstractGraphDatabase].getConfig.applyChanges(config)

val engine = new ExecutionEngine(graph);

// When
engine.prepare("START n=node(1) RETURN n")
engine.prepare("START n=node(2) RETURN n")
engine.prepare("START n=node(3) RETURN n")

// Then
assertTrue("Should have cached last query", engine.isPrepared("START n=node(3) RETURN n"))
assertTrue("Should have cached second query", engine.isPrepared("START n=node(2) RETURN n"))
assertFalse("Should not have cached first query", engine.isPrepared("START n=node(1) RETURN n"))
}

}
2 changes: 1 addition & 1 deletion kernel/src/main/java/org/neo4j/graphdb/config/Setting.java
Expand Up @@ -23,7 +23,7 @@
* This interface is available only for use, not for implementing. Implementing this interface is not expected, and
* backwards compatibility is not guaranteed for implementors.
*/
public interface Setting
public interface Setting<T>
{
public String name();

Expand Down
Expand Up @@ -49,7 +49,7 @@
*/
// Deprecated because we want to make this internal. Users should use Setting<T> instead.
@Deprecated
public abstract class GraphDatabaseSetting<T> implements Setting
public abstract class GraphDatabaseSetting<T> implements Setting<T>
{
public static final String TRUE = "true";
public static final String FALSE = "false";
Expand Down
Expand Up @@ -24,6 +24,7 @@
import static org.neo4j.graphdb.factory.GraphDatabaseSetting.FALSE;
import static org.neo4j.graphdb.factory.GraphDatabaseSetting.TRUE;

import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSetting.BooleanSetting;
import org.neo4j.graphdb.factory.GraphDatabaseSetting.DefaultValue;
import org.neo4j.graphdb.factory.GraphDatabaseSetting.FloatSetting;
Expand Down Expand Up @@ -99,10 +100,17 @@ public abstract class GraphDatabaseSettings
@Default(FALSE)
public static final BooleanSetting intercept_deserialized_transactions = new BooleanSetting( "intercept_deserialized_transactions" );

// Cypher version
// Cypher settings
// TODO: These should live with cypher
@Description( "Enable this to specify a parser other than the default one." )
public static final OptionsSetting cypher_parser_version = new CypherParserSetting();

@Description( "Used to set the number of Cypher query execution plans that are cached." )
@Default( "100" )
public static GraphDatabaseSetting<Integer> query_cache_size = new IntegerSetting( "query_cache_size",
"Query cache size must be at least 0.", 0, Integer.MAX_VALUE );


// Store files

@Description("The directory where the database files are located.")
Expand Down
Expand Up @@ -29,6 +29,7 @@
import java.util.List;
import java.util.Map;

import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSetting;
import org.neo4j.helpers.Function;
import org.neo4j.helpers.TimeUtil;
Expand Down Expand Up @@ -95,7 +96,7 @@ public Collection<String> getKeys()
return params.keySet();
}

public boolean isSet( GraphDatabaseSetting<?> graphDatabaseSetting )
public boolean isSet( Setting<?> graphDatabaseSetting )
{
return params.containsKey( graphDatabaseSetting.name() ) && params.get( graphDatabaseSetting.name() ) != null;
}
Expand Down

0 comments on commit 42fdff7

Please sign in to comment.