Skip to content

Commit

Permalink
rfe10257 support script loading in sessions
Browse files Browse the repository at this point in the history
Adds method to make use of the param in the http protocol.

ServerCodeTests uploads a script to verify the param works
and fails if the param is not set.

tests-added:     yes
tests-run:       prepush
performance:     no impact

<release-note>
rfe10257 support script loading in sessions

Added method to AGRepositoryConnection:
addSessionLoadScript(String scriptName)

When a dedicated session is created, the named scripts
on the AllegroGraph Server will be loaded.
</release-note>

Change-Id: I5d56931db7e7345ba6e25bf6825884262315c645
Reviewed-on: https://gerrit.franz.com:9080/1192
Reviewed-by: Ahmon Dancy <dancy@franz.com>
Reviewed-by: John O'Rourke <john.orourke@franz.com>
Tested-by: Kevin Layer <layer@franz.com>
  • Loading branch information
Mike Hinchey authored and dklayer committed Feb 22, 2011
1 parent 0859c86 commit 0995a5b
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 51 deletions.
32 changes: 24 additions & 8 deletions src/com/franz/agraph/http/AGHttpRepoClient.java
Expand Up @@ -102,6 +102,7 @@ public static void setDefaultSessionLifetime(int lifetimeInSeconds)
private int uploadCommitPeriod = 0;
private String sessionRoot, repoRoot;
private boolean loadInitFile = false;
private List<String> scripts = null;

// TODO: choose proper defaults
private TupleQueryResultFormat preferredTQRFormat = TupleQueryResultFormat.SPARQL;
Expand Down Expand Up @@ -160,6 +161,16 @@ public boolean getSessionLoadInitFile() {
return loadInitFile;
}

/**
* Adds a 'script' for a dedicated session spawned by this instance.
*/
public void addSessionLoadScript(String scriptName) {
if (this.scripts == null) {
this.scripts = new ArrayList<String>();
}
this.scripts.add(scriptName);
}

public TupleQueryResultFormat getPreferredTQRFormat() {
return preferredTQRFormat;
}
Expand Down Expand Up @@ -198,16 +209,21 @@ private void useDedicatedSession(boolean autoCommit)
if (sessionRoot == null) {
String url = getSessionURL(getRoot());
Header[] headers = new Header[0];
NameValuePair[] data = {
new NameValuePair(AGProtocol.LIFETIME_PARAM_NAME, Integer
.toString(lifetimeInSeconds)),
new NameValuePair(AGProtocol.LOAD_INIT_FILE_PARAM_NAME, Boolean
.toString(loadInitFile)),
new NameValuePair(AGProtocol.AUTOCOMMIT_PARAM_NAME, Boolean
.toString(autoCommit)) };
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new NameValuePair(AGProtocol.LIFETIME_PARAM_NAME,
Integer.toString(lifetimeInSeconds)));
params.add(new NameValuePair(AGProtocol.AUTOCOMMIT_PARAM_NAME,
Boolean.toString(autoCommit)));
params.add(new NameValuePair(AGProtocol.LOAD_INIT_FILE_PARAM_NAME,
Boolean.toString(loadInitFile)));
if (scripts != null) {
for (String script : scripts) {
params.add(new NameValuePair("script", script));
}
}
AGResponseHandler handler = new AGResponseHandler("");
try {
getHTTPClient().post(url, headers, data, null, handler);
getHTTPClient().post(url, headers, params.toArray(new NameValuePair[params.size()]), null, handler);
} catch (RDFParseException e) {
// bug.
throw new RuntimeException(e);
Expand Down
20 changes: 18 additions & 2 deletions src/com/franz/agraph/repository/AGRepositoryConnection.java
Expand Up @@ -81,8 +81,9 @@
* A session should be {@link #close() closed} when finished.
* </p>
*
* <p>{@link #setSessionLoadInitFile(boolean) InitFiles} are loaded into
* the server only for sessions. See
* <p>{@link #setSessionLoadInitFile(boolean) InitFiles}
* and {@link #addSessionLoadScript(String) Scripts}
* are loaded into the server only for sessions. See
* <a href="http://www.franz.com/agraph/support/documentation/v4/http-protocol.html#scripting"
* target="_top">Scripting in HTTP Protocol</a> and
* <a href="http://www.franz.com/agraph/support/documentation/v4/agwebview.html"
Expand All @@ -97,6 +98,7 @@
* <li>{@link #ping()}</li>
* <li>{@link #setSessionLifetime(int)} and {@link #getSessionLifetime()}</li>
* <li>{@link #setSessionLoadInitFile(boolean)}</li>
* <li>{@link #addSessionLoadScript(String)}</li>
* <li>{@link #close()}</li>
* </ul></p>
*/
Expand Down Expand Up @@ -1102,6 +1104,20 @@ public void setSessionLoadInitFile(boolean loadInitFile) {
getHttpRepoClient().setSessionLoadInitFile(loadInitFile);
}

/**
* Adds a 'script' for a dedicated session spawned by this connection.
* This method does not create a session.
* May be called multiple times for different scripts.
* The script text must already be uploaded to the user.
*
* <p>Scripts are server code that may be loaded during a session.</p>
*
* <p>See also: <a href="#sessions">Session overview</a>.</p>
*/
public void addSessionLoadScript(String scriptName) {
getHttpRepoClient().addSessionLoadScript(scriptName);
}

/**
* Enables the spogi cache in this repository.
*
Expand Down
121 changes: 84 additions & 37 deletions src/test/ServerCodeTests.java
Expand Up @@ -19,6 +19,7 @@
import junit.framework.Assert;

import org.apache.commons.httpclient.methods.FileRequestEntity;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openrdf.model.Statement;
Expand Down Expand Up @@ -46,6 +47,11 @@

@SuppressWarnings("deprecation")
public class ServerCodeTests extends AGAbstractTest {

private static String RULES = "java-rules.prolog";
private static File STORED_PROC = new File("src/test/ag-test-stored-proc.cl");
private static File RULES_FILE = new File("src/tutorial/java-rules.txt");


static class AGServerCode {
private final AGServer server;
Expand All @@ -66,6 +72,10 @@ public void putScript(String path, File script) throws Exception {
new FileRequestEntity(script, "text/plain"));
}

public void deleteScript(String path) throws Exception {
http().delete(server.getServerURL() + "/scripts/" + path, null, null);
}

public TupleQueryResult initFile() throws Exception {
return http().getTupleQueryResult(server.getServerURL() + "/initfile");
}
Expand All @@ -86,7 +96,14 @@ public void deleteInitFile() throws Exception {
@BeforeClass
public static void installScripts() throws Exception {
serverCode = new AGServerCode(server);
serverCode.putScript(SProcTest.FASL, new File("src/test/ag-test-stored-proc.cl"));
serverCode.putScript(SProcTest.SCRIPT, STORED_PROC);

serverCode.deleteInitFile(); // clean
}

@AfterClass
public static void cleanup() throws Exception {
serverCode.deleteInitFile();
}

@Test
Expand Down Expand Up @@ -115,55 +132,55 @@ public void storedProcs_encoding_rfe10189() throws Exception {
* Example class of how a user might wrap a stored-proc for convenience.
*/
class SProcTest {
static final String FASL = "ag-test-stored-proc.cl";
static final String SCRIPT = "ag-test-stored-proc.cl";

private final AGRepositoryConnection conn;
SProcTest(AGRepositoryConnection conn) {
this.conn = conn;
}

String addTwoStrings(String a, String b) throws Exception {
return (String) conn.callStoredProc("add-two-strings", FASL, a, b);
return (String) conn.callStoredProc("add-two-strings", SCRIPT, a, b);
}

int addTwoInts(int a, int b) throws Exception {
return (Integer) conn.callStoredProc("add-two-ints", FASL, a, b);
return (Integer) conn.callStoredProc("add-two-ints", SCRIPT, a, b);
}

String addTwoVecStrings(String a, String b) throws Exception {
return (String) conn.callStoredProc("add-two-vec-strings", FASL, a, b);
return (String) conn.callStoredProc("add-two-vec-strings", SCRIPT, a, b);
}

String addTwoVecStringsError() throws Exception {
return (String) conn.callStoredProc("add-two-vec-strings", FASL);
return (String) conn.callStoredProc("add-two-vec-strings", SCRIPT);
}

int addTwoVecInts(int a, int b) throws Exception {
return (Integer) conn.callStoredProc("add-two-vec-ints", FASL, a, b);
return (Integer) conn.callStoredProc("add-two-vec-ints", SCRIPT, a, b);
}

Object bestBeNull(String a) throws Exception {
return conn.callStoredProc("best-be-nil", FASL, a);
return conn.callStoredProc("best-be-nil", SCRIPT, a);
}

Object returnAllTypes() throws Exception {
return conn.callStoredProc("return-all-types", FASL);
return conn.callStoredProc("return-all-types", SCRIPT);
}

Object identity(Object input) throws Exception {
return conn.callStoredProc("identity", FASL, input);
return conn.callStoredProc("identity", SCRIPT, input);
}

Object checkAllTypes(Object input) throws Exception {
return conn.callStoredProc("check-all-types", FASL, input);
return conn.callStoredProc("check-all-types", SCRIPT, input);
}

Object addATripleInt(int i) throws Exception {
return conn.callStoredProc("add-a-triple-int", FASL, i);
return conn.callStoredProc("add-a-triple-int", SCRIPT, i);
}

Statement getATripleInt(int i) throws Exception {
String r = (String) conn.callStoredProc("get-a-triple-int", FASL, i);
String r = (String) conn.callStoredProc("get-a-triple-int", SCRIPT, i);
Statement st = parseNtriples(r);
return st;
}
Expand Down Expand Up @@ -206,7 +223,7 @@ public void encoding_all_types_rfe10189() throws Exception {
@Test
public void storedProcsEncoded_rfe10189() throws Exception {
String response = (String) AGDeserializer.decodeAndDeserialize(
conn.getHttpRepoClient().callStoredProcEncoded("add-two-strings", SProcTest.FASL,
conn.getHttpRepoClient().callStoredProcEncoded("add-two-strings", SProcTest.SCRIPT,
AGSerializer.serializeAndEncode(
new String[] {"123", "456"})));
assertEquals(579, Integer.parseInt(response));
Expand Down Expand Up @@ -264,6 +281,8 @@ public void storedProcs_triples_rfe10189() throws Exception {
//Assert.assertNotNull("add-a-triple", sp.addATriple(vf.createURI("http://test.com/s"), vf.createURI("http://test.com/p"), vf.createURI("http://test.com/p")));
}

// rfe10256: support loadInitFile param

/**
* @see TutorialExamples#example18()
* @see TutorialTests#example18()
Expand All @@ -282,11 +301,24 @@ public TupleQuery rfe10256_setup() throws Exception{
return conn.prepareTupleQuery(AGQueryLanguage.PROLOG, queryString);
}

private void rfe10256_fail(TupleQuery tupleQuery) throws QueryEvaluationException {
try {
tupleQuery.evaluate();
fail("expected QueryEvaluationException");
} catch (QueryEvaluationException e) {
if (e.getMessage().contains("attempt to call `#:uncle/2' which is an undefined function. (500)")) {
// good
} else {
throw e;
}
}
}

@Test
public void rfe10256_loadInitFile() throws Exception{
serverCode.deleteInitFile(); // clean before test

serverCode.putInitFile(new File("src/tutorial/java-rules.txt"));
serverCode.putInitFile(RULES_FILE);
// note, setSessionLoadInitFile must be done before setAutoCommit in example6_setup
conn.setSessionLoadInitFile(true);
TupleQuery tupleQuery = rfe10256_setup();
Expand All @@ -298,34 +330,49 @@ public void rfe10256_doNotPut_InitFile() throws Exception{
serverCode.deleteInitFile(); // clean before test

TupleQuery tupleQuery = rfe10256_setup();
try {
tupleQuery.evaluate();
fail("expected QueryEvaluationException");
} catch (QueryEvaluationException e) {
if (e.getMessage().contains("attempt to call `#:uncle/2' which is an undefined function. (500)")) {
// good
} else {
throw e;
}
}
rfe10256_fail(tupleQuery);
}

@Test
public void rfe10256_doNotUse_InitFile() throws Exception{
serverCode.deleteInitFile(); // clean before test

serverCode.putInitFile(new File("src/tutorial/java-rules.txt"));
serverCode.putInitFile(RULES_FILE);
TupleQuery tupleQuery = rfe10256_setup();
rfe10256_fail(tupleQuery);
}

// rfe10257: support script param

@Test
public void rfe10257_script() throws Exception{
serverCode.deleteInitFile(); // clean before test
serverCode.deleteScript(RULES); // clean before test

serverCode.putScript(RULES, RULES_FILE);
// note, addSessionLoadScript must be done before setAutoCommit in example6_setup
conn.addSessionLoadScript(RULES);
TupleQuery tupleQuery = rfe10256_setup();
assertEquals(52, statementSet(tupleQuery.evaluate()).size());
}

@Test
public void rfe10257_doNotPut_script() throws Exception{
serverCode.deleteInitFile(); // clean before test
serverCode.deleteScript(RULES); // clean before test

TupleQuery tupleQuery = rfe10256_setup();
rfe10256_fail(tupleQuery);
}

@Test
public void rfe10257_doNotUse_script() throws Exception{
serverCode.deleteInitFile(); // clean before test
serverCode.deleteScript(RULES); // clean before test

serverCode.putScript(RULES, RULES_FILE);
TupleQuery tupleQuery = rfe10256_setup();
try {
tupleQuery.evaluate();
fail("expected QueryEvaluationException");
} catch (QueryEvaluationException e) {
if (e.getMessage().contains("attempt to call `#:uncle/2' which is an undefined function. (500)")) {
// good
} else {
throw e;
}
}
rfe10256_fail(tupleQuery);
}

}
21 changes: 18 additions & 3 deletions src/test/TestRunner.java
Expand Up @@ -75,14 +75,16 @@ public static void main(String[] args) throws Exception {
e.printStackTrace(System.err);
System.err.println("FAIL Testcase: " + m.getName() + " took " + (System.currentTimeMillis() - start) + " ms");
} finally {
invokeAll(methodsAnnotated(testClass, After.class), false, test);
System.out.flush();
System.out.flush();
invokeAllIgnoreExceptions(Util.reverse( methodsAnnotated(testClass, After.class)), false, test);
System.out.flush();
System.err.flush();
Thread.sleep(2);
}
}
} finally {
invokeAll(methodsAnnotated(testClass, AfterClass.class), false, testClass);
System.out.flush();
invokeAllIgnoreExceptions(Util.reverse( methodsAnnotated(testClass, AfterClass.class) ), false, testClass);
}
}
if (failures > 0) {
Expand Down Expand Up @@ -175,4 +177,17 @@ static List<Object> invokeAll(List<Method> methods,
return r;
}

static List<Object> invokeAllIgnoreExceptions(List<Method> methods,
boolean logExceptions, Object obj, Object...args) throws Exception {
List<Object> r = new ArrayList<Object>();
for (Method m : methods) {
try {
r.add( m.invoke(obj, args) );
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
return r;
}

}
10 changes: 9 additions & 1 deletion src/test/Util.java
@@ -1,5 +1,5 @@
/******************************************************************************
** Copyright (c) 2008-2010 Franz Inc.
** Copyright (c) 2008-2011 Franz Inc.
** All rights reserved. This program and the accompanying materials
** are made available under the terms of the Eclipse Public License v1.0
** which accompanies this distribution, and is available at
Expand All @@ -17,12 +17,14 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.zip.GZIPOutputStream;

import com.franz.util.Closeable;

public class Util extends com.franz.util.Util {


public static String get(String[] arr, int i, String defaultVal) {
if (arr != null && arr.length > i) {
Expand Down Expand Up @@ -193,4 +195,10 @@ public static List toListDeep(Object obj) {
return out;
}

public static List reverse(List list) {
list = new ArrayList(list);
Collections.reverse(list);
return list;
}

}

0 comments on commit 0995a5b

Please sign in to comment.