After running mvn clean package
add the built jars to HDFS:
hadoop fs -mkdir -p /iterators/legacy/foo hadoop fs -mkdir -p /iterators/legacy/bar hadoop fs -mkdir -p /iterators/new/foo hadoop fs -mkdir -p /iterators/new/bar hadoop fs -mkdir -p /iterators/system hadoop fs -put -f modules/example-iterators-a/target/example-iterators-a-1.0.0-SNAPSHOT.jar /iterators/legacy/foo/examples.jar hadoop fs -put -f modules/example-iterators-a/target/example-iterators-a-1.0.0-SNAPSHOT.jar /iterators/new/foo/examples.jar hadoop fs -put -f modules/example-iterators-b/target/example-iterators-b-1.0.0-SNAPSHOT.jar /iterators/legacy/bar/examples.jar hadoop fs -put -f modules/example-iterators-b/target/example-iterators-b-1.0.0-SNAPSHOT.jar /iterators/new/bar/examples.jar hadoop fs -cp -f /iterators/legacy/foo/examples.jar /iterators/system/examples.jar
Copy the new class loader jar to /tmp:
cp ./modules/vfs-class-loader/target/vfs-reloading-classloader-1.0.0-SNAPSHOT.jar /tmp/.
Stop Accumulo if it's running and add the following to the accumulo-env.sh:
a. Add vfs-reloading-classloader-1.0.0-SNAPSHOT.jar to CLASSPATH b. Add "-Djava.system.class.loader=org.apache.accumulo.classloader.vfs.AccumuloVFSClassLoader" to JAVA_OPTS c. Add "-Dvfs.class.loader.classpath=hdfs://localhost:9000/iterators/system/.*" to JAVA_OPTS d. Add "-Dvfs.classpath.monitor.seconds=10" to JAVA_OPTS e. (optional) Add "-Dvfs.class.loader.debug=true" to JAVA_OPTS
The goal of this test is to create a table, insert some data, and change the value of the data using an iterator that is loaded from HDFS via the AccumuloVFSClassLoader set up as the System ClassLoader. After setting the iterator the value should be foo
in subsequent scans.
createtable test insert a b c this_is_a_test scan setiter -class org.apache.accumulo.classloader.vfs.examples.ExampleIterator -scan -t test -name example -p 100 scan
In this test we will define a context name with an associated classpath. Then we will set that context on the table. Note that we did not change the iterator class name, the context classloader will load a new class with the same name. Scans performed after the context is set on the table should return the value bar
.
a. Set Accumulo Classpath Context property:
config -s general.vfs.context.classpath.cx1=hdfs://localhost:9000/iterators/legacy/bar/.* config -s general.vfs.context.classpath.cx1.delegation=post
b. Set Accumulo Table Context property:
config -t test -s table.classpath.context=cx1
c. Test context classpath iterator setting:
scan
This test will continue from the previous test and we will copy a jar over the jar referenced in the cx1 context classpath. The legacy AccumuloReloadingVFSClassLoader has a hard-coded filesystem monitor time of 5 minutes, so we will need to wait some number of minutes after overwriting the jar before the scans will return the new value of foo
.
a. Copy the example-a.jar over the context-examples.jar to force a reload. The value in the scan result should change from bar
back to foo
.
hadoop fs -rm /iterators/legacy/bar/examples.jar hadoop fs -cp -f /iterators/legacy/foo/examples.jar /iterators/legacy/bar/examples2.jar
b. Wait 10 minutes for a reload
c. Test that class loader has been updated and is returning the value ‘foo’
scan
In this test we will unset the properties that we set in the previous tests. Instead of testing reloading we are testing that changing the context will have the same effect on the iterator class.
a. Unset prior properties and define two contexts:
deleteiter -n example -t test -scan config -t test -d table.classpath.context config -d general.vfs.context.classpath.cx1 config -d general.vfs.context.classpath.cx1.delegation config -s general.vfs.context.classpath.cx1=hdfs://localhost:9000/iterators/new/foo/examples.jar config -s general.vfs.context.classpath.cx1.delegation=post config -s general.vfs.context.classpath.cx2=hdfs://localhost:9000/iterators/new/bar/examples.jar config -s general.vfs.context.classpath.cx2.delegation=post
b. Set Accumulo Table Context property:
config -t test -s table.classpath.context=cx1
c. Test context classpath iterator setting:
The initial scan command should return the value this_is_a_test
. After setting the iterator, the scan should return foo
.
scan setiter -class org.apache.accumulo.classloader.vfs.examples.ExampleIterator -scan -t test -name example -p 100 scan
d. Change the context Table Context property:
config -t test -s table.classpath.context=cx2
e. Test Context change
After the context change, the scan should return bar
.
scan
For this test we will use the new ReloadingVFSContextClassLoaderFactory for the table context classloaders.
a. First, let's clean up from the prior tests
droptable -f test config -d general.vfs.context.classpath.cx1 config -d general.vfs.context.classpath.cx1.delegation config -d general.vfs.context.classpath.cx2 config -d general.vfs.context.classpath.cx2.delegation
b. Then, create a file on the local filesystem for the context configuration.
{ "contexts": [ { "name": "cxA", "config": { "classPath": "hdfs://localhost:9000/iterators/new/foo/.*", "postDelegate": true, "monitorIntervalMs": 10000 } }, { "name": "cxB", "config": { "classPath": "hdfs://localhost:9000/iterators/new/bar/.*", "postDelegate": true, "monitorIntervalMs": 10000 } } ] }
c. Next, shutdown Accumulo and make the following changes in the accumulo configuration. Then re-start Accumulo.
a. Add "general.context.class.loader.factory=org.apache.accumulo.classloader.vfs.context.ReloadingVFSContextClassLoaderFactory" to accumulo.properties b. Add "-Dvfs.context.class.loader.config=file:///path/to/config/file.json" to JAVA_OPTS
If you did not remove the configuration for the new System ClassLoader, then the following test should work as it should load the ExampleIterator class from the System ClassLoader.
a. Create the table as we did in the last test. Create a table, insert some data, and change the value of the data using an iterator that is loaded from HDFS via the VFSClassLoader set up as the System ClassLoader. After setting the iterator the value should be foo
in subsequent scans.
createtable test insert a b c this_is_a_test scan setiter -class org.apache.accumulo.classloader.vfs.examples.ExampleIterator -scan -t test -name example -p 100 scan
Change the contexts on the table to test the classes being loaded from the different jars.
a. Set the table context to cxA. The scan on the table should return the value foo
.
config -t test -s table.classpath.context=cxA scan
b. Set the table context to cxB. The scan on the table should return the value bar
.
config -t test -s table.classpath.context=cxB scan
Now we are going to remove the jar from the cxB
context directory and replace it with the jar from the cxA
context directory.
a. Test the reloading by removing the existing jar from HDFS, copy /iterators/example-a/examples.jar to /iterators/example-b/examples2.jar and rescan. The value from the scan should be foo
. Note that the context set on the table is cxB
which returned bar
in the previous test.
NOTE: Overwriting the example-b/examples.jar does not work, it does not appear that VFS pulls down the jar from HDFS into the local cache directory and it continues to serve up the old class.
hadoop fs -rm /iterators/new/bar/examples.jar hadoop fs -cp -f /iterators/new/foo/examples.jar /iterators/new/bar/examples2.jar scan