hugegraph-1379 support restore graph in restoring mode and merging mode

implement: #182

Change-Id: I7c2c85435af01c5d27279076d0473685b8f23f34
This commit is contained in:
zhangyi51 2018-08-06 17:19:53 +08:00 committed by Linary
parent 2c356c8a1e
commit 255df7e945
41 changed files with 1367 additions and 316 deletions

View File

@ -101,7 +101,7 @@
</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Implementation-Version>0.30.0.0</Implementation-Version>
<Implementation-Version>0.31.0.0</Implementation-Version>
</manifestEntries>
</archive>
</configuration>

View File

@ -20,6 +20,7 @@
package com.baidu.hugegraph.api;
import java.io.File;
import java.util.Map;
import java.util.Set;
import javax.annotation.security.RolesAllowed;
@ -44,9 +45,10 @@ import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.SchemaManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@ -152,38 +154,32 @@ public class GraphsAPI extends API {
@PUT
@Timed
@Path("{name}/restoring")
@Path("{name}/mode")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public Object restoring(@Context GraphManager manager,
@PathParam("name") String name,
JsonRestoring jsonRestoring) {
LOG.debug("Set restoring status to: '{}' of graph '{}'",
jsonRestoring, name);
public Map<String, GraphMode> mode(@Context GraphManager manager,
@PathParam("name") String name,
GraphMode mode) {
LOG.debug("Set mode to: '{}' of graph '{}'", mode, name);
E.checkArgument(mode != null, "Graph mode can't be null");
HugeGraph g = graph(manager, name);
g.restoring(jsonRestoring.restoring);
return jsonRestoring;
g.mode(mode);
return ImmutableMap.of("mode", mode);
}
@GET
@Timed
@Path("{name}/restoring")
@Path("{name}/mode")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public Object restoring(@Context GraphManager manager,
@PathParam("name") String name) {
LOG.debug("Get restoring status of graph '{}'", name);
public Map<String, GraphMode> mode(@Context GraphManager manager,
@PathParam("name") String name) {
LOG.debug("Get mode of graph '{}'", name);
HugeGraph g = graph(manager, name);
return ImmutableMap.of("restoring", g.restoring());
}
private static class JsonRestoring {
@JsonProperty("restoring")
public boolean restoring;
return ImmutableMap.of("mode", g.mode());
}
}

View File

@ -43,6 +43,7 @@ import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.EdgeLabel;
import com.baidu.hugegraph.type.define.Frequency;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@ -178,6 +179,16 @@ public class EdgeLabelAPI extends API {
private EdgeLabel.Builder convert2Builder(HugeGraph g) {
EdgeLabel.Builder builder = g.schema().edgeLabel(this.name);
if (this.id != 0) {
E.checkArgument(this.id > 0,
"Only positive number can be assign as " +
"edge label id");
E.checkArgument(g.mode() == GraphMode.RESTORING,
"Only accept edge label id when graph in " +
"RESTORING mode, but '%s' is in mode '%s'",
g, g.mode());
builder.id(this.id);
}
if (this.sourceLabel != null) {
builder.sourceLabel(this.sourceLabel);
}

View File

@ -41,6 +41,7 @@ import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.IndexLabel;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.type.define.IndexType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
@ -153,6 +154,16 @@ public class IndexLabelAPI extends API {
private IndexLabel.Builder convert2Builder(HugeGraph g) {
IndexLabel.Builder builder = g.schema().indexLabel(this.name);
if (this.id != 0) {
E.checkArgument(this.id > 0,
"Only positive number can be assign as " +
"index label id");
E.checkArgument(g.mode() == GraphMode.RESTORING,
"Only accept index label id when graph in " +
"RESTORING mode, but '%s' is in mode '%s'",
g, g.mode());
builder.id(this.id);
}
builder.on(this.baseType, this.baseValue);
if (this.indexType != null) {
builder.indexType(this.indexType);

View File

@ -43,6 +43,7 @@ import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.PropertyKey;
import com.baidu.hugegraph.type.define.Cardinality;
import com.baidu.hugegraph.type.define.DataType;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@ -173,6 +174,16 @@ public class PropertyKeyAPI extends API {
private PropertyKey.Builder convert2Builder(HugeGraph g) {
PropertyKey.Builder builder = g.schema().propertyKey(this.name);
if (this.id != 0) {
E.checkArgument(this.id > 0,
"Only positive number can be assign as " +
"property key id");
E.checkArgument(g.mode() == GraphMode.RESTORING,
"Only accept property key id when graph in " +
"RESTORING mode, but '%s' is in mode '%s'",
g, g.mode());
builder.id(this.id);
}
if (this.cardinality != null) {
builder.cardinality(this.cardinality);
}

View File

@ -42,6 +42,7 @@ import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.VertexLabel;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.type.define.IdStrategy;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
@ -177,6 +178,16 @@ public class VertexLabelAPI extends API {
private VertexLabel.Builder convert2Builder(HugeGraph g) {
VertexLabel.Builder builder = g.schema().vertexLabel(this.name);
if (this.id != 0) {
E.checkArgument(this.id > 0,
"Only positive number can be assign as " +
"vertex label id");
E.checkArgument(g.mode() == GraphMode.RESTORING,
"Only accept vertex label id when graph in " +
"RESTORING mode, but '%s' is in mode '%s'",
g, g.mode());
builder.id(this.id);
}
if (this.idStrategy != null) {
builder.idStrategy(this.idStrategy);
}

View File

@ -178,18 +178,6 @@ public class HugeGraphAuthProxy implements GremlinGraph {
this.hugegraph.clearBackend();
}
@Override
public void restoring(boolean restoring) {
this.verifyPermission(ROLE_ADMIN);
this.hugegraph.restoring(restoring);
}
@Override
public boolean restoring() {
this.verifyPermission(ROLE_ADMIN);
return this.hugegraph.restoring();
}
private void verifyPermission() {
/*
* The owner role should match the graph name

View File

@ -74,10 +74,11 @@ public final class ApiVersion {
* [0.28] Issue-153: Add task-cancel API
* [0.29] Issue-39: Add rays and rings RESTful API
* [0.30] Issue-32: Change index create API to return indexLabel and task id
* [0.31] Issue-182: Support restore graph in restoring and merging mode
*/
// The second parameter of Version.of() is for IDE running without JAR
public static final Version VERSION = Version.of(ApiVersion.class, "0.30");
public static final Version VERSION = Version.of(ApiVersion.class, "0.31");
public static final void check() {
// Check version of hugegraph-core. Firstly do check from version 0.3

View File

@ -488,10 +488,17 @@ public abstract class CassandraStore extends AbstractBackendStore {
}
@Override
public Id nextId(HugeType type) {
public void increaseCounter(HugeType type, long increment) {
this.checkSessionConnected();
CassandraSessionPool.Session session = super.sessions.session();
return this.counters.nextId(session, type);
this.counters.increaseCounter(session, type, increment);
}
@Override
public long getCounter(HugeType type) {
this.checkSessionConnected();
CassandraSessionPool.Session session = super.sessions.session();
return this.counters.getCounter(session, type);
}
}
@ -522,5 +529,17 @@ public abstract class CassandraStore extends AbstractBackendStore {
throw new UnsupportedOperationException(
"CassandraGraphStore.nextId()");
}
@Override
public void increaseCounter(HugeType type, long num) {
throw new UnsupportedOperationException(
"CassandraGraphStore.increaseCounter()");
}
@Override
public long getCounter(HugeType type) {
throw new UnsupportedOperationException(
"CassandraGraphStore.getCounter()");
}
}
}

View File

@ -65,8 +65,6 @@ public class CassandraTables {
public static final String TABLE = "counters";
public static final int MAX_TIMES = 1000;
public Counters() {
super(TABLE);
}
@ -84,40 +82,26 @@ public class CassandraTables {
this.createTable(session, pkeys, ckeys, columns);
}
public synchronized Id nextId(CassandraSessionPool.Session session,
HugeType type) {
public long getCounter(CassandraSessionPool.Session session,
HugeType type) {
Clause where = formatEQ(HugeKeys.SCHEMA_TYPE, type.name());
Select select = QueryBuilder.select(formatKey(HugeKeys.ID))
.from(TABLE);
select.where(where);
Update update = QueryBuilder.update(TABLE);
// Id increase 1
update.with(QueryBuilder.incr(formatKey(HugeKeys.ID), 1L));
update.where(where);
// Do get-increase-get-compare operation
long counter = 0L;
long expect = -1L;
for (int i = 0; i < MAX_TIMES; i++) {
Row row = session.execute(select).one();
if (row != null) {
counter = row.getLong(formatKey(HugeKeys.ID));
}
if (counter == expect) {
break;
}
// Increase local counter
expect = counter + 1L;
// Increase remote counter
session.execute(update);
Row row = session.execute(select).one();
if (row == null) {
return 0L;
} else {
return row.getLong(formatKey(HugeKeys.ID));
}
}
E.checkState(counter != 0L, "Please check whether Cassandra is OK");
E.checkState(counter == expect,
"Cassandra is busy please try again");
return IdGenerator.of(expect);
public void increaseCounter(CassandraSessionPool.Session session,
HugeType type, long increment) {
Update update = QueryBuilder.update(TABLE);
update.with(QueryBuilder.incr(formatKey(HugeKeys.ID), increment));
update.where(formatEQ(HugeKeys.SCHEMA_TYPE, type.name()));
session.execute(update);
}
}

View File

@ -35,7 +35,4 @@ public interface GremlinGraph extends Graph {
public String backend();
public void initBackend();
public void clearBackend();
public void restoring(boolean restoring);
public boolean restoring();
}

View File

@ -66,10 +66,12 @@ import com.baidu.hugegraph.task.TaskManager;
import com.baidu.hugegraph.task.TaskScheduler;
import com.baidu.hugegraph.traversal.optimize.HugeGraphStepStrategy;
import com.baidu.hugegraph.traversal.optimize.HugeVertexStepStrategy;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.LockUtil;
import com.baidu.hugegraph.util.Log;
import com.baidu.hugegraph.variables.HugeVariables;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.RateLimiter;
/**
@ -97,7 +99,7 @@ public class HugeGraph implements GremlinGraph {
private final String name;
private boolean closed;
private boolean restoring;
private GraphMode mode;
private final HugeConfig configuration;
@ -128,7 +130,7 @@ public class HugeGraph implements GremlinGraph {
this.name = configuration.get(CoreOptions.STORE);
this.closed = false;
this.restoring = false;
this.mode = GraphMode.NONE;
try {
this.storeProvider = this.loadStoreProvider();
@ -163,14 +165,12 @@ public class HugeGraph implements GremlinGraph {
return this.closed && this.tx.closed();
}
@Override
public boolean restoring() {
return this.restoring;
public GraphMode mode() {
return this.mode;
}
@Override
public void restoring(boolean restoring) {
this.restoring = restoring;
public void mode(GraphMode mode) {
this.mode = mode;
}
public EventHub schemaEventHub() {

View File

@ -35,7 +35,7 @@ public class LocalCounter {
this.counters = new ConcurrentHashMap<>();
}
public Id nextId(HugeType type) {
public synchronized Id nextId(HugeType type) {
AtomicLong counter = this.counters.get(type);
if (counter == null) {
counter = new AtomicLong(0);
@ -46,4 +46,30 @@ public class LocalCounter {
}
return IdGenerator.of(counter.incrementAndGet());
}
public long getCounter(HugeType type) {
AtomicLong counter = this.counters.get(type);
if (counter == null) {
counter = new AtomicLong(0);
AtomicLong previous = this.counters.putIfAbsent(type, counter);
if (previous != null) {
counter = previous;
}
}
return counter.longValue();
}
public synchronized void increaseCounter(HugeType type, long increment) {
AtomicLong counter = this.counters.get(type);
if (counter == null) {
counter = new AtomicLong(0);
AtomicLong previous = this.counters.putIfAbsent(type, counter);
if (previous != null) {
counter = previous;
}
}
long oldValue = counter.longValue();
AtomicLong value = new AtomicLong(oldValue + increment);
this.counters.put(type, value);
}
}

View File

@ -111,6 +111,16 @@ public class CachedBackendStore implements BackendStore {
return this.store.nextId(type);
}
@Override
public void increaseCounter(HugeType type, long increment) {
this.store.increaseCounter(type, increment);
}
@Override
public long getCounter(HugeType type) {
return this.store.getCounter(type);
}
@Override
public void mutate(BackendMutation mutation) {
// TODO: invalid cache, or set expire time at least

View File

@ -22,9 +22,11 @@ package com.baidu.hugegraph.backend.store;
import java.util.Iterator;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.query.Query;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.util.E;
public interface BackendStore {
@ -63,7 +65,47 @@ public interface BackendStore {
public BackendFeatures features();
// Generate an id for a specific type
public Id nextId(HugeType type);
public default Id nextId(HugeType type) {
final int MAX_TIMES = 1000;
// Do get-increase-get-compare operation
long counter = 0L;
long expect = -1L;
synchronized(this) {
for (int i = 0; i < MAX_TIMES; i++) {
counter = this.getCounter(type);
if (counter == expect) {
break;
}
// Increase local counter
expect = counter + 1L;
// Increase remote counter
this.increaseCounter(type, 1L);
}
}
E.checkState(counter != 0L, "Please check whether '%s' is OK",
this.provider().type());
E.checkState(counter == expect, "'%s' is busy please try again",
this.provider().type());
return IdGenerator.of(expect);
}
// Set next id >= lowest for a specific type
public default void setCounterLowest(HugeType type, long lowest) {
long current = this.getCounter(type);
if (current >= lowest) {
return;
}
long increment = lowest - current;
this.increaseCounter(type, increment);
}
// Increase next id for specific type
public void increaseCounter(HugeType type, long increment);
// Get current counter for a specific type
public long getCounter(HugeType type);
static enum TxState {
BEGIN, COMMITTING, COMMITT_FAIL, ROLLBACKING, ROLLBACK_FAIL, CLEAN

View File

@ -56,7 +56,7 @@ import com.baidu.hugegraph.util.Log;
* 1.remove by id + condition
* 2.append/subtract edge-property
*/
public class InMemoryDBStore extends AbstractBackendStore {
public abstract class InMemoryDBStore extends AbstractBackendStore {
private static final Logger LOG = Log.logger(InMemoryDBStore.class);
@ -66,7 +66,6 @@ public class InMemoryDBStore extends AbstractBackendStore {
private final String database;
private final Map<HugeType, InMemoryDBTable> tables;
private final LocalCounter counter;
public InMemoryDBStore(final BackendStoreProvider provider,
final String database, final String store) {
@ -74,7 +73,6 @@ public class InMemoryDBStore extends AbstractBackendStore {
this.database = database;
this.store = store;
this.tables = new HashMap<>();
this.counter = new LocalCounter();
}
@Override
@ -217,11 +215,6 @@ public class InMemoryDBStore extends AbstractBackendStore {
return FEATURES;
}
@Override
public Id nextId(HugeType type) {
return this.counter.nextId(type);
}
@Override
public String toString() {
return this.store;
@ -231,9 +224,12 @@ public class InMemoryDBStore extends AbstractBackendStore {
public static class InMemorySchemaStore extends InMemoryDBStore {
private final LocalCounter counter;
public InMemorySchemaStore(BackendStoreProvider provider,
String database, String store) {
super(provider, database, store);
this.counter = new LocalCounter();
registerTableManager(HugeType.VERTEX_LABEL,
new InMemoryDBTable(HugeType.VERTEX_LABEL));
@ -246,6 +242,21 @@ public class InMemoryDBStore extends AbstractBackendStore {
registerTableManager(HugeType.SECONDARY_INDEX,
new InMemoryDBTables.SecondaryIndex());
}
@Override
public Id nextId(HugeType type) {
return this.counter.nextId(type);
}
@Override
public void increaseCounter(HugeType type, long increment) {
this.counter.increaseCounter(type, increment);
}
@Override
public long getCounter(HugeType type) {
return this.counter.getCounter(type);
}
}
public static class InMemoryGraphStore extends InMemoryDBStore {
@ -267,6 +278,24 @@ public class InMemoryDBStore extends AbstractBackendStore {
registerTableManager(HugeType.SEARCH_INDEX,
new InMemoryDBTables.SearchIndex());
}
@Override
public Id nextId(HugeType type) {
throw new UnsupportedOperationException(
"InMemoryGraphStore.nextId()");
}
@Override
public void increaseCounter(HugeType type, long num) {
throw new UnsupportedOperationException(
"InMemoryGraphStore.increaseCounter()");
}
@Override
public long getCounter(HugeType type) {
throw new UnsupportedOperationException(
"InMemoryGraphStore.getCounter()");
}
}
/**

View File

@ -411,7 +411,7 @@ public class GraphTransaction extends IndexableTransaction {
ElementHelper.attachProperties(vertex, keyValues);
// Assign vertex id
if (this.graph().restoring() &&
if (this.graph().mode().maintaining() &&
vertexLabel.idStrategy() == IdStrategy.AUTOMATIC) {
// Resume id for AUTOMATIC id strategy in restoring mode
vertex.assignId(id, true);
@ -1071,7 +1071,7 @@ public class GraphTransaction extends IndexableTransaction {
vertexLabel.name(), strategy);
break;
case AUTOMATIC:
if (this.graph().restoring()) {
if (this.graph().mode().maintaining()) {
E.checkArgument(id != null && id.number(),
"Must customize vertex number id when " +
"id strategy is '%s' for vertex label " +

View File

@ -24,15 +24,19 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.tinkerpop.gremlin.structure.Graph;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.backend.BackendException;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.query.ConditionQuery;
import com.baidu.hugegraph.backend.query.Query;
import com.baidu.hugegraph.backend.store.BackendEntry;
import com.baidu.hugegraph.backend.store.BackendStore;
import com.baidu.hugegraph.config.CoreOptions;
import com.baidu.hugegraph.exception.ExistedException;
import com.baidu.hugegraph.exception.NotAllowException;
import com.baidu.hugegraph.job.JobBuilder;
import com.baidu.hugegraph.job.schema.EdgeLabelRemoveCallable;
@ -49,6 +53,7 @@ import com.baidu.hugegraph.schema.SchemaLabel;
import com.baidu.hugegraph.schema.VertexLabel;
import com.baidu.hugegraph.task.HugeTask;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.type.define.HugeKeys;
import com.baidu.hugegraph.type.define.SchemaStatus;
import com.baidu.hugegraph.util.E;
@ -328,6 +333,17 @@ public class SchemaTransaction extends IndexableTransaction {
return this.store().nextId(type);
}
public void setNextIdLowest(HugeType type, long lowest) {
LOG.debug("SchemaTransaction set next id to {} for {}", lowest, type);
this.store().setCounterLowest(type, lowest);
}
public Id getNextSystemId() {
LOG.debug("SchemaTransaction get next system id");
Id id = this.store().nextId(HugeType.SYS_SCHEMA);
return IdGenerator.of(-id.asLong());
}
private BackendEntry serialize(SchemaElement schema) {
switch (schema.type()) {
case PROPERTY_KEY:
@ -361,6 +377,50 @@ public class SchemaTransaction extends IndexableTransaction {
}
}
public Id validOrGenerateId(HugeType type, Id id, String name) {
boolean forSystem = Graph.Hidden.isHidden(name);
if (id != null) {
this.checkIdAndUpdateNextId(type, id, name, forSystem);
} else {
if (forSystem) {
id = this.getNextSystemId();
} else {
id = this.getNextId(type);
}
}
return id;
}
private void checkIdAndUpdateNextId(HugeType type, Id id,
String name, boolean forSystem) {
if (forSystem) {
if (id.number() && id.asLong() < 0) {
return;
}
throw new IllegalStateException(String.format(
"Invalid system id '%s'", id));
}
HugeGraph graph = this.graph();
E.checkState(id.number() && id.asLong() > 0L,
"Schema id must be number and >0, but got '%s'", id);
E.checkState(graph.mode() == GraphMode.RESTORING,
"Can't build schema with provided id '%s' " +
"when graph '%s' in mode '%s'",
id, graph, graph.mode());
this.setNextIdLowest(type, id.asLong());
}
public void checkIdIfRestoringMode(HugeType type, Id id) {
if (this.graph().mode() == GraphMode.RESTORING) {
E.checkArgument(id != null,
"Must provide schema id if in RESTORING mode");
SchemaElement element = this.getSchema(type, id);
if (element != null) {
throw new ExistedException(type.toString() + " id", id);
}
}
}
private static Id asyncRun(HugeGraph graph, HugeType schemaType,
Id schemaId, SchemaCallable callable) {
return asyncRun(graph, schemaType, schemaId,

View File

@ -32,6 +32,7 @@ import org.apache.commons.collections.CollectionUtils;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.tx.SchemaTransaction;
import com.baidu.hugegraph.exception.ExistedException;
import com.baidu.hugegraph.exception.NotAllowException;
@ -48,6 +49,7 @@ import com.google.common.collect.ImmutableList;
public class EdgeLabelBuilder implements EdgeLabel.Builder {
private Id id;
private String name;
private String sourceLabel;
private String targetLabel;
@ -64,6 +66,7 @@ public class EdgeLabelBuilder implements EdgeLabel.Builder {
public EdgeLabelBuilder(String name, SchemaTransaction transaction) {
E.checkNotNull(name, "name");
E.checkNotNull(transaction, "transaction");
this.id = null;
this.name = name;
this.sourceLabel = null;
this.targetLabel = null;
@ -77,10 +80,12 @@ public class EdgeLabelBuilder implements EdgeLabel.Builder {
this.transaction = transaction;
}
@Override
public EdgeLabel build() {
Id id = this.transaction.validOrGenerateId(HugeType.EDGE_LABEL,
this.id, this.name);
HugeGraph graph = this.transaction.graph();
Id id = this.transaction.getNextId(HugeType.EDGE_LABEL);
EdgeLabel edgeLabel = new EdgeLabel(graph, id, this.name);
edgeLabel.sourceLabel(this.transaction.getVertexLabel(
this.sourceLabel).id());
@ -109,16 +114,16 @@ public class EdgeLabelBuilder implements EdgeLabel.Builder {
@Override
public EdgeLabel create() {
SchemaElement.checkName(this.name,
this.transaction.graph().configuration());
EdgeLabel edgeLabel = this.transaction.getEdgeLabel(this.name);
SchemaTransaction tx = this.transaction;
SchemaElement.checkName(this.name, tx.graph().configuration());
EdgeLabel edgeLabel = tx.getEdgeLabel(this.name);
if (edgeLabel != null) {
if (this.checkExist) {
throw new ExistedException("edge label", this.name);
}
return edgeLabel;
}
tx.checkIdIfRestoringMode(HugeType.EDGE_LABEL, this.id);
if (this.frequency == Frequency.DEFAULT) {
this.frequency = Frequency.SINGLE;
@ -131,7 +136,7 @@ public class EdgeLabelBuilder implements EdgeLabel.Builder {
this.checkNullableKeys(Action.INSERT);
edgeLabel = this.build();
this.transaction.addEdgeLabel(edgeLabel);
tx.addEdgeLabel(edgeLabel);
return edgeLabel;
}
@ -201,6 +206,13 @@ public class EdgeLabelBuilder implements EdgeLabel.Builder {
return this.transaction.rebuildIndex(edgeLabel);
}
@Override
public EdgeLabelBuilder id(long id) {
E.checkArgument(id != 0L, "Not allowed to assign 0 as edge label id");
this.id = IdGenerator.of(id);
return this;
}
@Override
public EdgeLabelBuilder properties(String... properties) {
this.properties.addAll(Arrays.asList(properties));

View File

@ -28,10 +28,9 @@ import java.util.concurrent.TimeoutException;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.tx.GraphTransaction;
import com.baidu.hugegraph.backend.tx.SchemaTransaction;
import com.baidu.hugegraph.config.CoreOptions;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.exception.ExistedException;
import com.baidu.hugegraph.exception.NotSupportException;
import com.baidu.hugegraph.schema.EdgeLabel;
@ -52,6 +51,7 @@ import com.baidu.hugegraph.util.InsertionOrderUtil;
public class IndexLabelBuilder implements IndexLabel.Builder {
private Id id;
private String name;
private HugeType baseType;
private String baseValue;
@ -64,6 +64,7 @@ public class IndexLabelBuilder implements IndexLabel.Builder {
public IndexLabelBuilder(String name, SchemaTransaction transaction) {
E.checkNotNull(name, "name");
E.checkNotNull(transaction, "transaction");
this.id = null;
this.name = name;
this.indexType = IndexType.SECONDARY;
this.indexFields = new ArrayList<>();
@ -73,8 +74,9 @@ public class IndexLabelBuilder implements IndexLabel.Builder {
@Override
public IndexLabel build() {
Id id = this.transaction.validOrGenerateId(HugeType.INDEX_LABEL,
this.id, this.name);
HugeGraph graph = this.transaction.graph();
Id id = this.transaction.getNextId(HugeType.INDEX_LABEL);
IndexLabel indexLabel = new IndexLabel(graph, id, this.name);
indexLabel.baseType(this.baseType);
SchemaLabel schemaLabel = this.loadElement();
@ -89,15 +91,16 @@ public class IndexLabelBuilder implements IndexLabel.Builder {
@Override
public IndexLabel.CreatedIndexLabel createWithTask() {
SchemaElement.checkName(this.name,
this.transaction.graph().configuration());
IndexLabel indexLabel = this.transaction.getIndexLabel(this.name);
SchemaTransaction tx = this.transaction;
SchemaElement.checkName(this.name, tx.graph().configuration());
IndexLabel indexLabel = tx.getIndexLabel(this.name);
if (indexLabel != null) {
if (this.checkExist) {
throw new ExistedException("index label", this.name);
}
return new IndexLabel.CreatedIndexLabel(indexLabel, null);
}
tx.checkIdIfRestoringMode(HugeType.INDEX_LABEL, this.id);
SchemaLabel schemaLabel = this.loadElement();
@ -115,7 +118,7 @@ public class IndexLabelBuilder implements IndexLabel.Builder {
// Create index label
indexLabel = this.build();
indexLabel.status(SchemaStatus.CREATING);
this.transaction.addIndexLabel(schemaLabel, indexLabel);
tx.addIndexLabel(schemaLabel, indexLabel);
// TODO: use event to replace direct call
Id rebuildTask = this.rebuildIndexIfNeeded(schemaLabel, indexLabel,
@ -172,6 +175,14 @@ public class IndexLabelBuilder implements IndexLabel.Builder {
return this.transaction.rebuildIndex(indexLabel);
}
@Override
public IndexLabelBuilder id(long id) {
E.checkArgument(id != 0L,
"Not allowed to assign 0 as index label id");
this.id = IdGenerator.of(id);
return this;
}
@Override
public IndexLabelBuilder onV(String baseValue) {
this.baseType = HugeType.VERTEX_LABEL;

View File

@ -24,6 +24,7 @@ import java.util.Map;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.tx.SchemaTransaction;
import com.baidu.hugegraph.exception.ExistedException;
import com.baidu.hugegraph.exception.NotAllowException;
@ -38,6 +39,7 @@ import com.baidu.hugegraph.util.E;
public class PropertyKeyBuilder implements PropertyKey.Builder {
private Id id;
private String name;
private DataType dataType;
private Cardinality cardinality;
@ -49,6 +51,7 @@ public class PropertyKeyBuilder implements PropertyKey.Builder {
public PropertyKeyBuilder(String name, SchemaTransaction transaction) {
E.checkNotNull(name, "name");
E.checkNotNull(transaction, "transaction");
this.id = null;
this.name = name;
this.dataType = DataType.TEXT;
this.cardinality = Cardinality.SINGLE;
@ -59,8 +62,9 @@ public class PropertyKeyBuilder implements PropertyKey.Builder {
@Override
public PropertyKey build() {
Id id = this.transaction.validOrGenerateId(HugeType.PROPERTY_KEY,
this.id, this.name);
HugeGraph graph = this.transaction.graph();
Id id = this.transaction.getNextId(HugeType.PROPERTY_KEY);
PropertyKey propertyKey = new PropertyKey(graph, id, this.name);
propertyKey.dataType(this.dataType);
propertyKey.cardinality(this.cardinality);
@ -72,19 +76,21 @@ public class PropertyKeyBuilder implements PropertyKey.Builder {
@Override
public PropertyKey create() {
SchemaElement.checkName(this.name,
this.transaction.graph().configuration());
PropertyKey propertyKey = this.transaction.getPropertyKey(this.name);
SchemaTransaction tx = this.transaction;
SchemaElement.checkName(this.name, tx.graph().configuration());
PropertyKey propertyKey = tx.getPropertyKey(this.name);
if (propertyKey != null) {
if (this.checkExist) {
throw new ExistedException("property key", this.name);
}
return propertyKey;
}
tx.checkIdIfRestoringMode(HugeType.PROPERTY_KEY, this.id);
this.checkUserData(Action.INSERT);
propertyKey = this.build();
this.transaction.addPropertyKey(propertyKey);
tx.addPropertyKey(propertyKey);
return propertyKey;
}
@ -132,6 +138,14 @@ public class PropertyKeyBuilder implements PropertyKey.Builder {
return null;
}
@Override
public PropertyKeyBuilder id(long id) {
E.checkArgument(id != 0L,
"Not allowed to assign 0 as property key id");
this.id = IdGenerator.of(id);
return this;
}
@Override
public PropertyKeyBuilder asText() {
this.dataType = DataType.TEXT;

View File

@ -24,6 +24,8 @@ import com.baidu.hugegraph.schema.SchemaElement;
public interface SchemaBuilder<T extends SchemaElement> {
public SchemaBuilder<T> id(long id);
public T build();
public T create();

View File

@ -32,6 +32,7 @@ import org.apache.commons.collections.CollectionUtils;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.tx.SchemaTransaction;
import com.baidu.hugegraph.exception.ExistedException;
import com.baidu.hugegraph.exception.NotAllowException;
@ -48,6 +49,7 @@ import com.google.common.collect.ImmutableList;
public class VertexLabelBuilder implements VertexLabel.Builder {
private Id id;
private String name;
private IdStrategy idStrategy;
private Set<String> properties;
@ -62,6 +64,7 @@ public class VertexLabelBuilder implements VertexLabel.Builder {
public VertexLabelBuilder(String name, SchemaTransaction transaction) {
E.checkNotNull(name, "name");
E.checkNotNull(transaction, "transaction");
this.id = null;
this.name = name;
this.idStrategy = IdStrategy.DEFAULT;
this.properties = new HashSet<>();
@ -76,8 +79,9 @@ public class VertexLabelBuilder implements VertexLabel.Builder {
@Override
public VertexLabel build() {
Id id = this.transaction.validOrGenerateId(HugeType.VERTEX_LABEL,
this.id, this.name);
HugeGraph graph = this.transaction.graph();
Id id = this.transaction.getNextId(HugeType.VERTEX_LABEL);
VertexLabel vertexLabel = new VertexLabel(graph, id, this.name);
vertexLabel.idStrategy(this.idStrategy);
vertexLabel.enableLabelIndex(this.enableLabelIndex == null ||
@ -103,15 +107,16 @@ public class VertexLabelBuilder implements VertexLabel.Builder {
@Override
public VertexLabel create() {
SchemaElement.checkName(this.name,
this.transaction.graph().configuration());
VertexLabel vertexLabel = this.transaction.getVertexLabel(this.name);
SchemaTransaction tx = this.transaction;
SchemaElement.checkName(this.name, tx.graph().configuration());
VertexLabel vertexLabel = tx.getVertexLabel(this.name);
if (vertexLabel != null) {
if (this.checkExist) {
throw new ExistedException("vertex label", this.name);
}
return vertexLabel;
}
tx.checkIdIfRestoringMode(HugeType.VERTEX_LABEL, this.id);
this.checkProperties(Action.INSERT);
this.checkIdStrategy();
@ -119,7 +124,7 @@ public class VertexLabelBuilder implements VertexLabel.Builder {
this.checkUserData(Action.INSERT);
vertexLabel = this.build();
this.transaction.addVertexLabel(vertexLabel);
tx.addVertexLabel(vertexLabel);
return vertexLabel;
}
@ -190,6 +195,14 @@ public class VertexLabelBuilder implements VertexLabel.Builder {
return this.transaction.rebuildIndex(vertexLabel);
}
@Override
public VertexLabelBuilder id(long id) {
E.checkArgument(id != 0L,
"Not allowed to assign 0 as vertex label id");
this.id = IdGenerator.of(id);
return this;
}
@Override
public VertexLabelBuilder idStrategy(IdStrategy idStrategy) {
E.checkArgument(this.idStrategy == IdStrategy.DEFAULT ||

View File

@ -1,56 +0,0 @@
//package com.baidu.hugegraph.structure;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.Set;
//
//import com.baidu.hugegraph.backend.id.Id;
//import com.baidu.hugegraph.backend.id.IdGeneratorFactory;
//import com.baidu.hugegraph.type.HugeTypes;
//
///**
// * Created by liningrui on 2017/4/25.
// */
//public class HugeSearchIndex extends HugeIndex {
//
// private String indexLabelId;
// private List<String> propertyValues;
// private Set<String> elementIds;
//
// public HugeTypes type() {
// return HugeTypes.SEARCH_INDEX;
// }
//
// @Override
// protected Id generateId() {
// return IdGeneratorFactory.generator().generate(this);
// }
//
// public List<String> getPropertyValues() {
// return propertyValues;
// }
//
// public void setPropertyValues(List<String> propertyValues) {
// this.propertyValues = propertyValues;
// }
//
// public String getIndexLabelId() {
// return indexLabelId;
// }
//
// public void setIndexLabelId(String indexLabelId) {
// this.indexLabelId = indexLabelId;
// }
//
// public Set<String> getElementIds() {
// return elementIds;
// }
//
// public void setElementIds(Set<String> elementIds) {
// this.elementIds = elementIds;
// }
//
// public void setElementIds(String... elementIds) {
// this.elementIds.addAll(Arrays.asList(elementIds));
// }
//}

View File

@ -1,55 +0,0 @@
//package com.baidu.hugegraph.structure;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.Set;
//
//import com.baidu.hugegraph.backend.id.Id;
//import com.baidu.hugegraph.backend.id.IdGeneratorFactory;
//import com.baidu.hugegraph.type.HugeTypes;
//
///**
// * Created by liningrui on 2017/4/25.
// */
//public class HugeSecondaryIndex extends HugeIndex {
//
// private List<String> propertyValues;
// private String indexLabelId;
// private Set<String> elementIds;
//
// public HugeTypes type() {
// return HugeTypes.SECONDARY_INDEX;
// }
//
// protected Id generateId() {
// return IdGeneratorFactory.generator().generate(this);
// }
//
// public List<String> getPropertyValues() {
// return propertyValues;
// }
//
// public void setPropertyValues(List<String> propertyValues) {
// this.propertyValues = propertyValues;
// }
//
// public String getIndexLabelId() {
// return indexLabelId;
// }
//
// public void setIndexLabelId(String indexLabelId) {
// this.indexLabelId = indexLabelId;
// }
//
// public Set<String> getElementIds() {
// return elementIds;
// }
//
// public void setElementIds(Set<String> elementIds) {
// this.elementIds = elementIds;
// }
//
// public void setElementIds(String... elementIds) {
// this.elementIds.addAll(Arrays.asList(elementIds));
// }
//}

View File

@ -53,6 +53,9 @@ public enum HugeType implements SerialEnum {
TASK(180, "T"),
// System schema
SYS_SCHEMA(250, "SS"),
MAX_TYPE(255, "~");
private byte type = 0;

View File

@ -0,0 +1,65 @@
/*
* Copyright 2017 HugeGraph Authors
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.baidu.hugegraph.type.define;
public enum GraphMode {
/*
* None mode is regular mode
* 1. Not allowed create schema with specified id
* 2. Not support create vertex with id for AUTOMATIC id strategy
*/
NONE(1, "none"),
/*
* Restoring mode is used to restore schema and graph data to an new graph.
* 1. Support create schema with specified id
* 2. Support create vertex with id for AUTOMATIC id strategy
*/
RESTORING(2, "restoring"),
/*
* MERGING mode is used to merge schema and graph data to an existing graph.
* 1. Not allowed create schema with specified id
* 2. Support create vertex with id for AUTOMATIC id strategy
*/
MERGING(3, "merging");
private final byte code;
private final String name;
private GraphMode(int code, String name) {
assert code < 256;
this.code = (byte) code;
this.name = name;
}
public byte code() {
return this.code;
}
public String string() {
return this.name;
}
public boolean maintaining() {
return this == RESTORING || this == MERGING;
}
}

View File

@ -334,9 +334,16 @@ public abstract class HbaseStore extends AbstractBackendStore {
}
@Override
public Id nextId(HugeType type) {
public void increaseCounter(HugeType type, long increment) {
super.checkOpened();
return this.counters.nextId(super.sessions.session(), type);
this.counters.increaseCounter(super.sessions.session(),
type, increment);
}
@Override
public long getCounter(HugeType type) {
super.checkOpened();
return this.counters.getCounter(super.sessions.session(), type);
}
}
@ -367,5 +374,17 @@ public abstract class HbaseStore extends AbstractBackendStore {
throw new UnsupportedOperationException(
"HbaseGraphStore.nextId()");
}
@Override
public void increaseCounter(HugeType type, long num) {
throw new UnsupportedOperationException(
"HbaseGraphStore.increaseCounter()");
}
@Override
public long getCounter(HugeType type) {
throw new UnsupportedOperationException(
"HbaseGraphStore.getCounter()");
}
}
}

View File

@ -30,7 +30,6 @@ import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.query.Condition;
import com.baidu.hugegraph.backend.query.Condition.Relation;
import com.baidu.hugegraph.backend.query.ConditionQuery;
@ -42,6 +41,7 @@ import com.baidu.hugegraph.backend.store.hbase.HbaseSessions.Session;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.type.define.HugeKeys;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.NumericUtil;
public class HbaseTables {
@ -54,10 +54,21 @@ public class HbaseTables {
super(TABLE);
}
public synchronized Id nextId(Session session, HugeType type) {
public long getCounter(Session session, HugeType type) {
byte[] key = new byte[]{type.code()};
long counter = session.increase(this.table(), CF, key, COL, 1L);
return IdGenerator.of(counter);
RowIterator results = session.get(this.table(), CF, key);
if (results.hasNext()) {
Result row = results.next();
return NumericUtil.bytesToLong(row.getValue(CF, COL));
} else {
return 0L;
}
}
public void increaseCounter(Session session, HugeType type,
long increment) {
byte[] key = new byte[]{type.code()};
session.increase(this.table(), CF, key, COL, increment);
}
}

View File

@ -356,10 +356,17 @@ public abstract class MysqlStore extends AbstractBackendStore {
}
@Override
public Id nextId(HugeType type) {
public void increaseCounter(HugeType type, long increment) {
this.checkSessionConnected();
MysqlSessions.Session session = super.sessions.session();
return this.counters.nextId(session, type);
this.counters.increaseCounter(session, type, increment);
}
@Override
public long getCounter(HugeType type) {
this.checkSessionConnected();
MysqlSessions.Session session = super.sessions.session();
return this.counters.getCounter(session, type);
}
}
@ -389,5 +396,17 @@ public abstract class MysqlStore extends AbstractBackendStore {
public Id nextId(HugeType type) {
throw new UnsupportedOperationException("MysqlGraphStore.nextId()");
}
@Override
public void increaseCounter(HugeType type, long num) {
throw new UnsupportedOperationException(
"MysqlGraphStore.increaseCounter()");
}
@Override
public long getCounter(HugeType type) {
throw new UnsupportedOperationException(
"MysqlGraphStore.getCounter()");
}
}
}

View File

@ -72,8 +72,6 @@ public class MysqlTables {
public static final String TABLE = "counters";
public static final int MAX_TIMES = 10;
public Counters() {
super(TABLE);
@ -83,55 +81,38 @@ public class MysqlTables {
this.define.keys(HugeKeys.SCHEMA_TYPE);
}
public synchronized Id nextId(MysqlSessions.Session session,
HugeType type) {
public long getCounter(MysqlSessions.Session session, HugeType type) {
String schemaCol = formatKey(HugeKeys.SCHEMA_TYPE);
String idCol = formatKey(HugeKeys.ID);
String select = String.format("SELECT ID FROM %s WHERE %s = '%s';",
TABLE, schemaCol, type.name());
/*
* If the current schema record does not exist then insert,
* otherwise update it.
*/
String update = String.format("INSERT INTO %s VALUES ('%s', 1) " +
"ON DUPLICATE KEY UPDATE " +
"ID = ID + 1;", TABLE, type.name());
// Do get-increase-get-compare operation
long counter = 0L;
long expect = -1L;
for (int i = 0; i < MAX_TIMES; i++) {
try {
ResultSet resultSet = session.select(select);
if (resultSet.next()) {
counter = resultSet.getLong(idCol);
}
} catch (SQLException e) {
throw new BackendException("Failed to get id from " +
"counters with schema type '%s'",
e, type);
}
if (counter == expect) {
break;
}
// Increase local counter
expect = counter + 1L;
// Increase remote counter
try {
session.execute(update);
} catch (SQLException e) {
throw new BackendException("Failed to update counter " +
"for schema type '%s'", e, type);
try {
ResultSet resultSet = session.select(select);
if (resultSet.next()) {
return resultSet.getLong(idCol);
} else {
return 0L;
}
} catch (SQLException e) {
throw new BackendException(
"Failed to get id from counters with type '%s'",
e, type);
}
}
E.checkState(counter != 0L, "Please check whether MySQL is OK");
E.checkState(counter == expect, "MySQL is busy please try again");
return IdGenerator.of(expect);
public void increaseCounter(MysqlSessions.Session session,
HugeType type, long increment) {
String update = String.format(
"INSERT INTO %s VALUES ('%s', %s) " +
"ON DUPLICATE KEY UPDATE " +
"ID = ID + 1;", TABLE, type.name(), increment);
try {
session.execute(update);
} catch (SQLException e) {
throw new BackendException("Failed to update counters " +
"with '%s'", e, update);
}
}
}

View File

@ -86,6 +86,17 @@ public class PaloStoreProvider extends MysqlStoreProvider {
public Id nextId(HugeType type) {
return this.counter.nextId(type);
}
@Override
public void increaseCounter(HugeType type, long increment) {
this.counter.increaseCounter(type, increment);
}
@Override
public long getCounter(HugeType type) {
return this.counter.getCounter(type);
}
}
public static class PaloGraphStore extends PaloStore {
@ -117,5 +128,17 @@ public class PaloStoreProvider extends MysqlStoreProvider {
public Id nextId(HugeType type) {
throw new UnsupportedOperationException("PaloGraphStore.nextId()");
}
@Override
public void increaseCounter(HugeType type, long num) {
throw new UnsupportedOperationException(
"PaloGraphStore.increaseCounter()");
}
@Override
public long getCounter(HugeType type) {
throw new UnsupportedOperationException(
"PaloGraphStore.getCounter()");
}
}
}

View File

@ -59,6 +59,7 @@ public abstract class RocksDBSessions extends BackendSessionPool {
public abstract void put(String table, byte[] key, byte[] value);
public abstract void merge(String table, byte[] key, byte[] value);
public abstract void increase(String table, byte[] key, byte[] value);
public abstract void remove(String table, byte[] key);
public abstract void delete(String table, byte[] keyFrom, byte[] keyTo);

View File

@ -350,7 +350,7 @@ public class RocksDBStdSessions extends RocksDBSessions {
return StringEncoding.decode(bytes);
}
public static final byte[] increase(byte[] bytes) {
public static final byte[] increaseOne(byte[] bytes) {
final byte BYTE_MAX_VALUE = (byte) 0xff;
assert bytes.length > 0;
byte last = bytes[bytes.length - 1];
@ -484,6 +484,18 @@ public class RocksDBStdSessions extends RocksDBSessions {
this.batch.merge(cf(table), key, value);
}
/**
* Merge a record to an existing key to a table and commit immediately
*/
@Override
public void increase(String table, byte[] key, byte[] value) {
try {
rocksdb().merge(cf(table), key, value);
} catch (RocksDBException e) {
throw new BackendException(e);
}
}
/**
* Delete a record by key from a table
*/
@ -499,7 +511,7 @@ public class RocksDBStdSessions extends RocksDBSessions {
public void delete(String table, byte[] key) {
byte[] keyFrom = key;
byte[] keyTo = Arrays.copyOf(key, key.length);
keyTo = increase(keyTo);
keyTo = increaseOne(keyTo);
this.batch.deleteRange(cf(table), keyFrom, keyTo);
}

View File

@ -503,10 +503,17 @@ public abstract class RocksDBStore extends AbstractBackendStore {
}
@Override
public Id nextId(HugeType type) {
public void increaseCounter(HugeType type, long increment) {
super.checkOpened();
Session session = super.sessions.session();
return this.counters.nextId(session, type);
this.counters.increaseCounter(session, type, increment);
}
@Override
public long getCounter(HugeType type) {
super.checkOpened();
Session session = super.sessions.session();
return this.counters.getCounter(session, type);
}
}
@ -537,5 +544,17 @@ public abstract class RocksDBStore extends AbstractBackendStore {
throw new UnsupportedOperationException(
"RocksDBGraphStore.nextId()");
}
@Override
public void increaseCounter(HugeType type, long num) {
throw new UnsupportedOperationException(
"RocksDBGraphStore.increaseCounter()");
}
@Override
public long getCounter(HugeType type) {
throw new UnsupportedOperationException(
"RocksDBGraphStore.getCounter()");
}
}
}

View File

@ -41,38 +41,24 @@ public class RocksDBTables {
private static final String TABLE = "c";
private static final int MAX_TIMES = 1000;
private static final byte[] ONE = b(1L);
public Counters(String database) {
super(database, TABLE);
}
public synchronized Id nextId(Session session, HugeType type) {
public long getCounter(Session session, HugeType type) {
byte[] key = new byte[]{type.code()};
// Do get-increase-get-compare operation
long counter = 0L;
long expect = -1L;
for (int i = 0; i < MAX_TIMES; i++) {
// Get the latest value
byte[] value = session.get(this.table(), key);
if (value != null) {
counter = l(value);
}
if (counter == expect) {
break;
}
// Increase local counter
expect = counter + 1L;
// Increase 1, the default value of counter is 0 in RocksDB
session.merge(this.table(), key, ONE);
session.commit();
byte[] value = session.get(this.table(), key);
if (value != null) {
return l(value);
} else {
return 0L;
}
}
E.checkState(counter != 0L, "Please check whether RocksDB is OK");
E.checkState(counter == expect, "RocksDB is busy please try again");
return IdGenerator.of(counter);
public void increaseCounter(Session session, HugeType type,
long increment) {
byte[] key = new byte[]{type.code()};
session.increase(this.table(), key, b(increment));
}
private static byte[] b(long value) {
@ -234,7 +220,7 @@ public class RocksDBTables {
E.checkArgumentNotNull(min, "Range index begin key is missing");
byte[] begin = min.asBytes();
if (!minEq) {
begin = RocksDBStdSessions.increase(begin);
begin = RocksDBStdSessions.increaseOne(begin);
}
if (max == null) {

View File

@ -256,6 +256,14 @@ public class RocksDBSstSessions extends RocksDBSessions {
throw new NotSupportException("RocksDBSstStore merge()");
}
/**
* Merge a record to an existing key to a table and commit immediately
*/
@Override
public void increase(String table, byte[] key, byte[] value) {
throw new NotSupportException("RocksDBSstStore increase()");
}
/**
* Delete a record by key from a table
*/

View File

@ -79,5 +79,17 @@ public abstract class RocksDBSstStore extends RocksDBStore {
throw new UnsupportedOperationException(
"RocksDBSstGraphStore.nextId()");
}
@Override
public void increaseCounter(HugeType type, long increment) {
throw new UnsupportedOperationException(
"RocksDBSstGraphStore.increaseCounter()");
}
@Override
public long getCounter(HugeType type) {
throw new UnsupportedOperationException(
"RocksDBSstGraphStore.getCounter()");
}
}
}

View File

@ -43,7 +43,8 @@ import com.baidu.hugegraph.util.Log;
VertexCoreTest.class,
EdgeCoreTest.class,
VertexPropertyCoreTest.class,
EdgePropertyCoreTest.class
EdgePropertyCoreTest.class,
RestoreCoreTest.class
})
public class CoreTestSuite {

View File

@ -0,0 +1,727 @@
/*
* Copyright 2017 HugeGraph Authors
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.baidu.hugegraph.core;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.junit.After;
import org.junit.Test;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.exception.ExistedException;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.type.define.GraphMode;
import com.baidu.hugegraph.type.define.IdStrategy;
public class RestoreCoreTest extends BaseCoreTest {
@After
public void teardown() throws Exception {
super.teardown();
graph().mode(GraphMode.NONE);
}
@Test
public void testCreateVertexLabelWithId0InNoneMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().vertexLabel("person").id(0L).create()
);
}
@Test
public void testCreateVertexLabelWithId0InMergingMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().vertexLabel("person").id(0L).create()
);
}
@Test
public void testCreateVertexLabelWithId0InRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().vertexLabel("person").id(0L).create()
);
}
@Test
public void testCreateVertexLabelWithNegativeIdInNoneMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().vertexLabel("person").id(-100L).create()
);
}
@Test
public void testCreateVertexLabelWithNegativeIdInMergingMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().vertexLabel("person").id(-100L).create()
);
}
@Test
public void testCreateVertexLabelWithNegativeIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().vertexLabel("person").id(-100L).create()
);
}
@Test
public void testCreateVertexLabelWithPositiveIdInNoneMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().vertexLabel("person").id(100L).create()
);
}
@Test
public void testCreateVertexLabelWithPositiveIdInMergingMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().vertexLabel("person").id(100L).create()
);
}
@Test
public void testCreateVertexLabelWithPositiveIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().vertexLabel("person").id(100L).create();
}
@Test
public void testCreateVertexLabelWithNonExistNameAndIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().vertexLabel("non-exist").id(100000L).create();
}
@Test
public void testCreateVertexLabelWithNameExistWithIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().vertexLabel("person").id(100L).create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().vertexLabel("person").id(100L).create()
);
}
@Test
public void testCreateVertexLabelWithIdExistInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().vertexLabel("person").id(100L).create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().vertexLabel("person1").id(100L).create()
);
}
@Test
public void testCreateSystemVertexLabelWith0Id() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().vertexLabel("~person").id(0L).create()
);
}
@Test
public void testCreateSystemVertexLabelWithPositiveId() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().vertexLabel("~person").id(100L).build()
);
}
@Test
public void testCreateSystemVertexLabelWithNegativeId() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().vertexLabel("~person").id(-100L).build();
}
@Test
public void testCreateVertexWithAutomaticStrategyAndIdInNoneMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person")
.idStrategy(IdStrategy.AUTOMATIC).create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.addVertex(T.label, "person", T.id, 100L)
);
}
@Test
public void testCreateVertexWithAutomaticStrategyAndIdInMergingMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person")
.idStrategy(IdStrategy.AUTOMATIC).create();
graph.mode(GraphMode.MERGING);
graph.addVertex(T.label, "person", T.id, 100L);
}
@Test
public void testCreateVertexWithAutomaticStrategyAndIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person")
.idStrategy(IdStrategy.AUTOMATIC).create();
graph.mode(GraphMode.RESTORING);
graph.addVertex(T.label, "person", T.id, 100L);
}
@Test
public void testCreateVertexWithPrimaryKeyStrategyAndIdInNoneMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().vertexLabel("person").properties("name")
.idStrategy(IdStrategy.PRIMARY_KEY).primaryKeys("name").create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.addVertex(T.label, "person", T.id, 100L, "name", "Tom")
);
}
@Test
public void testCreateVertexWithPrimaryKeyStrategyAndIdInMergingMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().vertexLabel("person").properties("name")
.idStrategy(IdStrategy.PRIMARY_KEY).primaryKeys("name").create();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.addVertex(T.label, "person", T.id, 100L, "name", "Tom")
);
}
@Test
public void testCreateVertexWithPrimaryKeyStrategyAndIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().vertexLabel("person").properties("name")
.idStrategy(IdStrategy.PRIMARY_KEY).primaryKeys("name").create();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.addVertex(T.label, "person", T.id, 100L, "name", "Tom")
);
}
@Test
public void testCreateVertexWithCustomizeStrategyAndIdInNoneMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person")
.idStrategy(IdStrategy.CUSTOMIZE_NUMBER).create();
graph.mode(GraphMode.NONE);
graph.addVertex(T.label, "person", T.id, 100L);
}
@Test
public void testCreateVertexWithCustomizeStrategyAndIdInMergingMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person")
.idStrategy(IdStrategy.CUSTOMIZE_NUMBER).create();
graph.mode(GraphMode.MERGING);
graph.addVertex(T.label, "person", T.id, 100L);
}
@Test
public void testCreateVertexWithCustomizeStrategyAndIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person")
.idStrategy(IdStrategy.CUSTOMIZE_NUMBER).create();
graph.mode(GraphMode.RESTORING);
graph.addVertex(T.label, "person", T.id, 100L);
}
@Test
public void testCreateEdgeLabelWithId0InNoneMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(0L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithId0InMergingMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(0L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithId0InRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(0L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithNegativeIdInNoneMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(-100L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithNegativeIdInMergingMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(-100L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithNegativeIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(-100L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithPositiveIdInNoneMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(100L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithPositiveIdInMergingMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(100L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithPositiveIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.RESTORING);
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(100L)
.create();
}
@Test
public void testCreateEdgeLabelWithNonExistNameAndIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.RESTORING);
graph.schema().edgeLabel("non-exist").sourceLabel("person")
.targetLabel("person").id(100000L)
.create();
}
@Test
public void testCreateEdgeLabelWithNameExistWithIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.RESTORING);
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(100L)
.create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(100L)
.create()
);
}
@Test
public void testCreateEdgeLabelWithIdExistInRestoringMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person").create();
graph.mode(GraphMode.RESTORING);
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").id(100L)
.create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().edgeLabel("knows1").sourceLabel("person")
.targetLabel("person").id(100L)
.create()
);
}
@Test
public void testCreateEdgeWithIdInAllMode() {
HugeGraph graph = graph();
graph.schema().vertexLabel("person")
.idStrategy(IdStrategy.AUTOMATIC).create();
graph.schema().edgeLabel("knows").sourceLabel("person")
.targetLabel("person").create();
Vertex v1 = graph.addVertex(T.label, "person");
Vertex v2 = graph.addVertex(T.label, "person");
graph.mode(GraphMode.NONE);
Assert.assertThrows(UnsupportedOperationException.class, () ->
v1.addEdge("knows", v2, T.id, "id")
);
graph.mode(GraphMode.MERGING);
Assert.assertThrows(UnsupportedOperationException.class, () ->
v1.addEdge("knows", v2, T.id, "id")
);
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(UnsupportedOperationException.class, () ->
v1.addEdge("knows", v2, T.id, "id")
);
}
@Test
public void testCreatePropertyKeyWithId0InNoneMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().propertyKey("name").id(0L).create()
);
}
@Test
public void testCreatePropertyKeyWithId0InMergingMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().propertyKey("name").id(0L).create()
);
}
@Test
public void testCreatePropertyKeyWithId0InRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().propertyKey("name").id(0L).create()
);
}
@Test
public void testCreatePropertyKeyWithNegativeIdInNoneMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().propertyKey("name").id(-100L).create()
);
}
@Test
public void testCreatePropertyKeyWithNegativeIdInMergingMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().propertyKey("name").id(-100L).create()
);
}
@Test
public void testCreatePropertyKeyWithNegativeIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().propertyKey("name").id(-100L).create()
);
}
@Test
public void testCreatePropertyKeyWithPositiveIdInNoneMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().propertyKey("name").id(100L).create()
);
}
@Test
public void testCreatePropertyKeyWithPositiveIdInMergingMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().propertyKey("name").id(100L).create()
);
}
@Test
public void testCreatePropertyKeyWithPositiveIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().propertyKey("name").id(100L).create();
}
@Test
public void testCreatePropertyKeyWithNonExistNameAndIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().propertyKey("non-exist").id(100000L).create();
}
@Test
public void testCreatePropertyKeyWithNameExistWithIdInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().propertyKey("name").id(100L).create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().propertyKey("name").id(1000L).create()
);
}
@Test
public void testCreatePropertyKeyWithIdExistInRestoringMode() {
HugeGraph graph = graph();
graph.mode(GraphMode.RESTORING);
graph.schema().propertyKey("name").id(100L).create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().propertyKey("name1").id(100L).create()
);
}
@Test
public void testCreateIndexLabelWithId0InNoneMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(0L)
.create()
);
}
@Test
public void testCreateIndexLabelWithId0InMergingMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(0L)
.create()
);
}
@Test
public void testCreateIndexLabelWithId0InRestoringMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalArgumentException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(0L)
.create()
);
}
@Test
public void testCreateIndexLabelWithNegativeIdInNoneMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(-100L)
.create()
);
}
@Test
public void testCreateIndexLabelWithNegativeIdInMergingMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(-100L)
.create()
);
}
@Test
public void testCreateIndexLabelWithNegativeIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.RESTORING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(-100L)
.create()
);
}
@Test
public void testCreateIndexLabelWithPositiveIdInNoneMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.NONE);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(100L)
.create()
);
}
@Test
public void testCreateIndexLabelWithPositiveIdInMergingMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.MERGING);
Assert.assertThrows(IllegalStateException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(100L)
.create()
);
}
@Test
public void testCreateIndexLabelWithPositiveIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.RESTORING);
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(100L)
.create();
}
@Test
public void testCreateIndexLabelWithNonExistNameAndIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.RESTORING);
graph.schema().indexLabel("non-exist")
.onV("person").by("city").secondary().id(10000L)
.create();
}
@Test
public void testCreateIndexLabelWithNameExistWithIdInRestoringMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.RESTORING);
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(100L)
.create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(100L)
.create()
);
}
@Test
public void testCreateIndexLabelWithIdExistInRestoringMode() {
HugeGraph graph = graph();
graph.schema().propertyKey("name").create();
graph.schema().propertyKey("city").create();
graph.schema().vertexLabel("person").properties("name", "city")
.primaryKeys("name").create();
graph.mode(GraphMode.RESTORING);
graph.schema().indexLabel("personByCity")
.onV("person").by("city").secondary().id(100L)
.create();
Assert.assertThrows(ExistedException.class, () ->
graph.schema().indexLabel("personByCity1")
.onV("person").by("city").secondary().id(100L)
.create()
);
}
}

View File

@ -28,6 +28,7 @@ import org.junit.Test;
import org.rocksdb.RocksDBException;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.backend.store.rocksdb.RocksDBSessions.Session;
import com.baidu.hugegraph.backend.store.rocksdb.RocksDBTables;
import com.baidu.hugegraph.testutil.Assert;
@ -52,8 +53,9 @@ public class RocksDBCountersTest extends BaseRocksDBUnitTest {
public void testCounter() throws RocksDBException {
Session session = this.rocks.session();
for (int i = 1; i < 10000; i++) {
Id id = this.counters.nextId(session, HugeType.PROPERTY_KEY);
Assert.assertEquals(i, id.asLong());
this.counters.increaseCounter(session, HugeType.PROPERTY_KEY, 1L);
long id = this.counters.getCounter(session, HugeType.PROPERTY_KEY);
Assert.assertEquals(i, id);
}
}
@ -61,17 +63,21 @@ public class RocksDBCountersTest extends BaseRocksDBUnitTest {
public void testCounterWithMultiTypes() throws RocksDBException {
Session session = this.rocks.session();
for (int i = 1; i < 1000; i++) {
Id id = this.counters.nextId(session, HugeType.PROPERTY_KEY);
Assert.assertEquals(i, id.asLong());
this.counters.increaseCounter(session, HugeType.PROPERTY_KEY, 1L);
long id = this.counters.getCounter(session, HugeType.PROPERTY_KEY);
Assert.assertEquals(i, id);
id = this.counters.nextId(session, HugeType.VERTEX_LABEL);
Assert.assertEquals(i, id.asLong());
this.counters.increaseCounter(session, HugeType.VERTEX_LABEL, 1L);
id = this.counters.getCounter(session, HugeType.VERTEX_LABEL);
Assert.assertEquals(i, id);
id = this.counters.nextId(session, HugeType.EDGE_LABEL);
Assert.assertEquals(i, id.asLong());
this.counters.increaseCounter(session, HugeType.EDGE_LABEL, 1L);
id = this.counters.getCounter(session, HugeType.EDGE_LABEL);
Assert.assertEquals(i, id);
id = this.counters.nextId(session, HugeType.INDEX_LABEL);
Assert.assertEquals(i, id.asLong());
this.counters.increaseCounter(session, HugeType.INDEX_LABEL, 1L);
id = this.counters.getCounter(session, HugeType.INDEX_LABEL);
Assert.assertEquals(i, id);
}
}
@ -86,7 +92,7 @@ public class RocksDBCountersTest extends BaseRocksDBUnitTest {
Session session = this.rocks.session();
for (int i = 0; i < TIMES; i++) {
Id id = this.counters.nextId(session, HugeType.PROPERTY_KEY);
Id id = nextId(session, HugeType.PROPERTY_KEY);
Assert.assertFalse(ids.containsKey(id));
ids.put(id, true);
@ -96,4 +102,25 @@ public class RocksDBCountersTest extends BaseRocksDBUnitTest {
});
Assert.assertEquals(THREADS_NUM * TIMES, times.get());
}
private Id nextId(Session session, HugeType type) {
final int MAX_TIMES = 1000;
// Do get-increase-get-compare operation
long counter = 0L;
long expect = -1L;
synchronized(this) {
for (int i = 0; i < MAX_TIMES; i++) {
counter = this.counters.getCounter(session, type);
if (counter == expect) {
break;
}
// Increase local counter
expect = counter + 1L;
// Increase remote counter
this.counters.increaseCounter(session, type, 1L);
}
}
return IdGenerator.of(expect);
}
}