package org.vertexium.accumulo;
import org.apache.accumulo.core.client.*;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Mutation;
import org.apache.accumulo.core.data.Range;
import org.apache.accumulo.core.data.Value;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.io.Text;
import org.junit.Before;
import org.junit.Test;
import org.vertexium.*;
import org.vertexium.accumulo.iterator.model.EdgeInfo;
import org.vertexium.accumulo.iterator.model.VertexiumInvalidKeyException;
import org.vertexium.accumulo.keys.DataTableRowKey;
import org.vertexium.accumulo.keys.KeyHelper;
import org.vertexium.accumulo.tools.DeleteHistoricalLegacyStreamingPropertyValueData;
import org.vertexium.property.MutablePropertyImpl;
import org.vertexium.property.StreamingPropertyValue;
import org.vertexium.test.GraphTestBase;
import org.vertexium.util.IterableUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.*;
import static junit.framework.TestCase.fail;
import static org.junit.Assert.*;
import static org.vertexium.accumulo.ElementMutationBuilder.EMPTY_TEXT;
import static org.vertexium.accumulo.iterator.model.KeyBase.VALUE_SEPARATOR;
import static org.vertexium.util.IterableUtils.toList;
public abstract class AccumuloGraphTestBase extends GraphTestBase {
@Before
@Override
public void before() throws Exception {
getAccumuloResource().dropGraph();
super.before();
}
@SuppressWarnings("unchecked")
@Override
protected Graph createGraph() throws AccumuloSecurityException, AccumuloException, VertexiumException, InterruptedException, IOException, URISyntaxException {
return AccumuloGraph.create(new AccumuloGraphConfiguration(getAccumuloResource().createConfig()));
}
public abstract AccumuloResource getAccumuloResource();
@Override
protected Authorizations createAuthorizations(String... auths) {
return new AccumuloAuthorizations(auths);
}
@Override
protected boolean isFetchHintNoneVertexQuerySupported() {
return false;
}
@Test
public void testFilterHints() {
Vertex v1 = graph.addVertex("v1", VISIBILITY_A, AUTHORIZATIONS_A);
v1.addPropertyValue("k1", "n1", "value1", VISIBILITY_A, AUTHORIZATIONS_A);
Vertex v2 = graph.addVertex("v2", VISIBILITY_A, AUTHORIZATIONS_A);
Edge e1 = graph.addEdge("e1", v1, v2, "label1", VISIBILITY_A, AUTHORIZATIONS_A);
e1.addPropertyValue("k1", "n1", "value1", VISIBILITY_A, AUTHORIZATIONS_A);
graph.addEdge("e2", v2, v1, "label1", VISIBILITY_A, AUTHORIZATIONS_A);
graph.flush();
v1 = graph.getVertex("v1", FetchHint.NONE, AUTHORIZATIONS_A);
assertNotNull(v1);
assertEquals(0, IterableUtils.count(v1.getProperties()));
assertEquals(0, IterableUtils.count(v1.getEdges(Direction.IN, AUTHORIZATIONS_A)));
assertEquals(0, IterableUtils.count(v1.getEdges(Direction.OUT, AUTHORIZATIONS_A)));
v1 = graph.getVertex("v1", graph.getDefaultFetchHints(), AUTHORIZATIONS_A);
assertNotNull(v1);
assertEquals(1, IterableUtils.count(v1.getProperties()));
assertEquals(1, IterableUtils.count(v1.getEdges(Direction.IN, AUTHORIZATIONS_A)));
assertEquals(1, IterableUtils.count(v1.getEdges(Direction.OUT, AUTHORIZATIONS_A)));
v1 = graph.getVertex("v1", EnumSet.of(FetchHint.PROPERTIES), AUTHORIZATIONS_A);
assertNotNull(v1);
assertEquals(1, IterableUtils.count(v1.getProperties()));
assertEquals(0, IterableUtils.count(v1.getEdges(Direction.IN, AUTHORIZATIONS_A)));
assertEquals(0, IterableUtils.count(v1.getEdges(Direction.OUT, AUTHORIZATIONS_A)));
v1 = graph.getVertex("v1", FetchHint.EDGE_REFS, AUTHORIZATIONS_A);
assertNotNull(v1);
assertEquals(0, IterableUtils.count(v1.getProperties()));
assertEquals(1, IterableUtils.count(v1.getEdges(Direction.IN, AUTHORIZATIONS_A)));
assertEquals(1, IterableUtils.count(v1.getEdges(Direction.OUT, AUTHORIZATIONS_A)));
v1 = graph.getVertex("v1", EnumSet.of(FetchHint.IN_EDGE_REFS), AUTHORIZATIONS_A);
assertNotNull(v1);
assertEquals(0, IterableUtils.count(v1.getProperties()));
assertEquals(1, IterableUtils.count(v1.getEdges(Direction.IN, AUTHORIZATIONS_A)));
assertEquals(0, IterableUtils.count(v1.getEdges(Direction.OUT, AUTHORIZATIONS_A)));
v1 = graph.getVertex("v1", EnumSet.of(FetchHint.OUT_EDGE_REFS), AUTHORIZATIONS_A);
assertNotNull(v1);
assertEquals(0, IterableUtils.count(v1.getProperties()));
assertEquals(0, IterableUtils.count(v1.getEdges(Direction.IN, AUTHORIZATIONS_A)));
assertEquals(1, IterableUtils.count(v1.getEdges(Direction.OUT, AUTHORIZATIONS_A)));
e1 = graph.getEdge("e1", FetchHint.NONE, AUTHORIZATIONS_A);
assertNotNull(e1);
assertEquals(0, IterableUtils.count(e1.getProperties()));
assertEquals("v1", e1.getVertexId(Direction.OUT));
assertEquals("v2", e1.getVertexId(Direction.IN));
e1 = graph.getEdge("e1", graph.getDefaultFetchHints(), AUTHORIZATIONS_A);
assertEquals(1, IterableUtils.count(e1.getProperties()));
assertEquals("v1", e1.getVertexId(Direction.OUT));
assertEquals("v2", e1.getVertexId(Direction.IN));
e1 = graph.getEdge("e1", EnumSet.of(FetchHint.PROPERTIES), AUTHORIZATIONS_A);
assertEquals(1, IterableUtils.count(e1.getProperties()));
assertEquals("v1", e1.getVertexId(Direction.OUT));
assertEquals("v2", e1.getVertexId(Direction.IN));
}
@Test
public void testStoringEmptyMetadata() {
Vertex v1 = graph.addVertex("v1", VISIBILITY_EMPTY, AUTHORIZATIONS_EMPTY);
Metadata metadata = new Metadata();
v1.addPropertyValue("prop1", "prop1", "val1", metadata, VISIBILITY_EMPTY, AUTHORIZATIONS_A_AND_B);
Vertex v2 = graph.addVertex("v2", VISIBILITY_EMPTY, AUTHORIZATIONS_EMPTY);
metadata = new Metadata();
metadata.add("meta1", "metavalue1", VISIBILITY_EMPTY);
v2.addPropertyValue("prop1", "prop1", "val1", metadata, VISIBILITY_EMPTY, AUTHORIZATIONS_A_AND_B);
graph.flush();
v1 = graph.getVertex("v1", FetchHint.ALL, AUTHORIZATIONS_EMPTY);
assertEquals(0, v1.getProperty("prop1", "prop1").getMetadata().entrySet().size());
v2 = graph.getVertex("v2", FetchHint.ALL, AUTHORIZATIONS_EMPTY);
metadata = v2.getProperty("prop1", "prop1").getMetadata();
assertEquals(1, metadata.entrySet().size());
assertEquals("metavalue1", metadata.getEntry("meta1", VISIBILITY_EMPTY).getValue());
AccumuloGraph accumuloGraph = (AccumuloGraph) graph;
ScannerBase vertexScanner = accumuloGraph.createVertexScanner(
graph.getDefaultFetchHints(),
AccumuloGraph.SINGLE_VERSION,
null,
null,
new Range("V", "W"),
AUTHORIZATIONS_EMPTY
);
RowIterator rows = new RowIterator(vertexScanner.iterator());
while (rows.hasNext()) {
Iterator<Map.Entry<Key, Value>> row = rows.next();
while (row.hasNext()) {
Map.Entry<Key, Value> col = row.next();
if (col.getKey().getColumnFamily().equals(AccumuloElement.CF_PROPERTY_METADATA)) {
if (col.getKey().getRow().toString().equals("Vv1")) {
assertEquals("", col.getValue().toString());
} else if (col.getKey().getRow().toString().equals("Vv2")) {
assertNotEquals("", col.getValue().toString());
} else {
fail("invalid vertex");
}
}
}
}
}
@SuppressWarnings("UnusedAssignment")
@Test
public void testGetKeyValuePairsForVertexMutation() {
VertexBuilder m = graph.prepareVertex("v1", 100L, VISIBILITY_A);
Metadata metadata = new Metadata();
metadata.add("key1_prop2_m1", "m1_value", VISIBILITY_A);
metadata.add("key1_prop2_m2", "m2_value", VISIBILITY_A);
m.addPropertyValue("key1", "author", "value_key1_author", metadata, 400L, VISIBILITY_A_AND_B);
metadata = new Metadata();
metadata.add("key1_prop1_m1", "m1_value", VISIBILITY_A);
metadata.add("key1_prop1_m2", "m2_value", VISIBILITY_A);
m.addPropertyValue("key1", "prop1", "value_key1_prop1", metadata, 200L, VISIBILITY_A);
metadata = new Metadata();
metadata.add("key2_prop1_m1", "m1_value", VISIBILITY_A);
metadata.add("key2_prop1_m2", "m2_value", VISIBILITY_A);
m.addPropertyValue("key2", "prop1", "value_key2_prop1", metadata, 300L, VISIBILITY_B);
List<KeyValuePair> keyValuePairs = toList(((VertexBuilderWithKeyValuePairs) m).getKeyValuePairs());
Collections.sort(keyValuePairs);
assertEquals(10, keyValuePairs.size());
String authorDeflated = substitutionDeflate("author");
int i = 0;
KeyValuePair pair;
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY, new Text(authorDeflated + "\u001fkey1"), new Text("a&b"), 400L), pair.getKey());
assertTrue(pair.getValue().toString().contains("value_key1_author"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY, new Text("prop1\u001fkey1"), new Text("a"), 200L), pair.getKey());
assertTrue(pair.getValue().toString().contains("value_key1_prop1"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY, new Text("prop1\u001fkey2"), new Text("b"), 300L), pair.getKey());
assertTrue(pair.getValue().toString().contains("value_key2_prop1"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY_METADATA, new Text(authorDeflated + "\u001fkey1\u001Fa&b\u001Fkey1_prop2_m1"), new Text("a"), 400L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m1_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY_METADATA, new Text(authorDeflated + "\u001fkey1\u001Fa&b\u001Fkey1_prop2_m2"), new Text("a"), 400L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m2_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey1\u001Fa\u001Fkey1_prop1_m1"), new Text("a"), 200L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m1_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey1\u001Fa\u001Fkey1_prop1_m2"), new Text("a"), 200L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m2_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey2\u001Fb\u001Fkey2_prop1_m1"), new Text("a"), 300L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m1_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey2\u001Fb\u001Fkey2_prop1_m2"), new Text("a"), 300L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m2_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("v1"), AccumuloVertex.CF_SIGNAL, EMPTY_TEXT, new Text("a"), 100L), pair.getKey());
assertEquals(ElementMutationBuilder.EMPTY_VALUE, pair.getValue());
}
@SuppressWarnings("UnusedAssignment")
@Test
public void testGetKeyValuePairsForEdgeMutation() {
EdgeBuilderByVertexId m = graph.prepareEdge("e1", "v1", "v2", "label1", 100L, VISIBILITY_A);
Metadata metadata = new Metadata();
metadata.add("key1_prop2_m1", "m1_value", VISIBILITY_A);
metadata.add("key1_prop2_m2", "m2_value", VISIBILITY_A);
m.addPropertyValue("key1", "author", "value_key1_author", metadata, 400L, VISIBILITY_A_AND_B);
metadata = new Metadata();
metadata.add("key1_prop1_m1", "m1_value", VISIBILITY_A);
metadata.add("key1_prop1_m2", "m2_value", VISIBILITY_A);
m.addPropertyValue("key1", "prop1", "value_key1_prop1", metadata, 200L, VISIBILITY_A);
metadata = new Metadata();
metadata.add("key2_prop1_m1", "m1_value", VISIBILITY_A);
metadata.add("key2_prop1_m2", "m2_value", VISIBILITY_A);
m.addPropertyValue("key2", "prop1", "value_key2_prop1", metadata, 300L, VISIBILITY_B);
List<KeyValuePair> keyValuePairs = toList(((EdgeBuilderWithKeyValuePairs) m).getEdgeTableKeyValuePairs());
Collections.sort(keyValuePairs);
assertEquals(12, keyValuePairs.size());
String authorDeflated = substitutionDeflate("author");
int i = 0;
KeyValuePair pair;
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloEdge.CF_SIGNAL, new Text("label1"), new Text("a"), 100L), pair.getKey());
assertEquals(ElementMutationBuilder.EMPTY_VALUE, pair.getValue());
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloEdge.CF_IN_VERTEX, new Text("v2"), new Text("a"), 100L), pair.getKey());
assertEquals(ElementMutationBuilder.EMPTY_VALUE, pair.getValue());
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloEdge.CF_OUT_VERTEX, new Text("v1"), new Text("a"), 100L), pair.getKey());
assertEquals(ElementMutationBuilder.EMPTY_VALUE, pair.getValue());
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY, new Text(authorDeflated + "\u001fkey1"), new Text("a&b"), 400L), pair.getKey());
assertTrue(pair.getValue().toString().contains("value_key1_author"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY, new Text("prop1\u001fkey1"), new Text("a"), 200L), pair.getKey());
assertTrue(pair.getValue().toString().contains("value_key1_prop1"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY, new Text("prop1\u001fkey2"), new Text("b"), 300L), pair.getKey());
assertTrue(pair.getValue().toString().contains("value_key2_prop1"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY_METADATA, new Text(authorDeflated + "\u001fkey1\u001Fa&b\u001Fkey1_prop2_m1"), new Text("a"), 400L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m1_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY_METADATA, new Text(authorDeflated + "\u001fkey1\u001Fa&b\u001Fkey1_prop2_m2"), new Text("a"), 400L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m2_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey1\u001Fa\u001Fkey1_prop1_m1"), new Text("a"), 200L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m1_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey1\u001Fa\u001Fkey1_prop1_m2"), new Text("a"), 200L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m2_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey2\u001Fb\u001Fkey2_prop1_m1"), new Text("a"), 300L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m1_value"));
pair = keyValuePairs.get(i++);
assertEquals(new Key(new Text("e1"), AccumuloElement.CF_PROPERTY_METADATA, new Text("prop1\u001fkey2\u001Fb\u001Fkey2_prop1_m2"), new Text("a"), 300L), pair.getKey());
assertTrue(pair.getValue().toString().contains("m2_value"));
i = 0;
keyValuePairs = toList(((EdgeBuilderWithKeyValuePairs) m).getVertexTableKeyValuePairs());
Collections.sort(keyValuePairs);
assertEquals(2, keyValuePairs.size());
pair = keyValuePairs.get(i++);
org.vertexium.accumulo.iterator.model.EdgeInfo edgeInfo = new EdgeInfo(getGraph().getNameSubstitutionStrategy().deflate("label1"), "v2");
assertEquals(new Key(new Text("v1"), AccumuloVertex.CF_OUT_EDGE, new Text("e1"), new Text("a"), 100L), pair.getKey());
assertEquals(edgeInfo.toValue(), pair.getValue());
pair = keyValuePairs.get(i++);
edgeInfo = new EdgeInfo(getGraph().getNameSubstitutionStrategy().deflate("label1"), "v1");
assertEquals(new Key(new Text("v2"), AccumuloVertex.CF_IN_EDGE, new Text("e1"), new Text("a"), 100L), pair.getKey());
assertEquals(edgeInfo.toValue(), pair.getValue());
}
protected abstract String substitutionDeflate(String str);
@Test
public void testPropertyWithValueSeparator() {
try {
graph.prepareVertex("v1", VISIBILITY_EMPTY)
.addPropertyValue("prop1" + VALUE_SEPARATOR, "name1", "test", VISIBILITY_EMPTY)
.save(AUTHORIZATIONS_EMPTY);
throw new RuntimeException("Should have thrown a bad character exception");
} catch (VertexiumInvalidKeyException ex) {
// ok
}
}
@Test
public void testListSplits() throws AccumuloSecurityException, TableNotFoundException, AccumuloException {
SortedSet<Text> keys = new TreeSet<>();
keys.add(new Text("j"));
getGraph().getConnector().tableOperations().addSplits(getGraph().getVerticesTableName(), keys);
keys = new TreeSet<>();
keys.add(new Text("k"));
getGraph().getConnector().tableOperations().addSplits(getGraph().getEdgesTableName(), keys);
keys = new TreeSet<>();
keys.add(new Text("l"));
getGraph().getConnector().tableOperations().addSplits(getGraph().getDataTableName(), keys);
List<org.vertexium.Range> verticesTableSplits = toList(getGraph().listVerticesTableSplits());
assertEquals(2, verticesTableSplits.size());
assertEquals(null, verticesTableSplits.get(0).getInclusiveStart());
assertEquals("j", verticesTableSplits.get(0).getExclusiveEnd());
assertEquals("j", verticesTableSplits.get(1).getInclusiveStart());
assertEquals(null, verticesTableSplits.get(1).getExclusiveEnd());
List<org.vertexium.Range> edgesTableSplits = toList(getGraph().listEdgesTableSplits());
assertEquals(2, edgesTableSplits.size());
assertEquals(null, edgesTableSplits.get(0).getInclusiveStart());
assertEquals("k", edgesTableSplits.get(0).getExclusiveEnd());
assertEquals("k", edgesTableSplits.get(1).getInclusiveStart());
assertEquals(null, edgesTableSplits.get(1).getExclusiveEnd());
List<org.vertexium.Range> dataTableSplits = toList(getGraph().listDataTableSplits());
assertEquals(2, dataTableSplits.size());
assertEquals(null, dataTableSplits.get(0).getInclusiveStart());
assertEquals("l", dataTableSplits.get(0).getExclusiveEnd());
assertEquals("l", dataTableSplits.get(1).getInclusiveStart());
assertEquals(null, dataTableSplits.get(1).getExclusiveEnd());
}
@Test
public void testLegacyStreamingPropertyValuesWithTimestampInRowKey() throws Exception {
String vertexId = "v1";
graph.prepareVertex(vertexId, VISIBILITY_EMPTY)
.save(AUTHORIZATIONS_EMPTY);
graph.flush();
long timestamp = new Date().getTime();
String propertyKey = "k1";
String propertyName = "prop1";
String propertyValue = "Hello";
addLegacySPVData(vertexId, timestamp, propertyKey, propertyName, propertyValue);
getGraph().flush();
// verify we can still retrieve it
Vertex v1 = graph.getVertex(vertexId, AUTHORIZATIONS_EMPTY);
StreamingPropertyValue spv = (StreamingPropertyValue) v1.getPropertyValue(propertyKey, propertyName);
assertNotNull("spv should not be null", spv);
assertEquals(propertyValue, IOUtils.toString(spv.getInputStream()));
}
@Test
public void testDeleteHistoricalLegacyStreamingPropertyValueData_keysWithCommonPrefix() throws Exception {
String vertexId = "v1";
graph.prepareVertex(vertexId, VISIBILITY_EMPTY)
.save(AUTHORIZATIONS_EMPTY);
graph.flush();
long timestamp = new Date().getTime();
String propertyKey1 = "prefix";
String propertyKey2 = "prefixSuffix";
String propertyName = "prop1";
String propertyValue = "Hello";
addLegacySPVData(vertexId, timestamp, propertyKey1, propertyName, propertyValue);
addLegacySPVData(vertexId, timestamp, propertyKey2, propertyName, propertyValue);
getGraph().flush();
new DeleteHistoricalLegacyStreamingPropertyValueData(getGraph())
.execute(
new DeleteHistoricalLegacyStreamingPropertyValueData.Options()
.setDryRun(false)
.setVersionsToKeep(1),
AUTHORIZATIONS_EMPTY
);
// verify we can still retrieve it
Vertex v1 = graph.getVertex(vertexId, AUTHORIZATIONS_EMPTY);
StreamingPropertyValue spv = (StreamingPropertyValue) v1.getPropertyValue(propertyKey1, propertyName);
assertNotNull("spv should not be null", spv);
assertEquals(propertyValue, IOUtils.toString(spv.getInputStream()));
spv = (StreamingPropertyValue) v1.getPropertyValue(propertyKey2, propertyName);
assertNotNull("spv should not be null", spv);
assertEquals(propertyValue, IOUtils.toString(spv.getInputStream()));
}
@Test
public void testDeleteHistoricalLegacyStreamingPropertyValueData_mixOfOldAndNew() throws Exception {
String vertexId = "v1";
graph.prepareVertex(vertexId, VISIBILITY_EMPTY)
.save(AUTHORIZATIONS_EMPTY);
graph.flush();
long timestamp = new Date().getTime();
String propertyKey = "prefix";
String propertyName = "prop1";
String propertyValue1 = "Hello1";
String propertyValue2 = "Hello2";
addLegacySPVData(vertexId, timestamp - 100, propertyKey, propertyName, propertyValue1);
StreamingPropertyValue newSpv = StreamingPropertyValue.create(propertyValue2);
getGraph().getVertex("v1", AUTHORIZATIONS_EMPTY)
.addPropertyValue(propertyKey, propertyName, newSpv, VISIBILITY_EMPTY, AUTHORIZATIONS_EMPTY);
getGraph().flush();
new DeleteHistoricalLegacyStreamingPropertyValueData(getGraph())
.execute(
new DeleteHistoricalLegacyStreamingPropertyValueData.Options()
.setDryRun(false)
.setVersionsToKeep(1),
AUTHORIZATIONS_EMPTY
);
// verify we can still retrieve it
Vertex v1 = graph.getVertex(vertexId, AUTHORIZATIONS_EMPTY);
StreamingPropertyValue spv = (StreamingPropertyValue) v1.getPropertyValue(propertyKey, propertyName);
assertNotNull("spv should not be null", spv);
assertEquals(propertyValue2, IOUtils.toString(spv.getInputStream()));
}
// need to add it manually because the key format changed
private void addLegacySPVData(
String vertexId,
long timestamp,
String propertyKey,
String propertyName,
String propertyValue
) throws MutationsRejectedException {
String dataRowKey = new DataTableRowKey(vertexId, propertyKey, propertyName).getRowKey() + VALUE_SEPARATOR + timestamp;
Mutation addPropertyMutation = new Mutation(vertexId);
byte[] data = propertyValue.getBytes();
StreamingPropertyValue spv = StreamingPropertyValue.create(propertyValue);
StreamingPropertyValueTableRef spvValue = new StreamingPropertyValueTableRef(dataRowKey, spv, data);
Metadata metadata = new Metadata();
Property property = new MutablePropertyImpl(propertyKey, propertyName, spvValue, metadata, timestamp, new HashSet<>(), new Visibility(""), FetchHint.ALL);
Text columnQualifier = KeyHelper.getColumnQualifierFromPropertyColumnQualifier(property, getGraph().getNameSubstitutionStrategy());
addPropertyMutation.put(AccumuloElement.CF_PROPERTY, columnQualifier, new Value(getGraph().getVertexiumSerializer().objectToBytes(spvValue)));
getGraph().getVerticesWriter().addMutation(addPropertyMutation);
Mutation addDataMutation = new Mutation(dataRowKey);
addDataMutation.put(EMPTY_TEXT, EMPTY_TEXT, timestamp - 1000, new Value(data));
getGraph().getDataWriter().addMutation(addDataMutation);
getGraph().flush();
}
@Override
public AccumuloGraph getGraph() {
return (AccumuloGraph) super.getGraph();
}
}