Refactor ID Serial 1: Separate ObjectID and TaskID from UniqueID (#4776)

* Enable BaseId.

* Change TaskID and make python test pass

* Remove unnecessary functions and fix test failure and change TaskID to
16 bytes.

* Java code change draft

* Refine

* Lint

* Update java/api/src/main/java/org/ray/api/id/TaskId.java

Co-Authored-By: Hao Chen <chenh1024@gmail.com>

* Update java/api/src/main/java/org/ray/api/id/BaseId.java

Co-Authored-By: Hao Chen <chenh1024@gmail.com>

* Update java/api/src/main/java/org/ray/api/id/BaseId.java

Co-Authored-By: Hao Chen <chenh1024@gmail.com>

* Update java/api/src/main/java/org/ray/api/id/ObjectId.java

Co-Authored-By: Hao Chen <chenh1024@gmail.com>

* Address comment

* Lint

* Fix SINGLE_PROCESS

* Fix comments

* Refine code

* Refine test

* Resolve conflict
This commit is contained in:
Yuhong Guo
2019-05-22 14:46:30 +08:00
committed by GitHub
co-authored by Hao Chen
parent 259cdfa0de
commit 1a39fee9c6
57 changed files with 1077 additions and 645 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
package org.ray.api;
import java.util.List;
import org.ray.api.id.ObjectId;
import org.ray.api.id.UniqueId;
import org.ray.api.runtime.RayRuntime;
import org.ray.api.runtime.RayRuntimeFactory;
@@ -65,7 +66,7 @@ public final class Ray extends RayCall {
* @param objectId The ID of the object to get.
* @return The Java object.
*/
public static <T> T get(UniqueId objectId) {
public static <T> T get(ObjectId objectId) {
return runtime.get(objectId);
}
@@ -75,7 +76,7 @@ public final class Ray extends RayCall {
* @param objectIds The list of object IDs.
* @return A list of Java objects.
*/
public static <T> List<T> get(List<UniqueId> objectIds) {
public static <T> List<T> get(List<ObjectId> objectIds) {
return runtime.get(objectIds);
}
@@ -1,6 +1,6 @@
package org.ray.api;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
/**
* Represents an object in the object store.
@@ -17,7 +17,7 @@ public interface RayObject<T> {
/**
* Get the object id.
*/
UniqueId getId();
ObjectId getId();
}
@@ -1,6 +1,6 @@
package org.ray.api.exception;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
/**
* Indicates that an object is lost (either evicted or explicitly deleted) and cannot be
@@ -11,9 +11,9 @@ import org.ray.api.id.UniqueId;
*/
public class UnreconstructableException extends RayException {
public final UniqueId objectId;
public final ObjectId objectId;
public UnreconstructableException(UniqueId objectId) {
public UnreconstructableException(ObjectId objectId) {
super(String.format(
"Object %s is lost (either evicted or explicitly deleted) and cannot be reconstructed.",
objectId));
@@ -0,0 +1,99 @@
package org.ray.api.id;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.xml.bind.DatatypeConverter;
public abstract class BaseId implements Serializable {
private static final long serialVersionUID = 8588849129675565761L;
private final byte[] id;
private int hashCodeCache = 0;
private Boolean isNilCache = null;
/**
* Create a BaseId instance according to the input byte array.
*/
public BaseId(byte[] id) {
if (id.length != size()) {
throw new IllegalArgumentException("Failed to construct BaseId, expect " + size()
+ " bytes, but got " + id.length + " bytes.");
}
this.id = id;
}
/**
* Get the byte data of this id.
*/
public byte[] getBytes() {
return id;
}
/**
* Convert the byte data to a ByteBuffer.
*/
public ByteBuffer toByteBuffer() {
return ByteBuffer.wrap(id);
}
/**
* @return True if this id is nil.
*/
public boolean isNil() {
if (isNilCache == null) {
isNilCache = true;
for (int i = 0; i < size(); ++i) {
if (id[i] != (byte) 0xff) {
isNilCache = false;
break;
}
}
}
return isNilCache;
}
/**
* Derived class should implement this function.
* @return The length of this id in bytes.
*/
public abstract int size();
@Override
public int hashCode() {
// Lazy evaluation.
if (hashCodeCache == 0) {
hashCodeCache = Arrays.hashCode(id);
}
return hashCodeCache;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!this.getClass().equals(obj.getClass())) {
return false;
}
BaseId r = (BaseId) obj;
return Arrays.equals(id, r.id);
}
@Override
public String toString() {
return DatatypeConverter.printHexBinary(id).toLowerCase();
}
protected static byte[] hexString2Bytes(String hex) {
return DatatypeConverter.parseHexBinary(hex);
}
protected static byte[] byteBuffer2Bytes(ByteBuffer bb) {
byte[] id = new byte[bb.remaining()];
bb.get(id);
return id;
}
}
@@ -0,0 +1,62 @@
package org.ray.api.id;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
/**
* Represents the id of a Ray object.
*/
public class ObjectId extends BaseId implements Serializable {
public static final int LENGTH = 20;
public static final ObjectId NIL = genNil();
/**
* Create an ObjectId from a hex string.
*/
public static ObjectId fromHexString(String hex) {
return new ObjectId(hexString2Bytes(hex));
}
/**
* Create an ObjectId from a ByteBuffer.
*/
public static ObjectId fromByteBuffer(ByteBuffer bb) {
return new ObjectId(byteBuffer2Bytes(bb));
}
/**
* Generate a nil ObjectId.
*/
private static ObjectId genNil() {
byte[] b = new byte[LENGTH];
Arrays.fill(b, (byte) 0xFF);
return new ObjectId(b);
}
/**
* Generate an ObjectId with random value.
*/
public static ObjectId randomId() {
byte[] b = new byte[LENGTH];
new Random().nextBytes(b);
return new ObjectId(b);
}
public ObjectId(byte[] id) {
super(id);
}
@Override
public int size() {
return LENGTH;
}
public TaskId getTaskId() {
byte[] taskIdBytes = Arrays.copyOf(getBytes(), TaskId.LENGTH);
return new TaskId(taskIdBytes);
}
}
@@ -0,0 +1,56 @@
package org.ray.api.id;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
/**
* Represents the id of a Ray task.
*/
public class TaskId extends BaseId implements Serializable {
public static final int LENGTH = 16;
public static final TaskId NIL = genNil();
/**
* Create a TaskId from a hex string.
*/
public static TaskId fromHexString(String hex) {
return new TaskId(hexString2Bytes(hex));
}
/**
* Creates a TaskId from a ByteBuffer.
*/
public static TaskId fromByteBuffer(ByteBuffer bb) {
return new TaskId(byteBuffer2Bytes(bb));
}
/**
* Generate a nil TaskId.
*/
private static TaskId genNil() {
byte[] b = new byte[LENGTH];
Arrays.fill(b, (byte) 0xFF);
return new TaskId(b);
}
/**
* Generate an TaskId with random value.
*/
public static TaskId randomId() {
byte[] b = new byte[LENGTH];
new Random().nextBytes(b);
return new TaskId(b);
}
public TaskId(byte[] id) {
super(id);
}
@Override
public int size() {
return LENGTH;
}
}
@@ -4,41 +4,34 @@ import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
import javax.xml.bind.DatatypeConverter;
/**
* Represents a unique id of all Ray concepts, including
* objects, tasks, workers, actors, etc.
* workers, actors, checkpoints, etc.
*/
public class UniqueId implements Serializable {
public class UniqueId extends BaseId implements Serializable {
public static final int LENGTH = 20;
public static final UniqueId NIL = genNil();
private static final long serialVersionUID = 8588849129675565761L;
private final byte[] id;
/**
* Create a UniqueId from a hex string.
*/
public static UniqueId fromHexString(String hex) {
byte[] bytes = DatatypeConverter.parseHexBinary(hex);
return new UniqueId(bytes);
return new UniqueId(hexString2Bytes(hex));
}
/**
* Creates a UniqueId from a ByteBuffer.
*/
public static UniqueId fromByteBuffer(ByteBuffer bb) {
byte[] id = new byte[bb.remaining()];
bb.get(id);
return new UniqueId(id);
return new UniqueId(byteBuffer2Bytes(bb));
}
/**
* Generate a nil UniqueId.
*/
public static UniqueId genNil() {
private static UniqueId genNil() {
byte[] b = new byte[LENGTH];
Arrays.fill(b, (byte) 0xFF);
return new UniqueId(b);
@@ -54,64 +47,11 @@ public class UniqueId implements Serializable {
}
public UniqueId(byte[] id) {
if (id.length != LENGTH) {
throw new IllegalArgumentException("Illegal argument for UniqueId, expect " + LENGTH
+ " bytes, but got " + id.length + " bytes.");
}
this.id = id;
}
/**
* Get the byte data of this UniqueId.
*/
public byte[] getBytes() {
return id;
}
/**
* Convert the byte data to a ByteBuffer.
*/
public ByteBuffer toByteBuffer() {
return ByteBuffer.wrap(id);
}
/**
* Create a copy of this UniqueId.
*/
public UniqueId copy() {
byte[] nid = Arrays.copyOf(id, id.length);
return new UniqueId(nid);
}
/**
* Returns true if this id is nil.
*/
public boolean isNil() {
return this.equals(NIL);
super(id);
}
@Override
public int hashCode() {
return Arrays.hashCode(id);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof UniqueId)) {
return false;
}
UniqueId r = (UniqueId) obj;
return Arrays.equals(id, r.id);
}
@Override
public String toString() {
return DatatypeConverter.printHexBinary(id).toLowerCase();
public int size() {
return LENGTH;
}
}
@@ -6,6 +6,7 @@ import org.ray.api.RayObject;
import org.ray.api.RayPyActor;
import org.ray.api.WaitResult;
import org.ray.api.function.RayFunc;
import org.ray.api.id.ObjectId;
import org.ray.api.id.UniqueId;
import org.ray.api.options.ActorCreationOptions;
import org.ray.api.options.CallOptions;
@@ -35,7 +36,7 @@ public interface RayRuntime {
* @param objectId The ID of the object to get.
* @return The Java object.
*/
<T> T get(UniqueId objectId);
<T> T get(ObjectId objectId);
/**
* Get a list of objects from the object store.
@@ -43,7 +44,7 @@ public interface RayRuntime {
* @param objectIds The list of object IDs.
* @return A list of Java objects.
*/
<T> List<T> get(List<UniqueId> objectIds);
<T> List<T> get(List<ObjectId> objectIds);
/**
* Wait for a list of RayObjects to be locally available, until specified number of objects are
@@ -63,7 +64,7 @@ public interface RayRuntime {
* @param localOnly Whether only free objects for local object store or not.
* @param deleteCreatingTasks Whether also delete objects' creating tasks from GCS.
*/
void free(List<UniqueId> objectIds, boolean localOnly, boolean deleteCreatingTasks);
void free(List<ObjectId> objectIds, boolean localOnly, boolean deleteCreatingTasks);
/**
* Set the resource for the specific node.
@@ -15,6 +15,8 @@ import org.ray.api.RayPyActor;
import org.ray.api.WaitResult;
import org.ray.api.exception.RayException;
import org.ray.api.function.RayFunc;
import org.ray.api.id.ObjectId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.api.options.ActorCreationOptions;
import org.ray.api.options.BaseTaskOptions;
@@ -32,7 +34,7 @@ import org.ray.runtime.raylet.RayletClient;
import org.ray.runtime.task.ArgumentsBuilder;
import org.ray.runtime.task.TaskLanguage;
import org.ray.runtime.task.TaskSpec;
import org.ray.runtime.util.UniqueIdUtil;
import org.ray.runtime.util.IdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -88,15 +90,15 @@ public abstract class AbstractRayRuntime implements RayRuntime {
@Override
public <T> RayObject<T> put(T obj) {
UniqueId objectId = UniqueIdUtil.computePutId(
ObjectId objectId = IdUtil.computePutId(
workerContext.getCurrentTaskId(), workerContext.nextPutIndex());
put(objectId, obj);
return new RayObjectImpl<>(objectId);
}
public <T> void put(UniqueId objectId, T obj) {
UniqueId taskId = workerContext.getCurrentTaskId();
public <T> void put(ObjectId objectId, T obj) {
TaskId taskId = workerContext.getCurrentTaskId();
LOGGER.debug("Putting object {}, for task {} ", objectId, taskId);
objectStoreProxy.put(objectId, obj);
}
@@ -109,28 +111,28 @@ public abstract class AbstractRayRuntime implements RayRuntime {
* @return A RayObject instance that represents the in-store object.
*/
public RayObject<Object> putSerialized(byte[] obj) {
UniqueId objectId = UniqueIdUtil.computePutId(
ObjectId objectId = IdUtil.computePutId(
workerContext.getCurrentTaskId(), workerContext.nextPutIndex());
UniqueId taskId = workerContext.getCurrentTaskId();
TaskId taskId = workerContext.getCurrentTaskId();
LOGGER.debug("Putting serialized object {}, for task {} ", objectId, taskId);
objectStoreProxy.putSerialized(objectId, obj);
return new RayObjectImpl<>(objectId);
}
@Override
public <T> T get(UniqueId objectId) throws RayException {
public <T> T get(ObjectId objectId) throws RayException {
List<T> ret = get(ImmutableList.of(objectId));
return ret.get(0);
}
@Override
public <T> List<T> get(List<UniqueId> objectIds) {
public <T> List<T> get(List<ObjectId> objectIds) {
List<T> ret = new ArrayList<>(Collections.nCopies(objectIds.size(), null));
boolean wasBlocked = false;
try {
// A map that stores the unready object ids and their original indexes.
Map<UniqueId, Integer> unready = new HashMap<>();
Map<ObjectId, Integer> unready = new HashMap<>();
for (int i = 0; i < objectIds.size(); i++) {
unready.put(objectIds.get(i), i);
}
@@ -138,7 +140,7 @@ public abstract class AbstractRayRuntime implements RayRuntime {
// Repeat until we get all objects.
while (!unready.isEmpty()) {
List<UniqueId> unreadyIds = new ArrayList<>(unready.keySet());
List<ObjectId> unreadyIds = new ArrayList<>(unready.keySet());
// For the initial fetch, we only fetch the objects, do not reconstruct them.
boolean fetchOnly = numAttempts == 0;
@@ -147,7 +149,7 @@ public abstract class AbstractRayRuntime implements RayRuntime {
wasBlocked = true;
}
// Call `fetchOrReconstruct` in batches.
for (List<UniqueId> batch : splitIntoBatches(unreadyIds)) {
for (List<ObjectId> batch : splitIntoBatches(unreadyIds)) {
rayletClient.fetchOrReconstruct(batch, fetchOnly, workerContext.getCurrentTaskId());
}
@@ -161,7 +163,7 @@ public abstract class AbstractRayRuntime implements RayRuntime {
throw getResult.exception;
} else {
// Set the result to the return list, and remove it from the unready map.
UniqueId id = unreadyIds.get(i);
ObjectId id = unreadyIds.get(i);
ret.set(unready.get(id), getResult.object);
unready.remove(id);
}
@@ -172,11 +174,11 @@ public abstract class AbstractRayRuntime implements RayRuntime {
if (LOGGER.isWarnEnabled() && numAttempts % WARN_PER_NUM_ATTEMPTS == 0) {
// Print a warning if we've attempted too many times, but some objects are still
// unavailable.
List<UniqueId> idsToPrint = new ArrayList<>(unready.keySet());
List<ObjectId> idsToPrint = new ArrayList<>(unready.keySet());
if (idsToPrint.size() > MAX_IDS_TO_PRINT_IN_WARNING) {
idsToPrint = idsToPrint.subList(0, MAX_IDS_TO_PRINT_IN_WARNING);
}
String ids = idsToPrint.stream().map(UniqueId::toString)
String ids = idsToPrint.stream().map(ObjectId::toString)
.collect(Collectors.joining(", "));
if (idsToPrint.size() < unready.size()) {
ids += ", etc";
@@ -206,7 +208,7 @@ public abstract class AbstractRayRuntime implements RayRuntime {
}
@Override
public void free(List<UniqueId> objectIds, boolean localOnly, boolean deleteCreatingTasks) {
public void free(List<ObjectId> objectIds, boolean localOnly, boolean deleteCreatingTasks) {
rayletClient.freePlasmaObjects(objectIds, localOnly, deleteCreatingTasks);
}
@@ -219,13 +221,13 @@ public abstract class AbstractRayRuntime implements RayRuntime {
rayletClient.setResource(resourceName, capacity, nodeId);
}
private List<List<UniqueId>> splitIntoBatches(List<UniqueId> objectIds) {
List<List<UniqueId>> batches = new ArrayList<>();
private List<List<ObjectId>> splitIntoBatches(List<ObjectId> objectIds) {
List<List<ObjectId>> batches = new ArrayList<>();
int objectsSize = objectIds.size();
for (int i = 0; i < objectsSize; i += FETCH_BATCH_SIZE) {
int endIndex = i + FETCH_BATCH_SIZE;
List<UniqueId> batchIds = (endIndex < objectsSize)
List<ObjectId> batchIds = (endIndex < objectsSize)
? objectIds.subList(i, endIndex)
: objectIds.subList(i, objectsSize);
@@ -271,7 +273,7 @@ public abstract class AbstractRayRuntime implements RayRuntime {
Object[] args, ActorCreationOptions options) {
TaskSpec spec = createTaskSpec(actorFactoryFunc, null, RayActorImpl.NIL,
args, true, options);
RayActorImpl<?> actor = new RayActorImpl(spec.returnIds[0]);
RayActorImpl<?> actor = new RayActorImpl(new UniqueId(spec.returnIds[0].getBytes()));
actor.increaseTaskCounter();
actor.setTaskCursor(spec.returnIds[0]);
rayletClient.submitTask(spec);
@@ -343,14 +345,14 @@ public abstract class AbstractRayRuntime implements RayRuntime {
boolean isActorCreationTask, BaseTaskOptions taskOptions) {
Preconditions.checkArgument((func == null) != (pyFunctionDescriptor == null));
UniqueId taskId = rayletClient.generateTaskId(workerContext.getCurrentDriverId(),
TaskId taskId = rayletClient.generateTaskId(workerContext.getCurrentDriverId(),
workerContext.getCurrentTaskId(), workerContext.nextTaskIndex());
int numReturns = actor.getId().isNil() ? 1 : 2;
UniqueId[] returnIds = UniqueIdUtil.genReturnIds(taskId, numReturns);
ObjectId[] returnIds = IdUtil.genReturnIds(taskId, numReturns);
UniqueId actorCreationId = UniqueId.NIL;
if (isActorCreationTask) {
actorCreationId = returnIds[0];
actorCreationId = new UniqueId(returnIds[0].getBytes());
}
Map<String, Double> resources;
@@ -7,6 +7,7 @@ import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.List;
import org.ray.api.RayActor;
import org.ray.api.id.ObjectId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.util.Sha1Digestor;
@@ -30,7 +31,7 @@ public class RayActorImpl<T> implements RayActor<T>, Externalizable {
* The unique id of the last return of the last task.
* It's used as a dependency for the next task.
*/
protected UniqueId taskCursor;
protected ObjectId taskCursor;
/**
* The number of times that this actor handle has been forked.
* It's used to make sure ids of actor handles are unique.
@@ -72,7 +73,7 @@ public class RayActorImpl<T> implements RayActor<T>, Externalizable {
return handleId;
}
public void setTaskCursor(UniqueId taskCursor) {
public void setTaskCursor(ObjectId taskCursor) {
this.taskCursor = taskCursor;
}
@@ -84,7 +85,7 @@ public class RayActorImpl<T> implements RayActor<T>, Externalizable {
this.newActorHandles.clear();
}
public UniqueId getTaskCursor() {
public ObjectId getTaskCursor() {
return taskCursor;
}
@@ -121,7 +122,7 @@ public class RayActorImpl<T> implements RayActor<T>, Externalizable {
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.id = (UniqueId) in.readObject();
this.handleId = (UniqueId) in.readObject();
this.taskCursor = (UniqueId) in.readObject();
this.taskCursor = (ObjectId) in.readObject();
this.taskCounter = (int) in.readObject();
this.numForks = (int) in.readObject();
}
@@ -3,13 +3,13 @@ package org.ray.runtime;
import java.io.Serializable;
import org.ray.api.Ray;
import org.ray.api.RayObject;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
public final class RayObjectImpl<T> implements RayObject<T>, Serializable {
private final UniqueId id;
private final ObjectId id;
public RayObjectImpl(UniqueId id) {
public RayObjectImpl(ObjectId id) {
this.id = id;
}
@@ -19,7 +19,7 @@ public final class RayObjectImpl<T> implements RayObject<T>, Serializable {
}
@Override
public UniqueId getId() {
public ObjectId getId() {
return id;
}
@@ -7,6 +7,7 @@ import org.ray.api.Checkpointable;
import org.ray.api.Checkpointable.Checkpoint;
import org.ray.api.Checkpointable.CheckpointContext;
import org.ray.api.exception.RayTaskException;
import org.ray.api.id.ObjectId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.config.RunMode;
import org.ray.runtime.functionmanager.RayFunction;
@@ -80,7 +81,7 @@ public class Worker {
*/
public void execute(TaskSpec spec) {
LOGGER.debug("Executing task {}", spec);
UniqueId returnId = spec.returnIds[0];
ObjectId returnId = spec.returnIds[0];
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
try {
// Get method
@@ -91,7 +92,7 @@ public class Worker {
Thread.currentThread().setContextClassLoader(rayFunction.classLoader);
if (spec.isActorCreationTask()) {
currentActorId = returnId;
currentActorId = new UniqueId(returnId.getBytes());
}
// Get local actor object and arguments.
@@ -119,7 +120,7 @@ public class Worker {
}
runtime.put(returnId, result);
} else {
maybeLoadCheckpoint(result, returnId);
maybeLoadCheckpoint(result, new UniqueId(returnId.getBytes()));
currentActor = result;
}
LOGGER.debug("Finished executing task {}", spec.taskId);
@@ -1,6 +1,7 @@
package org.ray.runtime;
import com.google.common.base.Preconditions;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.config.RunMode;
import org.ray.runtime.config.WorkerMode;
@@ -14,7 +15,7 @@ public class WorkerContext {
private UniqueId workerId;
private ThreadLocal<UniqueId> currentTaskId;
private ThreadLocal<TaskId> currentTaskId;
/**
* Number of objects that have been put from current task.
@@ -46,17 +47,17 @@ public class WorkerContext {
mainThreadId = Thread.currentThread().getId();
taskIndex = ThreadLocal.withInitial(() -> 0);
putIndex = ThreadLocal.withInitial(() -> 0);
currentTaskId = ThreadLocal.withInitial(UniqueId::randomId);
currentTaskId = ThreadLocal.withInitial(TaskId::randomId);
this.runMode = runMode;
currentTask = ThreadLocal.withInitial(() -> null);
currentClassLoader = null;
if (workerMode == WorkerMode.DRIVER) {
workerId = driverId;
currentTaskId.set(UniqueId.randomId());
currentTaskId.set(TaskId.randomId());
currentDriverId = driverId;
} else {
workerId = UniqueId.randomId();
this.currentTaskId.set(UniqueId.NIL);
this.currentTaskId.set(TaskId.NIL);
this.currentDriverId = UniqueId.NIL;
}
}
@@ -65,7 +66,7 @@ public class WorkerContext {
* @return For the main thread, this method returns the ID of this worker's current running task;
* for other threads, this method returns a random ID.
*/
public UniqueId getCurrentTaskId() {
public TaskId getCurrentTaskId() {
return currentTaskId.get();
}
@@ -9,13 +9,15 @@ import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.ray.api.Checkpointable.Checkpoint;
import org.ray.api.id.BaseId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.api.runtimecontext.NodeInfo;
import org.ray.runtime.generated.ActorCheckpointIdData;
import org.ray.runtime.generated.ClientTableData;
import org.ray.runtime.generated.EntryType;
import org.ray.runtime.generated.TablePrefix;
import org.ray.runtime.util.UniqueIdUtil;
import org.ray.runtime.util.IdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -112,7 +114,7 @@ public class GcsClient {
/**
* Query whether the raylet task exists in Gcs.
*/
public boolean rayletTaskExistsInGcs(UniqueId taskId) {
public boolean rayletTaskExistsInGcs(TaskId taskId) {
byte[] key = ArrayUtils.addAll(TablePrefix.name(TablePrefix.RAYLET_TASK).getBytes(),
taskId.getBytes());
RedisClient client = getShardClient(taskId);
@@ -132,7 +134,7 @@ public class GcsClient {
if (result != null) {
ActorCheckpointIdData data =
ActorCheckpointIdData.getRootAsActorCheckpointIdData(ByteBuffer.wrap(result));
UniqueId[] checkpointIds = UniqueIdUtil.getUniqueIdsFromByteBuffer(
UniqueId[] checkpointIds = IdUtil.getUniqueIdsFromByteBuffer(
data.checkpointIdsAsByteBuffer());
for (int i = 0; i < checkpointIds.length; i++) {
@@ -143,8 +145,8 @@ public class GcsClient {
return checkpoints;
}
private RedisClient getShardClient(UniqueId key) {
return shards.get((int) Long.remainderUnsigned(UniqueIdUtil.murmurHashCode(key),
private RedisClient getShardClient(BaseId key) {
return shards.get((int) Long.remainderUnsigned(IdUtil.murmurHashCode(key),
shards.size()));
}
@@ -9,7 +9,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.arrow.plasma.ObjectStoreLink;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
import org.ray.runtime.RayDevRuntime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,16 +24,16 @@ public class MockObjectStore implements ObjectStoreLink {
private static final int GET_CHECK_INTERVAL_MS = 100;
private final RayDevRuntime runtime;
private final Map<UniqueId, byte[]> data = new ConcurrentHashMap<>();
private final Map<UniqueId, byte[]> metadata = new ConcurrentHashMap<>();
private final List<Consumer<UniqueId>> objectPutCallbacks;
private final Map<ObjectId, byte[]> data = new ConcurrentHashMap<>();
private final Map<ObjectId, byte[]> metadata = new ConcurrentHashMap<>();
private final List<Consumer<ObjectId>> objectPutCallbacks;
public MockObjectStore(RayDevRuntime runtime) {
this.runtime = runtime;
this.objectPutCallbacks = new ArrayList<>();
}
public void addObjectPutCallback(Consumer<UniqueId> callback) {
public void addObjectPutCallback(Consumer<ObjectId> callback) {
this.objectPutCallbacks.add(callback);
}
@@ -44,13 +44,12 @@ public class MockObjectStore implements ObjectStoreLink {
.error("{} cannot put null: {}, {}", logPrefix(), objectId, Arrays.toString(value));
System.exit(-1);
}
UniqueId uniqueId = new UniqueId(objectId);
data.put(uniqueId, value);
ObjectId id = new ObjectId(objectId);
data.put(id, value);
if (metadataValue != null) {
metadata.put(uniqueId, metadataValue);
metadata.put(id, metadataValue);
}
UniqueId id = new UniqueId(objectId);
for (Consumer<UniqueId> callback : objectPutCallbacks) {
for (Consumer<ObjectId> callback : objectPutCallbacks) {
callback.accept(id);
}
}
@@ -85,7 +84,7 @@ public class MockObjectStore implements ObjectStoreLink {
}
ready = 0;
for (byte[] id : objectIds) {
if (data.containsKey(new UniqueId(id))) {
if (data.containsKey(new ObjectId(id))) {
ready += 1;
}
}
@@ -93,8 +92,8 @@ public class MockObjectStore implements ObjectStoreLink {
}
ArrayList<ObjectStoreData> rets = new ArrayList<>();
for (byte[] objId : objectIds) {
UniqueId uniqueId = new UniqueId(objId);
rets.add(new ObjectStoreData(metadata.get(uniqueId), data.get(uniqueId)));
ObjectId objectId = new ObjectId(objId);
rets.add(new ObjectStoreData(metadata.get(objectId), data.get(objectId)));
}
return rets;
}
@@ -121,7 +120,7 @@ public class MockObjectStore implements ObjectStoreLink {
@Override
public boolean contains(byte[] objectId) {
return data.containsKey(new UniqueId(objectId));
return data.containsKey(new ObjectId(objectId));
}
private String logPrefix() {
@@ -138,11 +137,11 @@ public class MockObjectStore implements ObjectStoreLink {
return stes[k].getFileName() + ":" + stes[k].getLineNumber();
}
public boolean isObjectReady(UniqueId id) {
public boolean isObjectReady(ObjectId id) {
return data.containsKey(id);
}
public void free(UniqueId id) {
public void free(ObjectId id) {
data.remove(id);
metadata.remove(id);
}
@@ -12,13 +12,13 @@ import org.ray.api.exception.RayActorException;
import org.ray.api.exception.RayException;
import org.ray.api.exception.RayWorkerException;
import org.ray.api.exception.UnreconstructableException;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
import org.ray.runtime.AbstractRayRuntime;
import org.ray.runtime.RayDevRuntime;
import org.ray.runtime.config.RunMode;
import org.ray.runtime.generated.ErrorType;
import org.ray.runtime.util.IdUtil;
import org.ray.runtime.util.Serializer;
import org.ray.runtime.util.UniqueIdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,7 +61,7 @@ public class ObjectStoreProxy {
* @param <T> Type of the object.
* @return The GetResult object.
*/
public <T> GetResult<T> get(UniqueId id, int timeoutMs) {
public <T> GetResult<T> get(ObjectId id, int timeoutMs) {
List<GetResult<T>> list = get(ImmutableList.of(id), timeoutMs);
return list.get(0);
}
@@ -74,8 +74,8 @@ public class ObjectStoreProxy {
* @param <T> Type of these objects.
* @return A list of GetResult objects.
*/
public <T> List<GetResult<T>> get(List<UniqueId> ids, int timeoutMs) {
byte[][] binaryIds = UniqueIdUtil.getIdBytes(ids);
public <T> List<GetResult<T>> get(List<ObjectId> ids, int timeoutMs) {
byte[][] binaryIds = IdUtil.getIdBytes(ids);
List<ObjectStoreData> dataAndMetaList = objectStore.get().get(binaryIds, timeoutMs);
List<GetResult<T>> results = new ArrayList<>();
@@ -114,7 +114,7 @@ public class ObjectStoreProxy {
}
@SuppressWarnings("unchecked")
private <T> GetResult<T> deserializeFromMeta(byte[] meta, byte[] data, UniqueId objectId) {
private <T> GetResult<T> deserializeFromMeta(byte[] meta, byte[] data, ObjectId objectId) {
if (Arrays.equals(meta, RAW_TYPE_META)) {
return (GetResult<T>) new GetResult<>(true, data, null);
} else if (Arrays.equals(meta, WORKER_EXCEPTION_META)) {
@@ -133,7 +133,7 @@ public class ObjectStoreProxy {
* @param id Id of the object.
* @param object The object to put.
*/
public void put(UniqueId id, Object object) {
public void put(ObjectId id, Object object) {
try {
if (object instanceof byte[]) {
// If the object is a byte array, skip serializing it and use a special metadata to
@@ -153,7 +153,7 @@ public class ObjectStoreProxy {
* @param id Id of the object.
* @param serializedObject The serialized object to put.
*/
public void putSerialized(UniqueId id, byte[] serializedObject) {
public void putSerialized(ObjectId id, byte[] serializedObject) {
try {
objectStore.get().put(id.getBytes(), serializedObject, null);
} catch (DuplicateObjectException e) {
@@ -17,6 +17,8 @@ import java.util.concurrent.Executors;
import org.apache.commons.lang3.NotImplementedException;
import org.ray.api.RayObject;
import org.ray.api.WaitResult;
import org.ray.api.id.ObjectId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.RayDevRuntime;
import org.ray.runtime.Worker;
@@ -33,7 +35,7 @@ public class MockRayletClient implements RayletClient {
private static final Logger LOGGER = LoggerFactory.getLogger(MockRayletClient.class);
private final Map<UniqueId, Set<TaskSpec>> waitingTasks = new ConcurrentHashMap<>();
private final Map<ObjectId, Set<TaskSpec>> waitingTasks = new ConcurrentHashMap<>();
private final MockObjectStore store;
private final RayDevRuntime runtime;
private final ExecutorService exec;
@@ -52,7 +54,7 @@ public class MockRayletClient implements RayletClient {
currentWorker = new ThreadLocal<>();
}
public synchronized void onObjectPut(UniqueId id) {
public synchronized void onObjectPut(ObjectId id) {
Set<TaskSpec> tasks = waitingTasks.get(id);
if (tasks != null) {
waitingTasks.remove(id);
@@ -98,7 +100,7 @@ public class MockRayletClient implements RayletClient {
@Override
public synchronized void submitTask(TaskSpec task) {
LOGGER.debug("Submitting task: {}.", task);
Set<UniqueId> unreadyObjects = getUnreadyObjects(task);
Set<ObjectId> unreadyObjects = getUnreadyObjects(task);
if (unreadyObjects.isEmpty()) {
// If all dependencies are ready, execute this task.
exec.submit(() -> {
@@ -109,7 +111,7 @@ public class MockRayletClient implements RayletClient {
// put the dummy object in object store, so those tasks which depends on it
// can be executed.
if (task.isActorCreationTask() || task.isActorTask()) {
UniqueId[] returnIds = task.returnIds;
ObjectId[] returnIds = task.returnIds;
store.put(returnIds[returnIds.length - 1].getBytes(),
new byte[]{}, new byte[]{});
}
@@ -119,14 +121,14 @@ public class MockRayletClient implements RayletClient {
});
} else {
// If some dependencies aren't ready yet, put this task in waiting list.
for (UniqueId id : unreadyObjects) {
for (ObjectId id : unreadyObjects) {
waitingTasks.computeIfAbsent(id, k -> new HashSet<>()).add(task);
}
}
}
private Set<UniqueId> getUnreadyObjects(TaskSpec spec) {
Set<UniqueId> unreadyObjects = new HashSet<>();
private Set<ObjectId> getUnreadyObjects(TaskSpec spec) {
Set<ObjectId> unreadyObjects = new HashSet<>();
// Check whether task arguments are ready.
for (FunctionArg arg : spec.args) {
if (arg.id != null) {
@@ -136,7 +138,7 @@ public class MockRayletClient implements RayletClient {
}
}
// Check whether task dependencies are ready.
for (UniqueId id : spec.getExecutionDependencies()) {
for (ObjectId id : spec.getExecutionDependencies()) {
if (!store.isObjectReady(id)) {
unreadyObjects.add(id);
}
@@ -151,24 +153,24 @@ public class MockRayletClient implements RayletClient {
}
@Override
public void fetchOrReconstruct(List<UniqueId> objectIds, boolean fetchOnly,
UniqueId currentTaskId) {
public void fetchOrReconstruct(List<ObjectId> objectIds, boolean fetchOnly,
TaskId currentTaskId) {
}
@Override
public void notifyUnblocked(UniqueId currentTaskId) {
public void notifyUnblocked(TaskId currentTaskId) {
}
@Override
public UniqueId generateTaskId(UniqueId driverId, UniqueId parentTaskId, int taskIndex) {
return UniqueId.randomId();
public TaskId generateTaskId(UniqueId driverId, TaskId parentTaskId, int taskIndex) {
return TaskId.randomId();
}
@Override
public <T> WaitResult<T> wait(List<RayObject<T>> waitFor, int numReturns, int
timeoutMs, UniqueId currentTaskId) {
timeoutMs, TaskId currentTaskId) {
if (waitFor == null || waitFor.isEmpty()) {
return new WaitResult<>(ImmutableList.of(), ImmutableList.of());
}
@@ -191,9 +193,9 @@ public class MockRayletClient implements RayletClient {
}
@Override
public void freePlasmaObjects(List<UniqueId> objectIds, boolean localOnly,
public void freePlasmaObjects(List<ObjectId> objectIds, boolean localOnly,
boolean deleteCreatingTasks) {
for (UniqueId id : objectIds) {
for (ObjectId id : objectIds) {
store.free(id);
}
}
@@ -3,6 +3,8 @@ package org.ray.runtime.raylet;
import java.util.List;
import org.ray.api.RayObject;
import org.ray.api.WaitResult;
import org.ray.api.id.ObjectId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.task.TaskSpec;
@@ -15,16 +17,16 @@ public interface RayletClient {
TaskSpec getTask();
void fetchOrReconstruct(List<UniqueId> objectIds, boolean fetchOnly, UniqueId currentTaskId);
void fetchOrReconstruct(List<ObjectId> objectIds, boolean fetchOnly, TaskId currentTaskId);
void notifyUnblocked(UniqueId currentTaskId);
void notifyUnblocked(TaskId currentTaskId);
UniqueId generateTaskId(UniqueId driverId, UniqueId parentTaskId, int taskIndex);
TaskId generateTaskId(UniqueId driverId, TaskId parentTaskId, int taskIndex);
<T> WaitResult<T> wait(List<RayObject<T>> waitFor, int numReturns, int
timeoutMs, UniqueId currentTaskId);
timeoutMs, TaskId currentTaskId);
void freePlasmaObjects(List<UniqueId> objectIds, boolean localOnly, boolean deleteCreatingTasks);
void freePlasmaObjects(List<ObjectId> objectIds, boolean localOnly, boolean deleteCreatingTasks);
UniqueId prepareCheckpoint(UniqueId actorId);
@@ -11,6 +11,8 @@ import java.util.Map;
import org.ray.api.RayObject;
import org.ray.api.WaitResult;
import org.ray.api.exception.RayException;
import org.ray.api.id.ObjectId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.functionmanager.JavaFunctionDescriptor;
import org.ray.runtime.generated.Arg;
@@ -20,7 +22,7 @@ import org.ray.runtime.generated.TaskInfo;
import org.ray.runtime.task.FunctionArg;
import org.ray.runtime.task.TaskLanguage;
import org.ray.runtime.task.TaskSpec;
import org.ray.runtime.util.UniqueIdUtil;
import org.ray.runtime.util.IdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,18 +52,18 @@ public class RayletClientImpl implements RayletClient {
@Override
public <T> WaitResult<T> wait(List<RayObject<T>> waitFor, int numReturns, int
timeoutMs, UniqueId currentTaskId) {
timeoutMs, TaskId currentTaskId) {
Preconditions.checkNotNull(waitFor);
if (waitFor.isEmpty()) {
return new WaitResult<>(new ArrayList<>(), new ArrayList<>());
}
List<UniqueId> ids = new ArrayList<>();
List<ObjectId> ids = new ArrayList<>();
for (RayObject<T> element : waitFor) {
ids.add(element.getId());
}
boolean[] ready = nativeWaitObject(client, UniqueIdUtil.getIdBytes(ids),
boolean[] ready = nativeWaitObject(client, IdUtil.getIdBytes(ids),
numReturns, timeoutMs, false, currentTaskId.getBytes());
List<RayObject<T>> readyList = new ArrayList<>();
List<RayObject<T>> unreadyList = new ArrayList<>();
@@ -101,31 +103,31 @@ public class RayletClientImpl implements RayletClient {
}
@Override
public void fetchOrReconstruct(List<UniqueId> objectIds, boolean fetchOnly,
UniqueId currentTaskId) {
public void fetchOrReconstruct(List<ObjectId> objectIds, boolean fetchOnly,
TaskId currentTaskId) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Blocked on objects for task {}, object IDs are {}",
UniqueIdUtil.computeTaskId(objectIds.get(0)), objectIds);
objectIds.get(0).getTaskId(), objectIds);
}
nativeFetchOrReconstruct(client, UniqueIdUtil.getIdBytes(objectIds),
nativeFetchOrReconstruct(client, IdUtil.getIdBytes(objectIds),
fetchOnly, currentTaskId.getBytes());
}
@Override
public UniqueId generateTaskId(UniqueId driverId, UniqueId parentTaskId, int taskIndex) {
public TaskId generateTaskId(UniqueId driverId, TaskId parentTaskId, int taskIndex) {
byte[] bytes = nativeGenerateTaskId(driverId.getBytes(), parentTaskId.getBytes(), taskIndex);
return new UniqueId(bytes);
return new TaskId(bytes);
}
@Override
public void notifyUnblocked(UniqueId currentTaskId) {
public void notifyUnblocked(TaskId currentTaskId) {
nativeNotifyUnblocked(client, currentTaskId.getBytes());
}
@Override
public void freePlasmaObjects(List<UniqueId> objectIds, boolean localOnly,
public void freePlasmaObjects(List<ObjectId> objectIds, boolean localOnly,
boolean deleteCreatingTasks) {
byte[][] objectIdsArray = UniqueIdUtil.getIdBytes(objectIds);
byte[][] objectIdsArray = IdUtil.getIdBytes(objectIds);
nativeFreePlasmaObjects(client, objectIdsArray, localOnly, deleteCreatingTasks);
}
@@ -144,8 +146,8 @@ public class RayletClientImpl implements RayletClient {
bb.order(ByteOrder.LITTLE_ENDIAN);
TaskInfo info = TaskInfo.getRootAsTaskInfo(bb);
UniqueId driverId = UniqueId.fromByteBuffer(info.driverIdAsByteBuffer());
UniqueId taskId = UniqueId.fromByteBuffer(info.taskIdAsByteBuffer());
UniqueId parentTaskId = UniqueId.fromByteBuffer(info.parentTaskIdAsByteBuffer());
TaskId taskId = TaskId.fromByteBuffer(info.taskIdAsByteBuffer());
TaskId parentTaskId = TaskId.fromByteBuffer(info.parentTaskIdAsByteBuffer());
int parentCounter = info.parentCounter();
UniqueId actorCreationId = UniqueId.fromByteBuffer(info.actorCreationIdAsByteBuffer());
int maxActorReconstructions = info.maxActorReconstructions();
@@ -154,7 +156,7 @@ public class RayletClientImpl implements RayletClient {
int actorCounter = info.actorCounter();
// Deserialize new actor handles
UniqueId[] newActorHandles = UniqueIdUtil.getUniqueIdsFromByteBuffer(
UniqueId[] newActorHandles = IdUtil.getUniqueIdsFromByteBuffer(
info.newActorHandlesAsByteBuffer());
// Deserialize args
@@ -166,8 +168,7 @@ public class RayletClientImpl implements RayletClient {
if (objectIdsLength > 0) {
Preconditions.checkArgument(objectIdsLength == 1,
"This arg has more than one id: {}", objectIdsLength);
UniqueId id = UniqueIdUtil.getUniqueIdsFromByteBuffer(arg.objectIdsAsByteBuffer())[0];
args[i] = FunctionArg.passByReference(id);
args[i] = FunctionArg.passByReference(ObjectId.fromByteBuffer(arg.objectIdsAsByteBuffer()));
} else {
ByteBuffer lbb = arg.dataAsByteBuffer();
Preconditions.checkState(lbb != null && lbb.remaining() > 0);
@@ -177,7 +178,7 @@ public class RayletClientImpl implements RayletClient {
}
}
// Deserialize return ids
UniqueId[] returnIds = UniqueIdUtil.getUniqueIdsFromByteBuffer(info.returnsAsByteBuffer());
ObjectId[] returnIds = IdUtil.getObjectIdsFromByteBuffer(info.returnsAsByteBuffer());
// Deserialize required resources;
Map<String, Double> resources = new HashMap<>();
@@ -213,7 +214,7 @@ public class RayletClientImpl implements RayletClient {
// Serialize the new actor handles.
int newActorHandlesOffset
= fbb.createString(UniqueIdUtil.concatUniqueIds(task.newActorHandles));
= fbb.createString(IdUtil.concatIds(task.newActorHandles));
// Serialize args
int[] argsOffsets = new int[task.args.length];
@@ -222,7 +223,7 @@ public class RayletClientImpl implements RayletClient {
int dataOffset = 0;
if (task.args[i].id != null) {
objectIdOffset = fbb.createString(
UniqueIdUtil.concatUniqueIds(new UniqueId[]{task.args[i].id}));
IdUtil.concatIds(new ObjectId[]{task.args[i].id}));
} else {
objectIdOffset = fbb.createString("");
}
@@ -234,7 +235,7 @@ public class RayletClientImpl implements RayletClient {
int argsOffset = fbb.createVectorOfTables(argsOffsets);
// Serialize returns
int returnsOffset = fbb.createString(UniqueIdUtil.concatUniqueIds(task.returnIds));
int returnsOffset = fbb.createString(IdUtil.concatIds(task.returnIds));
// Serialize required resources
// The required_resources vector indicates the quantities of the different
@@ -5,7 +5,7 @@ import java.util.List;
import org.ray.api.Ray;
import org.ray.api.RayActor;
import org.ray.api.RayObject;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
import org.ray.runtime.AbstractRayRuntime;
import org.ray.runtime.util.Serializer;
@@ -24,7 +24,7 @@ public class ArgumentsBuilder {
FunctionArg[] ret = new FunctionArg[args.length];
for (int i = 0; i < ret.length; i++) {
Object arg = args[i];
UniqueId id = null;
ObjectId id = null;
byte[] data = null;
if (arg == null) {
data = Serializer.encode(null);
@@ -59,7 +59,7 @@ public class ArgumentsBuilder {
*/
public static Object[] unwrap(TaskSpec task, ClassLoader classLoader) {
Object[] realArgs = new Object[task.args.length];
List<UniqueId> idsToFetch = new ArrayList<>();
List<ObjectId> idsToFetch = new ArrayList<>();
List<Integer> indices = new ArrayList<>();
for (int i = 0; i < task.args.length; i++) {
FunctionArg arg = task.args[i];
@@ -1,6 +1,6 @@
package org.ray.runtime.task;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
/**
* Represents a function argument in task spec.
@@ -12,13 +12,13 @@ public class FunctionArg {
/**
* The id of this argument (passed by reference).
*/
public final UniqueId id;
public final ObjectId id;
/**
* Serialized data of this argument (passed by value).
*/
public final byte[] data;
private FunctionArg(UniqueId id, byte[] data) {
private FunctionArg(ObjectId id, byte[] data) {
this.id = id;
this.data = data;
}
@@ -26,7 +26,7 @@ public class FunctionArg {
/**
* Create a FunctionArg that will be passed by reference.
*/
public static FunctionArg passByReference(UniqueId id) {
public static FunctionArg passByReference(ObjectId id) {
return new FunctionArg(id, null);
}
@@ -5,6 +5,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.ray.api.id.ObjectId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.functionmanager.FunctionDescriptor;
import org.ray.runtime.functionmanager.JavaFunctionDescriptor;
@@ -19,10 +21,10 @@ public class TaskSpec {
public final UniqueId driverId;
// Task ID of the task.
public final UniqueId taskId;
public final TaskId taskId;
// Task ID of the parent task.
public final UniqueId parentTaskId;
public final TaskId parentTaskId;
// A count of the number of tasks submitted by the parent task before this one.
public final int parentCounter;
@@ -49,7 +51,7 @@ public class TaskSpec {
public final FunctionArg[] args;
// return ids
public final UniqueId[] returnIds;
public final ObjectId[] returnIds;
// The task's resource demands.
public final Map<String, Double> resources;
@@ -62,7 +64,7 @@ public class TaskSpec {
// is Python, the type is PyFunctionDescriptor.
private final FunctionDescriptor functionDescriptor;
private List<UniqueId> executionDependencies;
private List<ObjectId> executionDependencies;
public boolean isActorTask() {
return !actorId.isNil();
@@ -74,8 +76,8 @@ public class TaskSpec {
public TaskSpec(
UniqueId driverId,
UniqueId taskId,
UniqueId parentTaskId,
TaskId taskId,
TaskId parentTaskId,
int parentCounter,
UniqueId actorCreationId,
int maxActorReconstructions,
@@ -84,7 +86,7 @@ public class TaskSpec {
int actorCounter,
UniqueId[] newActorHandles,
FunctionArg[] args,
UniqueId[] returnIds,
ObjectId[] returnIds,
Map<String, Double> resources,
TaskLanguage language,
FunctionDescriptor functionDescriptor) {
@@ -125,7 +127,7 @@ public class TaskSpec {
return (PyFunctionDescriptor) functionDescriptor;
}
public List<UniqueId> getExecutionDependencies() {
public List<ObjectId> getExecutionDependencies() {
return executionDependencies;
}
@@ -3,19 +3,20 @@ package org.ray.runtime.util;
import com.google.common.base.Preconditions;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.List;
import org.ray.api.id.BaseId;
import org.ray.api.id.ObjectId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
/**
* Helper method for UniqueId.
* Helper method for different Ids.
* Note: any changes to these methods must be synced with C++ helper functions
* in src/ray/id.h
*/
public class UniqueIdUtil {
public static final int OBJECT_INDEX_POS = 0;
public static final int OBJECT_INDEX_LENGTH = 4;
public class IdUtil {
public static final int OBJECT_INDEX_POS = 16;
/**
* Compute the object ID of an object returned by the task.
@@ -24,7 +25,7 @@ public class UniqueIdUtil {
* @param returnIndex What number return value this object is in the task.
* @return The computed object ID.
*/
public static UniqueId computeReturnId(UniqueId taskId, int returnIndex) {
public static ObjectId computeReturnId(TaskId taskId, int returnIndex) {
return computeObjectId(taskId, returnIndex);
}
@@ -34,14 +35,13 @@ public class UniqueIdUtil {
* @param index The index which can distinguish different objects in one task.
* @return The computed object ID.
*/
private static UniqueId computeObjectId(UniqueId taskId, int index) {
byte[] objId = new byte[UniqueId.LENGTH];
System.arraycopy(taskId.getBytes(),0, objId, 0, UniqueId.LENGTH);
ByteBuffer wbb = ByteBuffer.wrap(objId);
private static ObjectId computeObjectId(TaskId taskId, int index) {
byte[] bytes = new byte[ObjectId.LENGTH];
System.arraycopy(taskId.getBytes(), 0, bytes, 0, taskId.size());
ByteBuffer wbb = ByteBuffer.wrap(bytes);
wbb.order(ByteOrder.LITTLE_ENDIAN);
wbb.putInt(UniqueIdUtil.OBJECT_INDEX_POS, index);
return new UniqueId(objId);
wbb.putInt(OBJECT_INDEX_POS, index);
return new ObjectId(bytes);
}
/**
@@ -51,26 +51,11 @@ public class UniqueIdUtil {
* @param putIndex What number put this object was created by in the task.
* @return The computed object ID.
*/
public static UniqueId computePutId(UniqueId taskId, int putIndex) {
public static ObjectId computePutId(TaskId taskId, int putIndex) {
// We multiply putIndex by -1 to distinguish from returnIndex.
return computeObjectId(taskId, -1 * putIndex);
}
/**
* Compute the task ID of the task that created the object.
*
* @param objectId The object ID.
* @return The task ID of the task that created this object.
*/
public static UniqueId computeTaskId(UniqueId objectId) {
byte[] taskId = new byte[UniqueId.LENGTH];
System.arraycopy(objectId.getBytes(), 0, taskId, 0, UniqueId.LENGTH);
Arrays.fill(taskId, UniqueIdUtil.OBJECT_INDEX_POS,
UniqueIdUtil.OBJECT_INDEX_POS + UniqueIdUtil.OBJECT_INDEX_LENGTH, (byte) 0);
return new UniqueId(taskId);
}
/**
* Generate the return ids of a task.
*
@@ -78,15 +63,15 @@ public class UniqueIdUtil {
* @param numReturns The number of returnIds.
* @return The Return Ids of this task.
*/
public static UniqueId[] genReturnIds(UniqueId taskId, int numReturns) {
UniqueId[] ret = new UniqueId[numReturns];
public static ObjectId[] genReturnIds(TaskId taskId, int numReturns) {
ObjectId[] ret = new ObjectId[numReturns];
for (int i = 0; i < numReturns; i++) {
ret[i] = UniqueIdUtil.computeReturnId(taskId, i + 1);
ret[i] = IdUtil.computeReturnId(taskId, i + 1);
}
return ret;
}
public static byte[][] getIdBytes(List<UniqueId> objectIds) {
public static <T extends BaseId> byte[][] getIdBytes(List<T> objectIds) {
int size = objectIds.size();
byte[][] ids = new byte[size][];
for (int i = 0; i < size; i++) {
@@ -95,6 +80,24 @@ public class UniqueIdUtil {
return ids;
}
public static byte[][] getByteListFromByteBuffer(ByteBuffer byteBufferOfIds, int length) {
Preconditions.checkArgument(byteBufferOfIds != null);
byte[] bytesOfIds = new byte[byteBufferOfIds.remaining()];
byteBufferOfIds.get(bytesOfIds, 0, byteBufferOfIds.remaining());
int count = bytesOfIds.length / length;
byte[][] idBytes = new byte[count][];
for (int i = 0; i < count; ++i) {
byte[] id = new byte[length];
System.arraycopy(bytesOfIds, i * length, id, 0, length);
idBytes[i] = id;
}
return idBytes;
}
/**
* Get unique IDs from concatenated ByteBuffer.
*
@@ -102,34 +105,48 @@ public class UniqueIdUtil {
* @return The array of unique IDs.
*/
public static UniqueId[] getUniqueIdsFromByteBuffer(ByteBuffer byteBufferOfIds) {
Preconditions.checkArgument(byteBufferOfIds != null);
byte[][]idBytes = getByteListFromByteBuffer(byteBufferOfIds, UniqueId.LENGTH);
UniqueId[] uniqueIds = new UniqueId[idBytes.length];
byte[] bytesOfIds = new byte[byteBufferOfIds.remaining()];
byteBufferOfIds.get(bytesOfIds, 0, byteBufferOfIds.remaining());
int count = bytesOfIds.length / UniqueId.LENGTH;
UniqueId[] uniqueIds = new UniqueId[count];
for (int i = 0; i < count; ++i) {
byte[] id = new byte[UniqueId.LENGTH];
System.arraycopy(bytesOfIds, i * UniqueId.LENGTH, id, 0, UniqueId.LENGTH);
uniqueIds[i] = UniqueId.fromByteBuffer(ByteBuffer.wrap(id));
for (int i = 0; i < idBytes.length; ++i) {
uniqueIds[i] = UniqueId.fromByteBuffer(ByteBuffer.wrap(idBytes[i]));
}
return uniqueIds;
}
/**
* Get object IDs from concatenated ByteBuffer.
*
* @param byteBufferOfIds The ByteBuffer concatenated from IDs.
* @return The array of object IDs.
*/
public static ObjectId[] getObjectIdsFromByteBuffer(ByteBuffer byteBufferOfIds) {
byte[][]idBytes = getByteListFromByteBuffer(byteBufferOfIds, UniqueId.LENGTH);
ObjectId[] objectIds = new ObjectId[idBytes.length];
for (int i = 0; i < idBytes.length; ++i) {
objectIds[i] = ObjectId.fromByteBuffer(ByteBuffer.wrap(idBytes[i]));
}
return objectIds;
}
/**
* Concatenate IDs to a ByteBuffer.
*
* @param ids The array of IDs that will be concatenated.
* @return A ByteBuffer that contains bytes of concatenated IDs.
*/
public static ByteBuffer concatUniqueIds(UniqueId[] ids) {
byte[] bytesOfIds = new byte[UniqueId.LENGTH * ids.length];
public static <T extends BaseId> ByteBuffer concatIds(T[] ids) {
int length = 0;
if (ids != null && ids.length != 0) {
length = ids[0].size() * ids.length;
}
byte[] bytesOfIds = new byte[length];
for (int i = 0; i < ids.length; ++i) {
System.arraycopy(ids[i].getBytes(), 0, bytesOfIds,
i * UniqueId.LENGTH, UniqueId.LENGTH);
i * ids[i].size(), ids[i].size());
}
return ByteBuffer.wrap(bytesOfIds);
@@ -139,8 +156,8 @@ public class UniqueIdUtil {
/**
* Compute the murmur hash code of this ID.
*/
public static long murmurHashCode(UniqueId id) {
return murmurHash64A(id.getBytes(), UniqueId.LENGTH, 0);
public static long murmurHashCode(BaseId id) {
return murmurHash64A(id.getBytes(), id.size(), 0);
}
/**
@@ -6,7 +6,7 @@ import org.ray.api.Ray;
import org.ray.api.RayObject;
import org.ray.api.TestUtils;
import org.ray.api.exception.RayException;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
import org.ray.runtime.RayObjectImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,7 +20,7 @@ public class ClientExceptionTest extends BaseTest {
@Test
public void testWaitAndCrash() {
TestUtils.skipTestUnderSingleProcess();
UniqueId randomId = UniqueId.randomId();
ObjectId randomId = ObjectId.randomId();
RayObject<String> notExisting = new RayObjectImpl(randomId);
Thread thread = new Thread(() -> {
@@ -5,7 +5,7 @@ import java.util.List;
import java.util.stream.Collectors;
import org.ray.api.Ray;
import org.ray.api.RayObject;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -23,7 +23,7 @@ public class ObjectStoreTest extends BaseTest {
@Test
public void testGetMultipleObjects() {
List<Integer> ints = ImmutableList.of(1, 2, 3, 4, 5);
List<UniqueId> ids = ints.stream().map(obj -> Ray.put(obj).getId())
List<ObjectId> ids = ints.stream().map(obj -> Ray.put(obj).getId())
.collect(Collectors.toList());
Assert.assertEquals(ints, Ray.get(ids));
}
@@ -6,7 +6,6 @@ import org.ray.api.RayObject;
import org.ray.api.TestUtils;
import org.ray.api.annotation.RayRemote;
import org.ray.runtime.AbstractRayRuntime;
import org.ray.runtime.util.UniqueIdUtil;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -38,7 +37,7 @@ public class PlasmaFreeTest extends BaseTest {
final boolean result = TestUtils.waitForCondition(
() -> !(((AbstractRayRuntime)Ray.internal()).getGcsClient())
.rayletTaskExistsInGcs(UniqueIdUtil.computeTaskId(helloId.getId())), 50);
.rayletTaskExistsInGcs(helloId.getId().getTaskId()), 50);
Assert.assertTrue(result);
}
@@ -7,7 +7,7 @@ import org.ray.api.Ray;
import org.ray.api.RayActor;
import org.ray.api.RayObject;
import org.ray.api.TestUtils;
import org.ray.api.id.UniqueId;
import org.ray.api.id.ObjectId;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -23,7 +23,7 @@ public class StressTest extends BaseTest {
for (int numIterations : ImmutableList.of(1, 10, 100, 1000)) {
int numTasks = 1000 / numIterations;
for (int i = 0; i < numIterations; i++) {
List<UniqueId> resultIds = new ArrayList<>();
List<ObjectId> resultIds = new ArrayList<>();
for (int j = 0; j < numTasks; j++) {
resultIds.add(Ray.call(StressTest::echo, 1).getId());
}
@@ -60,7 +60,7 @@ public class StressTest extends BaseTest {
}
public int ping(int n) {
List<UniqueId> objectIds = new ArrayList<>();
List<ObjectId> objectIds = new ArrayList<>();
for (int i = 0; i < n; i++) {
objectIds.add(Ray.call(Actor::ping, actor).getId());
}
@@ -76,7 +76,7 @@ public class StressTest extends BaseTest {
public void testSubmittingManyTasksToOneActor() {
TestUtils.skipTestUnderSingleProcess();
RayActor<Actor> actor = Ray.createActor(Actor::new);
List<UniqueId> objectIds = new ArrayList<>();
List<ObjectId> objectIds = new ArrayList<>();
for (int i = 0; i < 10; i++) {
RayActor<Worker> worker = Ray.createActor(Worker::new, actor);
objectIds.add(Ray.call(Worker::ping, worker, 100).getId());
@@ -3,8 +3,10 @@ package org.ray.api.test;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.xml.bind.DatatypeConverter;
import org.ray.api.id.ObjectId;
import org.ray.api.id.TaskId;
import org.ray.api.id.UniqueId;
import org.ray.runtime.util.UniqueIdUtil;
import org.ray.runtime.util.IdUtil;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -42,7 +44,7 @@ public class UniqueIdTest {
// Test `genNil()`
UniqueId id6 = UniqueId.genNil();
UniqueId id6 = UniqueId.NIL;
Assert.assertEquals("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase(), id6.toString());
Assert.assertTrue(id6.isNil());
}
@@ -50,33 +52,33 @@ public class UniqueIdTest {
@Test
public void testComputeReturnId() {
// Mock a taskId, and the lowest 4 bytes should be 0.
UniqueId taskId = UniqueId.fromHexString("00000000123456789ABCDEF123456789ABCDEF00");
TaskId taskId = TaskId.fromHexString("123456789ABCDEF123456789ABCDEF00");
UniqueId returnId = UniqueIdUtil.computeReturnId(taskId, 1);
Assert.assertEquals("01000000123456789abcdef123456789abcdef00", returnId.toString());
ObjectId returnId = IdUtil.computeReturnId(taskId, 1);
Assert.assertEquals("123456789abcdef123456789abcdef0001000000", returnId.toString());
returnId = UniqueIdUtil.computeReturnId(taskId, 0x01020304);
Assert.assertEquals("04030201123456789abcdef123456789abcdef00", returnId.toString());
returnId = IdUtil.computeReturnId(taskId, 0x01020304);
Assert.assertEquals("123456789abcdef123456789abcdef0004030201", returnId.toString());
}
@Test
public void testComputeTaskId() {
UniqueId objId = UniqueId.fromHexString("34421980123456789ABCDEF123456789ABCDEF00");
UniqueId taskId = UniqueIdUtil.computeTaskId(objId);
ObjectId objId = ObjectId.fromHexString("123456789ABCDEF123456789ABCDEF0034421980");
TaskId taskId = objId.getTaskId();
Assert.assertEquals("00000000123456789abcdef123456789abcdef00", taskId.toString());
Assert.assertEquals("123456789abcdef123456789abcdef00", taskId.toString());
}
@Test
public void testComputePutId() {
// Mock a taskId, the lowest 4 bytes should be 0.
UniqueId taskId = UniqueId.fromHexString("00000000123456789ABCDEF123456789ABCDEF00");
TaskId taskId = TaskId.fromHexString("123456789ABCDEF123456789ABCDEF00");
UniqueId putId = UniqueIdUtil.computePutId(taskId, 1);
Assert.assertEquals("FFFFFFFF123456789ABCDEF123456789ABCDEF00".toLowerCase(), putId.toString());
ObjectId putId = IdUtil.computePutId(taskId, 1);
Assert.assertEquals("123456789ABCDEF123456789ABCDEF00FFFFFFFF".toLowerCase(), putId.toString());
putId = UniqueIdUtil.computePutId(taskId, 0x01020304);
Assert.assertEquals("FCFCFDFE123456789ABCDEF123456789ABCDEF00".toLowerCase(), putId.toString());
putId = IdUtil.computePutId(taskId, 0x01020304);
Assert.assertEquals("123456789ABCDEF123456789ABCDEF00FCFCFDFE".toLowerCase(), putId.toString());
}
@Test
@@ -87,8 +89,8 @@ public class UniqueIdTest {
ids[i] = UniqueId.randomId();
}
ByteBuffer temp = UniqueIdUtil.concatUniqueIds(ids);
UniqueId[] res = UniqueIdUtil.getUniqueIdsFromByteBuffer(temp);
ByteBuffer temp = IdUtil.concatIds(ids);
UniqueId[] res = IdUtil.getUniqueIdsFromByteBuffer(temp);
for (int i = 0; i < len; ++i) {
Assert.assertEquals(ids[i], res[i]);
@@ -98,8 +100,28 @@ public class UniqueIdTest {
@Test
void testMurmurHash() {
UniqueId id = UniqueId.fromHexString("3131313131313131313132323232323232323232");
long remainder = Long.remainderUnsigned(UniqueIdUtil.murmurHashCode(id), 1000000000);
long remainder = Long.remainderUnsigned(IdUtil.murmurHashCode(id), 1000000000);
Assert.assertEquals(remainder, 787616861);
}
@Test
void testConcateIds() {
String taskHexStr = "123456789ABCDEF123456789ABCDEF00";
String objectHexStr = taskHexStr + "01020304";
ObjectId objectId1 = ObjectId.fromHexString(objectHexStr);
ObjectId objectId2 = ObjectId.fromHexString(objectHexStr);
TaskId[] taskIds = new TaskId[2];
taskIds[0] = objectId1.getTaskId();
taskIds[1] = objectId2.getTaskId();
ObjectId[] objectIds = new ObjectId[2];
objectIds[0] = objectId1;
objectIds[1] = objectId2;
String taskHexCompareStr = taskHexStr + taskHexStr;
String objectHexCompareStr = objectHexStr + objectHexStr;
Assert.assertEquals(DatatypeConverter.printHexBinary(
IdUtil.concatIds(taskIds).array()), taskHexCompareStr);
Assert.assertEquals(DatatypeConverter.printHexBinary(
IdUtil.concatIds(objectIds).array()), objectHexCompareStr);
}
}
+2 -2
View File
@@ -88,11 +88,11 @@ def compute_put_id(TaskID task_id, int64_t put_index):
if put_index < 1 or put_index > kMaxTaskPuts:
raise ValueError("The range of 'put_index' should be [1, %d]"
% kMaxTaskPuts)
return ObjectID(ComputePutId(task_id.native(), put_index).binary())
return ObjectID(CObjectID.for_put(task_id.native(), put_index).binary())
def compute_task_id(ObjectID object_id):
return TaskID(ComputeTaskId(object_id.native()).binary())
return TaskID(object_id.native().task_id().binary())
cdef c_bool is_simple_value(value, int *num_elements_contained):
+3 -4
View File
@@ -17,7 +17,6 @@ from ray.function_manager import FunctionDescriptor
import ray.ray_constants as ray_constants
import ray.signature as signature
import ray.worker
from ray.utils import _random_string
from ray import (ObjectID, ActorID, ActorHandleID, ActorClassID, TaskID,
DriverID)
@@ -308,7 +307,7 @@ class ActorClass(object):
raise Exception("Actors cannot be created before ray.init() "
"has been called.")
actor_id = ActorID(_random_string())
actor_id = ActorID.from_random()
# The actor cursor is a dummy object representing the most recent
# actor method invocation. For each subsequent method invocation,
# the current cursor should be added as a dependency, and then
@@ -670,7 +669,7 @@ class ActorHandle(object):
# to release, since it could be unpickled and submit another
# dependent task at any time. Therefore, we notify the backend of a
# random handle ID that will never actually be used.
new_actor_handle_id = ActorHandleID(_random_string())
new_actor_handle_id = ActorHandleID.from_random()
# Notify the backend to expect this new actor handle. The backend will
# not release the cursor for any new handles until the first task for
# each of the new handles is submitted.
@@ -780,7 +779,7 @@ def make_actor(cls, num_cpus, num_gpus, resources, max_reconstructions):
Class.__module__ = cls.__module__
Class.__name__ = cls.__name__
class_id = ActorClassID(_random_string())
class_id = ActorClassID.from_random()
return ActorClass(Class, class_id, max_reconstructions, num_cpus, num_gpus,
resources)
-6
View File
@@ -81,15 +81,9 @@ cdef extern from "ray/status.h" namespace "ray::StatusCode" nogil:
cdef extern from "ray/id.h" namespace "ray" nogil:
const CTaskID FinishTaskId(const CTaskID &task_id)
const CObjectID ComputeReturnId(const CTaskID &task_id,
int64_t return_index)
const CObjectID ComputePutId(const CTaskID &task_id, int64_t put_index)
const CTaskID ComputeTaskId(const CObjectID &object_id)
const CTaskID GenerateTaskId(const CDriverID &driver_id,
const CTaskID &parent_task_id,
int parent_task_counter)
int64_t ComputeObjectIndex(const CObjectID &object_id)
cdef extern from "ray/gcs/format/gcs_generated.h" nogil:
+55 -15
View File
@@ -1,12 +1,35 @@
from libcpp cimport bool as c_bool
from libcpp.string cimport string as c_string
from libc.stdint cimport uint8_t
from libc.stdint cimport uint8_t, int64_t
cdef extern from "ray/id.h" namespace "ray" nogil:
cdef cppclass CUniqueID "ray::UniqueID":
cdef cppclass CBaseID[T]:
@staticmethod
T from_random()
@staticmethod
T from_binary(const c_string &binary)
@staticmethod
const T nil()
@staticmethod
size_t size()
size_t hash() const
c_bool is_nil() const
c_bool operator==(const CBaseID &rhs) const
c_bool operator!=(const CBaseID &rhs) const
const uint8_t *data() const;
c_string binary() const;
c_string hex() const;
cdef cppclass CUniqueID "ray::UniqueID"(CBaseID):
CUniqueID()
CUniqueID(const c_string &binary)
CUniqueID(const CUniqueID &from_id)
@staticmethod
size_t size()
@staticmethod
CUniqueID from_random()
@@ -17,15 +40,8 @@ cdef extern from "ray/id.h" namespace "ray" nogil:
@staticmethod
const CUniqueID nil()
size_t hash() const
c_bool is_nil() const
c_bool operator==(const CUniqueID& rhs) const
c_bool operator!=(const CUniqueID& rhs) const
const uint8_t *data() const
uint8_t *mutable_data()
size_t size() const
c_string binary() const
c_string hex() const
@staticmethod
size_t size()
cdef cppclass CActorCheckpointID "ray::ActorCheckpointID"(CUniqueID):
@@ -67,16 +83,40 @@ cdef extern from "ray/id.h" namespace "ray" nogil:
@staticmethod
CDriverID from_binary(const c_string &binary)
cdef cppclass CTaskID "ray::TaskID"(CUniqueID):
cdef cppclass CTaskID "ray::TaskID"(CBaseID[CTaskID]):
@staticmethod
CTaskID from_binary(const c_string &binary)
cdef cppclass CObjectID" ray::ObjectID"(CUniqueID):
@staticmethod
const CTaskID nil()
@staticmethod
size_t size()
cdef cppclass CObjectID" ray::ObjectID"(CBaseID[CObjectID]):
@staticmethod
CObjectID from_binary(const c_string &binary)
@staticmethod
const CObjectID nil()
@staticmethod
CObjectID for_put(const CTaskID &task_id, int64_t index);
@staticmethod
CObjectID for_task_return(const CTaskID &task_id, int64_t index);
@staticmethod
size_t size()
c_bool is_put()
int64_t object_index() const
CTaskID task_id() const
cdef cppclass CWorkerID "ray::WorkerID"(CUniqueID):
@staticmethod
+116 -36
View File
@@ -6,10 +6,8 @@ See https://github.com/ray-project/ray/issues/3721.
# WARNING: Any additional ID types defined in this file must be added to the
# _ID_TYPES list at the bottom of this file.
from ray.includes.common cimport (
ComputePutId,
ComputeTaskId,
)
import os
from ray.includes.unique_ids cimport (
CActorCheckpointID,
CActorClassID,
@@ -28,12 +26,12 @@ from ray.includes.unique_ids cimport (
from ray.utils import decode
def check_id(b):
def check_id(b, size=kUniqueIDSize):
if not isinstance(b, bytes):
raise TypeError("Unsupported type: " + str(type(b)))
if len(b) != kUniqueIDSize:
if len(b) != size:
raise ValueError("ID string needs to have length " +
str(kUniqueIDSize))
str(size))
cdef extern from "ray/constants.h" nogil:
@@ -41,28 +39,27 @@ cdef extern from "ray/constants.h" nogil:
cdef int64_t kMaxTaskPuts
cdef class UniqueID:
cdef CUniqueID data
cdef class BaseID:
def __init__(self, id):
check_id(id)
self.data = CUniqueID.from_binary(id)
# To avoid the error of "Python int too large to convert to C ssize_t",
# here `cdef size_t` is required.
cdef size_t hash(self):
pass
@classmethod
def from_binary(cls, id_bytes):
if not isinstance(id_bytes, bytes):
raise TypeError("Expect bytes, got " + str(type(id_bytes)))
return cls(id_bytes)
def binary(self):
pass
@classmethod
def nil(cls):
return cls(CUniqueID.nil().binary())
def size(self):
pass
def __hash__(self):
return self.data.hash()
def hex(self):
pass
def is_nil(self):
return self.data.is_nil()
pass
def __hash__(self):
return self.hash()
def __eq__(self, other):
return type(self) == type(other) and self.binary() == other.binary()
@@ -70,18 +67,9 @@ cdef class UniqueID:
def __ne__(self, other):
return self.binary() != other.binary()
def size(self):
return self.data.size()
def binary(self):
return self.data.binary()
def __bytes__(self):
return self.binary()
def hex(self):
return decode(self.data.hex())
def __hex__(self):
return self.hex()
@@ -98,11 +86,52 @@ cdef class UniqueID:
# NOTE: The hash function used here must match the one in
# GetRedisContext in src/ray/gcs/tables.h. Changes to the
# hash function should only be made through std::hash in
# src/common/common.h
# src/common/common.h.
# Do not use __hash__ that returns signed uint64_t, which
# is different from std::hash in c++ code.
return self.hash()
cdef class UniqueID(BaseID):
cdef CUniqueID data
def __init__(self, id):
check_id(id)
self.data = CUniqueID.from_binary(id)
@classmethod
def from_binary(cls, id_bytes):
if not isinstance(id_bytes, bytes):
raise TypeError("Expect bytes, got " + str(type(id_bytes)))
return cls(id_bytes)
@classmethod
def nil(cls):
return cls(CUniqueID.nil().binary())
@classmethod
def from_random(cls):
return cls(os.urandom(CUniqueID.size()))
def size(self):
return CUniqueID.size()
def binary(self):
return self.data.binary()
def hex(self):
return decode(self.data.hex())
def is_nil(self):
return self.data.is_nil()
cdef size_t hash(self):
return self.data.hash()
cdef class ObjectID(UniqueID):
cdef class ObjectID(BaseID):
cdef CObjectID data
def __init__(self, id):
check_id(id)
@@ -111,16 +140,67 @@ cdef class ObjectID(UniqueID):
cdef CObjectID native(self):
return <CObjectID>self.data
def size(self):
return CObjectID.size()
cdef class TaskID(UniqueID):
def binary(self):
return self.data.binary()
def hex(self):
return decode(self.data.hex())
def is_nil(self):
return self.data.is_nil()
cdef size_t hash(self):
return self.data.hash()
@classmethod
def nil(cls):
return cls(CObjectID.nil().binary())
@classmethod
def from_random(cls):
return cls(os.urandom(CObjectID.size()))
cdef class TaskID(BaseID):
cdef CTaskID data
def __init__(self, id):
check_id(id)
check_id(id, CTaskID.size())
self.data = CTaskID.from_binary(<c_string>id)
cdef CTaskID native(self):
return <CTaskID>self.data
def size(self):
return CTaskID.size()
def binary(self):
return self.data.binary()
def hex(self):
return decode(self.data.hex())
def is_nil(self):
return self.data.is_nil()
cdef size_t hash(self):
return self.data.hash()
@classmethod
def nil(cls):
return cls(CTaskID.nil().binary())
@classmethod
def size(cla):
return CTaskID.size()
@classmethod
def from_random(cls):
return cls(os.urandom(CTaskID.size()))
cdef class ClientID(UniqueID):
+8 -4
View File
@@ -16,8 +16,8 @@ import ray.cloudpickle as pickle
import ray.gcs_utils
import ray.utils
import ray.ray_constants as ray_constants
from ray.utils import (binary_to_hex, binary_to_object_id, hex_to_binary,
setup_logger)
from ray.utils import (binary_to_hex, binary_to_object_id, binary_to_task_id,
hex_to_binary, setup_logger)
logger = logging.getLogger(__name__)
@@ -169,8 +169,12 @@ class Monitor(object):
driver_object_id_bins.add(object_id.binary())
def to_shard_index(id_bin):
return binary_to_object_id(id_bin).redis_shard_hash() % len(
self.state.redis_clients)
if len(id_bin) == ray.TaskID.size():
return binary_to_task_id(id_bin).redis_shard_hash() % len(
self.state.redis_clients)
else:
return binary_to_object_id(id_bin).redis_shard_hash() % len(
self.state.redis_clients)
# Form the redis keys to delete.
sharded_keys = [[] for _ in range(len(self.state.redis_clients))]
+24 -3
View File
@@ -7,6 +7,7 @@ import collections
from concurrent.futures import ThreadPoolExecutor
import json
import logging
from multiprocessing import Process
import os
import random
import re
@@ -28,7 +29,6 @@ import pytest
import ray
import ray.tests.cluster_utils
import ray.tests.utils
from ray.utils import _random_string
logger = logging.getLogger(__name__)
@@ -2630,12 +2630,33 @@ def test_object_id_properties():
ray.ObjectID(id_bytes + b"1234")
with pytest.raises(ValueError, match=r".*needs to have length 20.*"):
ray.ObjectID(b"0123456789")
object_id = ray.ObjectID(_random_string())
object_id = ray.ObjectID.from_random()
assert not object_id.is_nil()
assert object_id.binary() != id_bytes
id_dumps = pickle.dumps(object_id)
id_from_dumps = pickle.loads(id_dumps)
assert id_from_dumps == object_id
file_prefix = "test_object_id_properties"
# Make sure the ids are fork safe.
def write(index):
str = ray.ObjectID.from_random().hex()
with open("{}{}".format(file_prefix, index), "w") as fo:
fo.write(str)
def read(index):
with open("{}{}".format(file_prefix, index), "r") as fi:
for line in fi:
return line
processes = [Process(target=write, args=(_, )) for _ in range(4)]
for process in processes:
process.start()
for process in processes:
process.join()
hexes = {read(i) for i in range(4)}
[os.remove("{}{}".format(file_prefix, i)) for i in range(4)]
assert len(hexes) == 4
@pytest.fixture
@@ -2768,7 +2789,7 @@ def test_pandas_parquet_serialization():
def test_socket_dir_not_existing(shutdown_only):
random_name = ray.ObjectID(_random_string()).hex()
random_name = ray.ObjectID.from_random().hex()
temp_raylet_socket_dir = "/tmp/ray/tests/{}".format(random_name)
temp_raylet_socket_name = os.path.join(temp_raylet_socket_dir,
"raylet_socket")
+1 -2
View File
@@ -15,7 +15,6 @@ import redis
import ray
import ray.ray_constants as ray_constants
from ray.utils import _random_string
from ray.tests.cluster_utils import Cluster
from ray.tests.utils import (
relevant_errors,
@@ -667,7 +666,7 @@ def test_warning_for_dead_node(ray_start_cluster_2_nodes):
def test_raylet_crash_when_get(ray_start_regular):
nonexistent_id = ray.ObjectID(_random_string())
nonexistent_id = ray.ObjectID.from_random()
def sleep_to_kill_raylet():
# Don't kill raylet before default workers get connected.
+4
View File
@@ -216,6 +216,10 @@ def binary_to_object_id(binary_object_id):
return ray.ObjectID(binary_object_id)
def binary_to_task_id(binary_task_id):
return ray.TaskID(binary_task_id)
def binary_to_hex(identifier):
hex_identifier = binascii.hexlify(identifier)
if sys.version_info >= (3, 0):
+5 -4
View File
@@ -198,7 +198,7 @@ class Worker(object):
# to the current task ID may not be correct. Generate a
# random task ID so that the backend can differentiate
# between different threads.
self._task_context.current_task_id = TaskID(_random_string())
self._task_context.current_task_id = TaskID.from_random()
if getattr(self, "_multithreading_warned", False) is not True:
logger.warning(
"Calling ray.get or ray.wait in a separate thread "
@@ -1725,7 +1725,7 @@ def connect(node,
else:
# This is the code path of driver mode.
if driver_id is None:
driver_id = DriverID(_random_string())
driver_id = DriverID.from_random()
if not isinstance(driver_id, DriverID):
raise TypeError("The type of given driver id must be DriverID.")
@@ -1834,6 +1834,7 @@ def connect(node,
# Create an object store client.
worker.plasma_client = thread_safe_client(
plasma.connect(node.plasma_store_socket_name, None, 0, 300))
driver_id_str = _random_string()
# If this is a driver, set the current task ID, the task driver ID, and set
# the task index to 0.
@@ -1865,7 +1866,7 @@ def connect(node,
function_descriptor.get_function_descriptor_list(),
[], # arguments.
0, # num_returns.
TaskID(_random_string()), # parent_task_id.
TaskID(driver_id_str[:TaskID.size()]), # parent_task_id.
0, # parent_counter.
ActorID.nil(), # actor_creation_id.
ObjectID.nil(), # actor_creation_dummy_object_id.
@@ -1894,7 +1895,7 @@ def connect(node,
node.raylet_socket_name,
ClientID(worker.worker_id),
(mode == WORKER_MODE),
DriverID(worker.current_task_id.binary()),
DriverID(driver_id_str),
)
# Start the import thread
+4 -1
View File
@@ -4,7 +4,7 @@
#include <limits.h>
#include <stdint.h>
/// Length of Ray IDs in bytes.
/// Length of Ray full-length IDs in bytes.
constexpr int64_t kUniqueIDSize = 20;
/// An ObjectID's bytes are split into the task ID itself and the index of the
@@ -13,6 +13,9 @@ constexpr int kObjectIdIndexSize = 32;
static_assert(kObjectIdIndexSize % CHAR_BIT == 0,
"ObjectID prefix not a multiple of bytes");
/// Length of Ray TaskID in bytes. 32-bit integer is used for object index.
constexpr int64_t kTaskIDSize = kUniqueIDSize - kObjectIdIndexSize / 8;
/// The maximum number of objects that can be returned by a task when finishing
/// execution. An ObjectID's bytes are split into the task ID itself and the
/// index of the object's creation. A positive index indicates an object
+18 -18
View File
@@ -89,7 +89,7 @@ void TestTableLookup(const DriverID &driver_id,
data->task_specification = "123";
// Check that we added the correct task.
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const UniqueID &id,
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const TaskID &id,
const protocol::TaskT &d) {
ASSERT_EQ(id, task_id);
ASSERT_EQ(data->task_specification, d.task_specification);
@@ -104,7 +104,7 @@ void TestTableLookup(const DriverID &driver_id,
};
// Check that the lookup does not return an empty entry.
auto failure_callback = [](gcs::AsyncGcsClient *client, const UniqueID &id) {
auto failure_callback = [](gcs::AsyncGcsClient *client, const TaskID &id) {
RAY_CHECK(false);
};
@@ -139,7 +139,7 @@ void TestLogLookup(const DriverID &driver_id,
auto data = std::make_shared<TaskReconstructionDataT>();
data->node_manager_id = node_manager_id;
// Check that we added the correct object entries.
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const UniqueID &id,
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const TaskID &id,
const TaskReconstructionDataT &d) {
ASSERT_EQ(id, task_id);
ASSERT_EQ(data->node_manager_id, d.node_manager_id);
@@ -150,7 +150,7 @@ void TestLogLookup(const DriverID &driver_id,
// Check that lookup returns the added object entries.
auto lookup_callback = [task_id, node_manager_ids](
gcs::AsyncGcsClient *client, const UniqueID &id,
gcs::AsyncGcsClient *client, const TaskID &id,
const std::vector<TaskReconstructionDataT> &data) {
ASSERT_EQ(id, task_id);
for (const auto &entry : data) {
@@ -181,11 +181,11 @@ void TestTableLookupFailure(const DriverID &driver_id,
TaskID task_id = TaskID::from_random();
// Check that the lookup does not return data.
auto lookup_callback = [](gcs::AsyncGcsClient *client, const UniqueID &id,
auto lookup_callback = [](gcs::AsyncGcsClient *client, const TaskID &id,
const protocol::TaskT &d) { RAY_CHECK(false); };
// Check that the lookup returns an empty entry.
auto failure_callback = [task_id](gcs::AsyncGcsClient *client, const UniqueID &id) {
auto failure_callback = [task_id](gcs::AsyncGcsClient *client, const TaskID &id) {
ASSERT_EQ(id, task_id);
test->Stop();
};
@@ -215,7 +215,7 @@ void TestLogAppendAt(const DriverID &driver_id,
}
// Check that we added the correct task.
auto failure_callback = [task_id](gcs::AsyncGcsClient *client, const UniqueID &id,
auto failure_callback = [task_id](gcs::AsyncGcsClient *client, const TaskID &id,
const TaskReconstructionDataT &d) {
ASSERT_EQ(id, task_id);
test->IncrementNumCallbacks();
@@ -241,7 +241,7 @@ void TestLogAppendAt(const DriverID &driver_id,
/*done callback=*/nullptr, failure_callback, /*log_length=*/1));
auto lookup_callback = [node_manager_ids](
gcs::AsyncGcsClient *client, const UniqueID &id,
gcs::AsyncGcsClient *client, const TaskID &id,
const std::vector<TaskReconstructionDataT> &data) {
std::vector<std::string> appended_managers;
for (const auto &entry : data) {
@@ -271,7 +271,7 @@ void TestSet(const DriverID &driver_id, std::shared_ptr<gcs::AsyncGcsClient> cli
auto data = std::make_shared<ObjectTableDataT>();
data->manager = manager;
// Check that we added the correct object entries.
auto add_callback = [object_id, data](gcs::AsyncGcsClient *client, const UniqueID &id,
auto add_callback = [object_id, data](gcs::AsyncGcsClient *client, const ObjectID &id,
const ObjectTableDataT &d) {
ASSERT_EQ(id, object_id);
ASSERT_EQ(data->manager, d.manager);
@@ -297,7 +297,7 @@ void TestSet(const DriverID &driver_id, std::shared_ptr<gcs::AsyncGcsClient> cli
data->manager = manager;
// Check that we added the correct object entries.
auto remove_entry_callback = [object_id, data](
gcs::AsyncGcsClient *client, const UniqueID &id, const ObjectTableDataT &d) {
gcs::AsyncGcsClient *client, const ObjectID &id, const ObjectTableDataT &d) {
ASSERT_EQ(id, object_id);
ASSERT_EQ(data->manager, d.manager);
test->IncrementNumCallbacks();
@@ -338,7 +338,7 @@ void TestDeleteKeysFromLog(
task_id = TaskID::from_random();
ids.push_back(task_id);
// Check that we added the correct object entries.
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const UniqueID &id,
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const TaskID &id,
const TaskReconstructionDataT &d) {
ASSERT_EQ(id, task_id);
ASSERT_EQ(data->node_manager_id, d.node_manager_id);
@@ -350,7 +350,7 @@ void TestDeleteKeysFromLog(
for (const auto &task_id : ids) {
// Check that lookup returns the added object entries.
auto lookup_callback = [task_id, data_vector](
gcs::AsyncGcsClient *client, const UniqueID &id,
gcs::AsyncGcsClient *client, const TaskID &id,
const std::vector<TaskReconstructionDataT> &data) {
ASSERT_EQ(id, task_id);
ASSERT_EQ(data.size(), 1);
@@ -386,7 +386,7 @@ void TestDeleteKeysFromTable(const DriverID &driver_id,
task_id = TaskID::from_random();
ids.push_back(task_id);
// Check that we added the correct object entries.
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const UniqueID &id,
auto add_callback = [task_id, data](gcs::AsyncGcsClient *client, const TaskID &id,
const protocol::TaskT &d) {
ASSERT_EQ(id, task_id);
ASSERT_EQ(data->task_specification, d.task_specification);
@@ -434,7 +434,7 @@ void TestDeleteKeysFromSet(const DriverID &driver_id,
object_id = ObjectID::from_random();
ids.push_back(object_id);
// Check that we added the correct object entries.
auto add_callback = [object_id, data](gcs::AsyncGcsClient *client, const UniqueID &id,
auto add_callback = [object_id, data](gcs::AsyncGcsClient *client, const ObjectID &id,
const ObjectTableDataT &d) {
ASSERT_EQ(id, object_id);
ASSERT_EQ(data->manager, d.manager);
@@ -607,7 +607,7 @@ void TestLogSubscribeAll(const DriverID &driver_id,
}
// Callback for a notification.
auto notification_callback = [driver_ids](gcs::AsyncGcsClient *client,
const UniqueID &id,
const DriverID &id,
const std::vector<DriverTableDataT> data) {
ASSERT_EQ(id, driver_ids[test->NumCallbacks()]);
// Check that we get notifications in the same order as the writes.
@@ -657,7 +657,7 @@ void TestSetSubscribeAll(const DriverID &driver_id,
// Callback for a notification.
auto notification_callback = [object_ids, managers](
gcs::AsyncGcsClient *client, const UniqueID &id,
gcs::AsyncGcsClient *client, const ObjectID &id,
const GcsTableNotificationMode notification_mode,
const std::vector<ObjectTableDataT> data) {
if (test->NumCallbacks() < 3 * 3) {
@@ -752,7 +752,7 @@ void TestTableSubscribeId(const DriverID &driver_id,
// The failure callback should be called once since both keys start as empty.
bool failure_notification_received = false;
auto failure_callback = [task_id2, &failure_notification_received](
gcs::AsyncGcsClient *client, const UniqueID &id) {
gcs::AsyncGcsClient *client, const TaskID &id) {
ASSERT_EQ(id, task_id2);
// The failure notification should be the first notification received.
ASSERT_EQ(test->NumCallbacks(), 0);
@@ -962,7 +962,7 @@ void TestTableSubscribeCancel(const DriverID &driver_id,
// The failure callback should not be called since all keys are non-empty
// when notifications are requested.
auto failure_callback = [](gcs::AsyncGcsClient *client, const UniqueID &id) {
auto failure_callback = [](gcs::AsyncGcsClient *client, const TaskID &id) {
RAY_CHECK(false);
};
-39
View File
@@ -226,45 +226,6 @@ Status RedisContext::AttachToEventLoop(aeEventLoop *loop) {
}
}
Status RedisContext::RunAsync(const std::string &command, const UniqueID &id,
const uint8_t *data, int64_t length,
const TablePrefix prefix, const TablePubsub pubsub_channel,
RedisCallback redisCallback, int log_length) {
int64_t callback_index = RedisCallbackManager::instance().add(redisCallback, false);
if (length > 0) {
if (log_length >= 0) {
std::string redis_command = command + " %d %d %b %b %d";
int status = redisAsyncCommand(
async_context_, reinterpret_cast<redisCallbackFn *>(&GlobalRedisCallback),
reinterpret_cast<void *>(callback_index), redis_command.c_str(), prefix,
pubsub_channel, id.data(), id.size(), data, length, log_length);
if (status == REDIS_ERR) {
return Status::RedisError(std::string(async_context_->errstr));
}
} else {
std::string redis_command = command + " %d %d %b %b";
int status = redisAsyncCommand(
async_context_, reinterpret_cast<redisCallbackFn *>(&GlobalRedisCallback),
reinterpret_cast<void *>(callback_index), redis_command.c_str(), prefix,
pubsub_channel, id.data(), id.size(), data, length);
if (status == REDIS_ERR) {
return Status::RedisError(std::string(async_context_->errstr));
}
}
} else {
RAY_CHECK(log_length == -1);
std::string redis_command = command + " %d %d %b";
int status = redisAsyncCommand(
async_context_, reinterpret_cast<redisCallbackFn *>(&GlobalRedisCallback),
reinterpret_cast<void *>(callback_index), redis_command.c_str(), prefix,
pubsub_channel, id.data(), id.size());
if (status == REDIS_ERR) {
return Status::RedisError(std::string(async_context_->errstr));
}
}
return Status::OK();
}
Status RedisContext::RunArgvAsync(const std::vector<std::string> &args) {
// Build the arguments.
std::vector<const char *> argv;
+50 -1
View File
@@ -11,6 +11,12 @@
#include "ray/gcs/format/gcs_generated.h"
extern "C" {
#include "ray/thirdparty/hiredis/adapters/ae.h"
#include "ray/thirdparty/hiredis/async.h"
#include "ray/thirdparty/hiredis/hiredis.h"
}
struct redisContext;
struct redisAsyncContext;
struct aeEventLoop;
@@ -22,6 +28,8 @@ namespace gcs {
/// operation.
using RedisCallback = std::function<void(const std::string &)>;
void GlobalRedisCallback(void *c, void *r, void *privdata);
class RedisCallbackManager {
public:
static RedisCallbackManager &instance() {
@@ -83,7 +91,8 @@ class RedisContext {
/// at which the data must be appended. For all other commands, set to
/// -1 for unused. If set, then data must be provided.
/// \return Status.
Status RunAsync(const std::string &command, const UniqueID &id, const uint8_t *data,
template <typename ID>
Status RunAsync(const std::string &command, const ID &id, const uint8_t *data,
int64_t length, const TablePrefix prefix,
const TablePubsub pubsub_channel, RedisCallback redisCallback,
int log_length = -1);
@@ -113,6 +122,46 @@ class RedisContext {
redisAsyncContext *subscribe_context_;
};
template <typename ID>
Status RedisContext::RunAsync(const std::string &command, const ID &id,
const uint8_t *data, int64_t length,
const TablePrefix prefix, const TablePubsub pubsub_channel,
RedisCallback redisCallback, int log_length) {
int64_t callback_index = RedisCallbackManager::instance().add(redisCallback, false);
if (length > 0) {
if (log_length >= 0) {
std::string redis_command = command + " %d %d %b %b %d";
int status = redisAsyncCommand(
async_context_, reinterpret_cast<redisCallbackFn *>(&GlobalRedisCallback),
reinterpret_cast<void *>(callback_index), redis_command.c_str(), prefix,
pubsub_channel, id.data(), id.size(), data, length, log_length);
if (status == REDIS_ERR) {
return Status::RedisError(std::string(async_context_->errstr));
}
} else {
std::string redis_command = command + " %d %d %b %b";
int status = redisAsyncCommand(
async_context_, reinterpret_cast<redisCallbackFn *>(&GlobalRedisCallback),
reinterpret_cast<void *>(callback_index), redis_command.c_str(), prefix,
pubsub_channel, id.data(), id.size(), data, length);
if (status == REDIS_ERR) {
return Status::RedisError(std::string(async_context_->errstr));
}
}
} else {
RAY_CHECK(log_length == -1);
std::string redis_command = command + " %d %d %b";
int status = redisAsyncCommand(
async_context_, reinterpret_cast<redisCallbackFn *>(&GlobalRedisCallback),
reinterpret_cast<void *>(callback_index), redis_command.c_str(), prefix,
pubsub_channel, id.data(), id.size());
if (status == REDIS_ERR) {
return Status::RedisError(std::string(async_context_->errstr));
}
}
return Status::OK();
}
} // namespace gcs
} // namespace ray
+7 -5
View File
@@ -676,13 +676,15 @@ int TableDelete_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int
size_t len = 0;
const char *data_ptr = nullptr;
data_ptr = RedisModule_StringPtrLen(data, &len);
REPLY_AND_RETURN_IF_FALSE(
len % kUniqueIDSize == 0,
"The deletion data length must be a multiple of the UniqueID size.");
size_t ids_to_delete = len / kUniqueIDSize;
// The first uint16_t are used to encode the number of ids to delete.
size_t ids_to_delete = *reinterpret_cast<const uint16_t *>(data_ptr);
size_t id_length = (len - sizeof(uint16_t)) / ids_to_delete;
REPLY_AND_RETURN_IF_FALSE((len - sizeof(uint16_t)) % ids_to_delete == 0,
"The deletion data length must be multiple of the ID size");
data_ptr += sizeof(uint16_t);
for (size_t i = 0; i < ids_to_delete; ++i) {
RedisModuleString *id_data =
RedisModule_CreateString(ctx, data_ptr + i * kUniqueIDSize, kUniqueIDSize);
RedisModule_CreateString(ctx, data_ptr + i * id_length, id_length);
RAY_IGNORE_EXPR(DeleteKeyHelper(ctx, prefix_str, id_data));
}
return RedisModule_ReplyWithSimpleString(ctx, "OK");
+16 -6
View File
@@ -192,15 +192,25 @@ void Log<ID, Data>::Delete(const DriverID &driver_id, const std::vector<ID> &ids
}
// Breaking really large deletion commands into batches of smaller size.
const size_t batch_size =
RayConfig::instance().maximum_gcs_deletion_batch_size() * kUniqueIDSize;
RayConfig::instance().maximum_gcs_deletion_batch_size() * ID::size();
for (const auto &pair : sharded_data) {
std::string current_data = pair.second.str();
for (size_t cur = 0; cur < pair.second.str().size(); cur += batch_size) {
RAY_IGNORE_EXPR(pair.first->RunAsync(
"RAY.TABLE_DELETE", UniqueID::nil(),
reinterpret_cast<const uint8_t *>(current_data.c_str() + cur),
std::min(batch_size, current_data.size() - cur), prefix_, pubsub_channel_,
/*redisCallback=*/nullptr));
size_t data_field_size = std::min(batch_size, current_data.size() - cur);
uint16_t id_count = data_field_size / ID::size();
// Send data contains id count and all the id data.
std::string send_data(data_field_size + sizeof(id_count), 0);
uint8_t *buffer = reinterpret_cast<uint8_t *>(&send_data[0]);
*reinterpret_cast<uint16_t *>(buffer) = id_count;
RAY_IGNORE_EXPR(
std::copy_n(reinterpret_cast<const uint8_t *>(current_data.c_str() + cur),
data_field_size, buffer + sizeof(uint16_t)));
RAY_IGNORE_EXPR(
pair.first->RunAsync("RAY.TABLE_DELETE", UniqueID::nil(),
reinterpret_cast<const uint8_t *>(send_data.c_str()),
send_data.size(), prefix_, pubsub_channel_,
/*redisCallback=*/nullptr));
}
}
}
+1 -1
View File
@@ -206,7 +206,7 @@ class Log : public LogInterface<ID, Data>, virtual public PubsubInterface<ID> {
protected:
std::shared_ptr<RedisContext> GetRedisContext(const ID &id) {
static std::hash<ray::UniqueID> index;
static std::hash<ID> index;
return shard_contexts_[index(id) % shard_contexts_.size()];
}
+38 -127
View File
@@ -26,82 +26,16 @@ std::mt19937 RandomlySeededMersenneTwister() {
uint64_t MurmurHash64A(const void *key, int len, unsigned int seed);
UniqueID::UniqueID() {
// Set the ID to nil.
std::fill_n(id_, kUniqueIDSize, 255);
}
UniqueID::UniqueID(const std::string &binary) {
std::memcpy(&id_, binary.data(), kUniqueIDSize);
}
UniqueID::UniqueID(const plasma::UniqueID &from) {
std::memcpy(&id_, from.data(), kUniqueIDSize);
}
UniqueID UniqueID::from_random() {
std::string data(kUniqueIDSize, 0);
// NOTE(pcm): The right way to do this is to have one std::mt19937 per
// thread (using the thread_local keyword), but that's not supported on
// older versions of macOS (see https://stackoverflow.com/a/29929949)
static std::mutex random_engine_mutex;
std::lock_guard<std::mutex> lock(random_engine_mutex);
static std::mt19937 generator = RandomlySeededMersenneTwister();
std::uniform_int_distribution<uint32_t> dist(0, std::numeric_limits<uint8_t>::max());
for (int i = 0; i < kUniqueIDSize; i++) {
data[i] = static_cast<uint8_t>(dist(generator));
}
return UniqueID::from_binary(data);
}
UniqueID UniqueID::from_binary(const std::string &binary) { return UniqueID(binary); }
const UniqueID &UniqueID::nil() {
static const UniqueID nil_id;
return nil_id;
}
bool UniqueID::is_nil() const {
const uint8_t *d = data();
for (int i = 0; i < kUniqueIDSize; ++i) {
if (d[i] != 255) {
return false;
}
}
return true;
}
const uint8_t *UniqueID::data() const { return id_; }
size_t UniqueID::size() { return kUniqueIDSize; }
std::string UniqueID::binary() const {
return std::string(reinterpret_cast<const char *>(id_), kUniqueIDSize);
}
std::string UniqueID::hex() const {
constexpr char hex[] = "0123456789abcdef";
std::string result;
for (int i = 0; i < kUniqueIDSize; i++) {
unsigned int val = id_[i];
result.push_back(hex[val >> 4]);
result.push_back(hex[val & 0xf]);
}
return result;
}
plasma::UniqueID UniqueID::to_plasma_id() const {
plasma::UniqueID ObjectID::to_plasma_id() const {
plasma::UniqueID result;
std::memcpy(result.mutable_data(), &id_, kUniqueIDSize);
std::memcpy(result.mutable_data(), data(), kUniqueIDSize);
return result;
}
bool UniqueID::operator==(const UniqueID &rhs) const {
return std::memcmp(data(), rhs.data(), kUniqueIDSize) == 0;
ObjectID::ObjectID(const plasma::UniqueID &from) {
std::memcpy(this->mutable_data(), from.data(), kUniqueIDSize);
}
bool UniqueID::operator!=(const UniqueID &rhs) const { return !(*this == rhs); }
// This code is from https://sites.google.com/site/murmurhash/
// and is public domain.
uint64_t MurmurHash64A(const void *key, int len, unsigned int seed) {
@@ -151,60 +85,32 @@ uint64_t MurmurHash64A(const void *key, int len, unsigned int seed) {
return h;
}
size_t UniqueID::hash() const {
// Note(ashione): hash code lazy calculation(it's invoked every time if hash code is
// default value 0)
if (!hash_) {
hash_ = MurmurHash64A(&id_[0], kUniqueIDSize, 0);
}
return hash_;
TaskID TaskID::GetDriverTaskID(const DriverID &driver_id) {
std::string driver_id_str = driver_id.binary();
driver_id_str.resize(size());
return TaskID::from_binary(driver_id_str);
}
std::ostream &operator<<(std::ostream &os, const UniqueID &id) {
if (id.is_nil()) {
os << "NIL_ID";
} else {
os << id.hex();
}
return os;
TaskID ObjectID::task_id() const {
return TaskID::from_binary(
std::string(reinterpret_cast<const char *>(id_), TaskID::size()));
}
const ObjectID ComputeObjectId(const TaskID &task_id, int64_t object_index) {
RAY_CHECK(object_index <= kMaxTaskReturns && object_index >= -kMaxTaskPuts);
ObjectID return_id = ObjectID(task_id);
int64_t *first_bytes = reinterpret_cast<int64_t *>(&return_id);
// Zero out the lowest kObjectIdIndexSize bits of the first byte of the
// object ID.
uint64_t bitmask = static_cast<uint64_t>(-1) << kObjectIdIndexSize;
*first_bytes = *first_bytes & (bitmask);
// OR the first byte of the object ID with the return index.
*first_bytes = *first_bytes | (object_index & ~bitmask);
return return_id;
ObjectID ObjectID::for_put(const TaskID &task_id, int64_t put_index) {
RAY_CHECK(put_index >= 1 && put_index <= kMaxTaskPuts) << "index=" << put_index;
ObjectID object_id;
std::memcpy(object_id.id_, task_id.binary().c_str(), task_id.size());
object_id.index_ = -put_index;
return object_id;
}
const TaskID FinishTaskId(const TaskID &task_id) {
return TaskID(ComputeObjectId(task_id, 0));
}
const ObjectID ComputeReturnId(const TaskID &task_id, int64_t return_index) {
RAY_CHECK(return_index >= 1 && return_index <= kMaxTaskReturns);
return ComputeObjectId(task_id, return_index);
}
const ObjectID ComputePutId(const TaskID &task_id, int64_t put_index) {
RAY_CHECK(put_index >= 1 && put_index <= kMaxTaskPuts);
// We multiply put_index by -1 to distinguish from return_index.
return ComputeObjectId(task_id, -1 * put_index);
}
const TaskID ComputeTaskId(const ObjectID &object_id) {
TaskID task_id = TaskID(object_id);
int64_t *first_bytes = reinterpret_cast<int64_t *>(&task_id);
// Zero out the lowest kObjectIdIndexSize bits of the first byte of the
// object ID.
uint64_t bitmask = static_cast<uint64_t>(-1) << kObjectIdIndexSize;
*first_bytes = *first_bytes & (bitmask);
return task_id;
ObjectID ObjectID::for_task_return(const TaskID &task_id, int64_t return_index) {
RAY_CHECK(return_index >= 1 && return_index <= kMaxTaskReturns) << "index="
<< return_index;
ObjectID object_id;
std::memcpy(object_id.id_, task_id.binary().c_str(), task_id.size());
object_id.index_ = return_index;
return object_id;
}
const TaskID GenerateTaskId(const DriverID &driver_id, const TaskID &parent_task_id,
@@ -220,16 +126,21 @@ const TaskID GenerateTaskId(const DriverID &driver_id, const TaskID &parent_task
// Compute the final task ID from the hash.
BYTE buff[DIGEST_SIZE];
sha256_final(&ctx, buff);
return FinishTaskId(TaskID::from_binary(std::string(buff, buff + kUniqueIDSize)));
return TaskID::from_binary(std::string(buff, buff + TaskID::size()));
}
int64_t ComputeObjectIndex(const ObjectID &object_id) {
const int64_t *first_bytes = reinterpret_cast<const int64_t *>(&object_id);
uint64_t bitmask = static_cast<uint64_t>(-1) << kObjectIdIndexSize;
int64_t index = *first_bytes & (~bitmask);
index <<= (8 * sizeof(int64_t) - kObjectIdIndexSize);
index >>= (8 * sizeof(int64_t) - kObjectIdIndexSize);
return index;
}
#define ID_OSTREAM_OPERATOR(id_type) \
std::ostream &operator<<(std::ostream &os, const id_type &id) { \
if (id.is_nil()) { \
os << "NIL_ID"; \
} else { \
os << id.hex(); \
} \
return os; \
}
ID_OSTREAM_OPERATOR(UniqueID);
ID_OSTREAM_OPERATOR(TaskID);
ID_OSTREAM_OPERATOR(ObjectID);
} // namespace ray
+190 -49
View File
@@ -2,44 +2,128 @@
#define RAY_ID_H_
#include <inttypes.h>
#include <limits.h>
#include <chrono>
#include <cstring>
#include <mutex>
#include <random>
#include <string>
#include "plasma/common.h"
#include "ray/constants.h"
#include "ray/util/logging.h"
#include "ray/util/visibility.h"
namespace ray {
class RAY_EXPORT UniqueID {
class DriverID;
class UniqueID;
// Declaration.
std::mt19937 RandomlySeededMersenneTwister();
uint64_t MurmurHash64A(const void *key, int len, unsigned int seed);
// Change the compiler alignment to 1 byte (default is 8).
#pragma pack(push, 1)
template <typename T>
class BaseID {
public:
UniqueID();
UniqueID(const plasma::UniqueID &from);
static UniqueID from_random();
static UniqueID from_binary(const std::string &binary);
static const UniqueID &nil();
BaseID();
static T from_random();
static T from_binary(const std::string &binary);
static const T &nil();
static size_t size() { return T::size(); }
size_t hash() const;
bool is_nil() const;
bool operator==(const UniqueID &rhs) const;
bool operator!=(const UniqueID &rhs) const;
bool operator==(const BaseID &rhs) const;
bool operator!=(const BaseID &rhs) const;
const uint8_t *data() const;
static size_t size();
std::string binary() const;
std::string hex() const;
plasma::UniqueID to_plasma_id() const;
private:
protected:
BaseID(const std::string &binary) {
std::memcpy(const_cast<uint8_t *>(this->data()), binary.data(), T::size());
}
// All IDs are immutable for hash evaluations. mutable_data is only allow to use
// in construction time, so this function is protected.
uint8_t *mutable_data();
// For lazy evaluation, be careful to have one Id contained in another.
// This hash code will be duplicated.
mutable size_t hash_ = 0;
};
class UniqueID : public BaseID<UniqueID> {
public:
UniqueID() : BaseID(){};
static size_t size() { return kUniqueIDSize; }
protected:
UniqueID(const std::string &binary);
protected:
uint8_t id_[kUniqueIDSize];
mutable size_t hash_ = 0;
};
static_assert(std::is_standard_layout<UniqueID>::value, "UniqueID must be standard");
class TaskID : public BaseID<TaskID> {
public:
TaskID() : BaseID() {}
static size_t size() { return kTaskIDSize; }
static TaskID GetDriverTaskID(const DriverID &driver_id);
private:
uint8_t id_[kTaskIDSize];
};
class ObjectID : public BaseID<ObjectID> {
public:
ObjectID() : BaseID() {}
static size_t size() { return kUniqueIDSize; }
plasma::ObjectID to_plasma_id() const;
ObjectID(const plasma::UniqueID &from);
/// Get the index of this object in the task that created it.
///
/// \return The index of object creation according to the task that created
/// this object. This is positive if the task returned the object and negative
/// if created by a put.
int32_t object_index() const { return index_; }
/// Compute the task ID of the task that created the object.
///
/// \return The task ID of the task that created this object.
TaskID task_id() const;
/// Compute the object ID of an object put by the task.
///
/// \param task_id The task ID of the task that created the object.
/// \param index What index of the object put in the task.
/// \return The computed object ID.
static ObjectID for_put(const TaskID &task_id, int64_t put_index);
/// Compute the object ID of an object returned by the task.
///
/// \param task_id The task ID of the task that created the object.
/// \param return_index What index of the object returned by in the task.
/// \return The computed object ID.
static ObjectID for_task_return(const TaskID &task_id, int64_t return_index);
private:
uint8_t id_[kTaskIDSize];
int32_t index_;
};
static_assert(sizeof(TaskID) == kTaskIDSize + sizeof(size_t),
"TaskID size is not as expected");
static_assert(sizeof(ObjectID) == sizeof(int32_t) + sizeof(TaskID),
"ObjectID size is not as expected");
std::ostream &operator<<(std::ostream &os, const UniqueID &id);
std::ostream &operator<<(std::ostream &os, const TaskID &id);
std::ostream &operator<<(std::ostream &os, const ObjectID &id);
#define DEFINE_UNIQUE_ID(type) \
class RAY_EXPORT type : public UniqueID { \
@@ -63,35 +147,8 @@ std::ostream &operator<<(std::ostream &os, const UniqueID &id);
#undef DEFINE_UNIQUE_ID
// TODO(swang): ObjectID and TaskID should derive from UniqueID. Then, we
// can make these methods of the derived classes.
/// Finish computing a task ID. Since objects created by the task share a
/// prefix of the ID, the suffix of the task ID is zeroed out by this function.
///
/// \param task_id A task ID to finish.
/// \return The finished task ID. It may now be used to compute IDs for objects
/// created by the task.
const TaskID FinishTaskId(const TaskID &task_id);
/// Compute the object ID of an object returned by the task.
///
/// \param task_id The task ID of the task that created the object.
/// \param return_index What number return value this object is in the task.
/// \return The computed object ID.
const ObjectID ComputeReturnId(const TaskID &task_id, int64_t return_index);
/// Compute the object ID of an object put by the task.
///
/// \param task_id The task ID of the task that created the object.
/// \param put_index What number put this object was created by in the task.
/// \return The computed object ID.
const ObjectID ComputePutId(const TaskID &task_id, int64_t put_index);
/// Compute the task ID of the task that created the object.
///
/// \param object_id The object ID.
/// \return The task ID of the task that created this object.
const TaskID ComputeTaskId(const ObjectID &object_id);
// Restore the compiler alignment to defult (8 bytes).
#pragma pack(pop)
/// Generate a task ID from the given info.
///
@@ -102,13 +159,95 @@ const TaskID ComputeTaskId(const ObjectID &object_id);
const TaskID GenerateTaskId(const DriverID &driver_id, const TaskID &parent_task_id,
int parent_task_counter);
/// Compute the index of this object in the task that created it.
///
/// \param object_id The object ID.
/// \return The index of object creation according to the task that created
/// this object. This is positive if the task returned the object and negative
/// if created by a put.
int64_t ComputeObjectIndex(const ObjectID &object_id);
template <typename T>
BaseID<T>::BaseID() {
// Using const_cast to directly change data is dangerous. The cached
// hash may not be changed. This is used in construction time.
std::fill_n(this->mutable_data(), T::size(), 0xff);
}
template <typename T>
T BaseID<T>::from_random() {
std::string data(T::size(), 0);
// NOTE(pcm): The right way to do this is to have one std::mt19937 per
// thread (using the thread_local keyword), but that's not supported on
// older versions of macOS (see https://stackoverflow.com/a/29929949)
static std::mutex random_engine_mutex;
std::lock_guard<std::mutex> lock(random_engine_mutex);
static std::mt19937 generator = RandomlySeededMersenneTwister();
std::uniform_int_distribution<uint32_t> dist(0, std::numeric_limits<uint8_t>::max());
for (int i = 0; i < T::size(); i++) {
data[i] = static_cast<uint8_t>(dist(generator));
}
return T::from_binary(data);
}
template <typename T>
T BaseID<T>::from_binary(const std::string &binary) {
T t = T::nil();
std::memcpy(t.mutable_data(), binary.data(), T::size());
return t;
}
template <typename T>
const T &BaseID<T>::nil() {
static const T nil_id;
return nil_id;
}
template <typename T>
bool BaseID<T>::is_nil() const {
static T nil_id = T::nil();
return *this == nil_id;
}
template <typename T>
size_t BaseID<T>::hash() const {
// Note(ashione): hash code lazy calculation(it's invoked every time if hash code is
// default value 0)
if (!hash_) {
hash_ = MurmurHash64A(data(), T::size(), 0);
}
return hash_;
}
template <typename T>
bool BaseID<T>::operator==(const BaseID &rhs) const {
return std::memcmp(data(), rhs.data(), T::size()) == 0;
}
template <typename T>
bool BaseID<T>::operator!=(const BaseID &rhs) const {
return !(*this == rhs);
}
template <typename T>
uint8_t *BaseID<T>::mutable_data() {
return reinterpret_cast<uint8_t *>(this) + sizeof(hash_);
}
template <typename T>
const uint8_t *BaseID<T>::data() const {
return reinterpret_cast<const uint8_t *>(this) + sizeof(hash_);
}
template <typename T>
std::string BaseID<T>::binary() const {
return std::string(reinterpret_cast<const char *>(data()), T::size());
}
template <typename T>
std::string BaseID<T>::hex() const {
constexpr char hex[] = "0123456789abcdef";
const uint8_t *id = data();
std::string result;
for (int i = 0; i < T::size(); i++) {
unsigned int val = id[i];
result.push_back(hex[val >> 4]);
result.push_back(hex[val & 0xf]);
}
return result;
}
} // namespace ray
@@ -125,6 +264,8 @@ namespace std {
};
DEFINE_UNIQUE_ID(UniqueID);
DEFINE_UNIQUE_ID(TaskID);
DEFINE_UNIQUE_ID(ObjectID);
#include "id_def.h"
#undef DEFINE_UNIQUE_ID
-2
View File
@@ -4,8 +4,6 @@
// Macro definition format: DEFINE_UNIQUE_ID(id_type).
// NOTE: This file should NOT be included in any file other than id.h.
DEFINE_UNIQUE_ID(TaskID)
DEFINE_UNIQUE_ID(ObjectID)
DEFINE_UNIQUE_ID(FunctionID)
DEFINE_UNIQUE_ID(ActorClassID)
DEFINE_UNIQUE_ID(ActorID)
@@ -288,7 +288,7 @@ class TestObjectManager : public TestObjectManagerBase {
// object.
ObjectID object_1 = WriteDataToClient(client2, data_size);
ObjectID object_2 = WriteDataToClient(client2, data_size);
UniqueID sub_id = ray::ObjectID::from_random();
UniqueID sub_id = ray::UniqueID::from_random();
RAY_CHECK_OK(server1->object_manager_.object_directory_->SubscribeObjectLocations(
sub_id, object_1, [this, sub_id, object_1, object_2](
+1 -1
View File
@@ -48,7 +48,7 @@ void LineageEntry::ComputeParentTaskIds() {
parent_task_ids_.clear();
// A task's parents are the tasks that created its arguments.
for (const auto &dependency : task_.GetDependencies()) {
parent_task_ids_.insert(ComputeTaskId(dependency));
parent_task_ids_.insert(dependency.task_id());
}
}
+5 -4
View File
@@ -852,7 +852,7 @@ void NodeManager::ProcessClientMessage(
// Clean up their creating tasks from GCS.
std::vector<TaskID> creating_task_ids;
for (const auto &object_id : object_ids) {
creating_task_ids.push_back(ComputeTaskId(object_id));
creating_task_ids.push_back(object_id.task_id());
}
gcs_client_->raylet_task_table().Delete(DriverID::nil(), creating_task_ids);
}
@@ -887,11 +887,12 @@ void NodeManager::ProcessRegisterClientRequestMessage(
// message is actually the ID of the driver task, while client_id represents the
// real driver ID, which can associate all the tasks/actors for a given driver,
// which is set to the worker ID.
const DriverID driver_task_id = from_flatbuf<DriverID>(*message->driver_id());
worker->AssignTaskId(TaskID(driver_task_id));
const DriverID driver_id = from_flatbuf<DriverID>(*message->driver_id());
TaskID driver_task_id = TaskID::GetDriverTaskID(driver_id);
worker->AssignTaskId(driver_task_id);
worker->AssignDriverId(from_flatbuf<DriverID>(*message->client_id()));
worker_pool_.RegisterDriver(std::move(worker));
local_queues_.AddDriverTaskId(TaskID(driver_task_id));
local_queues_.AddDriverTaskId(driver_task_id);
}
}
+2 -2
View File
@@ -171,7 +171,7 @@ void ReconstructionPolicy::HandleTaskLeaseNotification(const TaskID &task_id,
}
void ReconstructionPolicy::ListenAndMaybeReconstruct(const ObjectID &object_id) {
TaskID task_id = ComputeTaskId(object_id);
TaskID task_id = object_id.task_id();
auto it = listening_tasks_.find(task_id);
// Add this object to the list of objects created by the same task.
if (it == listening_tasks_.end()) {
@@ -185,7 +185,7 @@ void ReconstructionPolicy::ListenAndMaybeReconstruct(const ObjectID &object_id)
}
void ReconstructionPolicy::Cancel(const ObjectID &object_id) {
TaskID task_id = ComputeTaskId(object_id);
TaskID task_id = object_id.task_id();
auto it = listening_tasks_.find(task_id);
if (it == listening_tasks_.end()) {
// We already stopped listening for this task.
+9 -17
View File
@@ -224,8 +224,7 @@ class ReconstructionPolicyTest : public ::testing::Test {
TEST_F(ReconstructionPolicyTest, TestReconstructionSimple) {
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id = ComputeReturnId(task_id, 1);
ObjectID object_id = ObjectID::for_task_return(task_id, 1);
// Listen for an object.
reconstruction_policy_->ListenAndMaybeReconstruct(object_id);
@@ -243,8 +242,7 @@ TEST_F(ReconstructionPolicyTest, TestReconstructionSimple) {
TEST_F(ReconstructionPolicyTest, TestReconstructionEvicted) {
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id = ComputeReturnId(task_id, 1);
ObjectID object_id = ObjectID::for_task_return(task_id, 1);
mock_object_directory_->SetObjectLocations(object_id, {ClientID::from_random()});
// Listen for both objects.
@@ -267,8 +265,7 @@ TEST_F(ReconstructionPolicyTest, TestReconstructionEvicted) {
TEST_F(ReconstructionPolicyTest, TestReconstructionObjectLost) {
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id = ComputeReturnId(task_id, 1);
ObjectID object_id = ObjectID::for_task_return(task_id, 1);
ClientID client_id = ClientID::from_random();
mock_object_directory_->SetObjectLocations(object_id, {client_id});
@@ -292,9 +289,8 @@ TEST_F(ReconstructionPolicyTest, TestReconstructionObjectLost) {
TEST_F(ReconstructionPolicyTest, TestDuplicateReconstruction) {
// Create two object IDs produced by the same task.
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id1 = ComputeReturnId(task_id, 1);
ObjectID object_id2 = ComputeReturnId(task_id, 2);
ObjectID object_id1 = ObjectID::for_task_return(task_id, 1);
ObjectID object_id2 = ObjectID::for_task_return(task_id, 2);
// Listen for both objects.
reconstruction_policy_->ListenAndMaybeReconstruct(object_id1);
@@ -313,8 +309,7 @@ TEST_F(ReconstructionPolicyTest, TestDuplicateReconstruction) {
TEST_F(ReconstructionPolicyTest, TestReconstructionSuppressed) {
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id = ComputeReturnId(task_id, 1);
ObjectID object_id = ObjectID::for_task_return(task_id, 1);
// Run the test for much longer than the reconstruction timeout.
int64_t test_period = 2 * reconstruction_timeout_ms_;
@@ -340,8 +335,7 @@ TEST_F(ReconstructionPolicyTest, TestReconstructionSuppressed) {
TEST_F(ReconstructionPolicyTest, TestReconstructionContinuallySuppressed) {
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id = ComputeReturnId(task_id, 1);
ObjectID object_id = ObjectID::for_task_return(task_id, 1);
// Listen for an object.
reconstruction_policy_->ListenAndMaybeReconstruct(object_id);
@@ -368,8 +362,7 @@ TEST_F(ReconstructionPolicyTest, TestReconstructionContinuallySuppressed) {
TEST_F(ReconstructionPolicyTest, TestReconstructionCanceled) {
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id = ComputeReturnId(task_id, 1);
ObjectID object_id = ObjectID::for_task_return(task_id, 1);
// Listen for an object.
reconstruction_policy_->ListenAndMaybeReconstruct(object_id);
@@ -395,8 +388,7 @@ TEST_F(ReconstructionPolicyTest, TestReconstructionCanceled) {
TEST_F(ReconstructionPolicyTest, TestSimultaneousReconstructionSuppressed) {
TaskID task_id = TaskID::from_random();
task_id = FinishTaskId(task_id);
ObjectID object_id = ComputeReturnId(task_id, 1);
ObjectID object_id = ObjectID::for_task_return(task_id, 1);
// Log a reconstruction attempt to simulate a different node attempting the
// reconstruction first. This should suppress this node's first attempt at
+6 -6
View File
@@ -24,7 +24,7 @@ bool TaskDependencyManager::CheckObjectLocal(const ObjectID &object_id) const {
}
bool TaskDependencyManager::CheckObjectRequired(const ObjectID &object_id) const {
const TaskID task_id = ComputeTaskId(object_id);
const TaskID task_id = object_id.task_id();
auto task_entry = required_tasks_.find(task_id);
// If there are no subscribed tasks that are dependent on the object, then do
// nothing.
@@ -82,7 +82,7 @@ std::vector<TaskID> TaskDependencyManager::HandleObjectLocal(
// Find any tasks that are dependent on the newly available object.
std::vector<TaskID> ready_task_ids;
auto creating_task_entry = required_tasks_.find(ComputeTaskId(object_id));
auto creating_task_entry = required_tasks_.find(object_id.task_id());
if (creating_task_entry != required_tasks_.end()) {
auto object_entry = creating_task_entry->second.find(object_id);
if (object_entry != creating_task_entry->second.end()) {
@@ -113,7 +113,7 @@ std::vector<TaskID> TaskDependencyManager::HandleObjectMissing(
// Find any tasks that are dependent on the missing object.
std::vector<TaskID> waiting_task_ids;
TaskID creating_task_id = ComputeTaskId(object_id);
TaskID creating_task_id = object_id.task_id();
auto creating_task_entry = required_tasks_.find(creating_task_id);
if (creating_task_entry != required_tasks_.end()) {
auto object_entry = creating_task_entry->second.find(object_id);
@@ -149,7 +149,7 @@ bool TaskDependencyManager::SubscribeDependencies(
auto inserted = task_entry.object_dependencies.insert(object_id);
if (inserted.second) {
// Get the ID of the task that creates the dependency.
TaskID creating_task_id = ComputeTaskId(object_id);
TaskID creating_task_id = object_id.task_id();
// Determine whether the dependency can be fulfilled by the local node.
if (local_objects_.count(object_id) == 0) {
// The object is not local.
@@ -186,7 +186,7 @@ bool TaskDependencyManager::UnsubscribeDependencies(const TaskID &task_id) {
// Remove the task from the list of tasks that are dependent on this
// object.
// Get the ID of the task that creates the dependency.
TaskID creating_task_id = ComputeTaskId(object_id);
TaskID creating_task_id = object_id.task_id();
auto creating_task_entry = required_tasks_.find(creating_task_id);
std::vector<TaskID> &dependent_tasks = creating_task_entry->second[object_id];
auto it = std::find(dependent_tasks.begin(), dependent_tasks.end(), task_id);
@@ -324,7 +324,7 @@ void TaskDependencyManager::RemoveTasksAndRelatedObjects(
// Cancel all of the objects that were required by the removed tasks.
for (const auto &object_id : required_objects) {
TaskID creating_task_id = ComputeTaskId(object_id);
TaskID creating_task_id = object_id.task_id();
required_tasks_.erase(creating_task_id);
HandleRemoteDependencyCanceled(object_id);
}
@@ -266,7 +266,7 @@ TEST_F(TaskDependencyManagerTest, TestTaskChain) {
TEST_F(TaskDependencyManagerTest, TestDependentPut) {
// Create a task with 3 arguments.
auto task1 = ExampleTask({}, 0);
ObjectID put_id = ComputePutId(task1.GetTaskSpecification().TaskId(), 1);
ObjectID put_id = ObjectID::for_put(task1.GetTaskSpecification().TaskId(), 1);
auto task2 = ExampleTask({put_id}, 0);
// No objects have been registered in the task dependency manager, so the put
+1 -1
View File
@@ -95,7 +95,7 @@ TaskSpecification::TaskSpecification(
// Generate return ids.
std::vector<ray::ObjectID> returns;
for (int64_t i = 1; i < num_returns + 1; ++i) {
returns.push_back(ComputeReturnId(task_id, i));
returns.push_back(ObjectID::for_task_return(task_id, i));
}
// Serialize the TaskSpecification.
+19 -7
View File
@@ -9,21 +9,21 @@ namespace raylet {
void TestTaskReturnId(const TaskID &task_id, int64_t return_index) {
// Round trip test for computing the object ID for a task's return value,
// then computing the task ID that created the object.
ObjectID return_id = ComputeReturnId(task_id, return_index);
ASSERT_EQ(ComputeTaskId(return_id), task_id);
ASSERT_EQ(ComputeObjectIndex(return_id), return_index);
ObjectID return_id = ObjectID::for_task_return(task_id, return_index);
ASSERT_EQ(return_id.task_id(), task_id);
ASSERT_EQ(return_id.object_index(), return_index);
}
void TestTaskPutId(const TaskID &task_id, int64_t put_index) {
// Round trip test for computing the object ID for a task's put value, then
// computing the task ID that created the object.
ObjectID put_id = ComputePutId(task_id, put_index);
ASSERT_EQ(ComputeTaskId(put_id), task_id);
ASSERT_EQ(ComputeObjectIndex(put_id), -1 * put_index);
ObjectID put_id = ObjectID::for_put(task_id, put_index);
ASSERT_EQ(put_id.task_id(), task_id);
ASSERT_EQ(put_id.object_index(), -1 * put_index);
}
TEST(TaskSpecTest, TestTaskReturnIds) {
TaskID task_id = FinishTaskId(TaskID::from_random());
TaskID task_id = TaskID::from_random();
// Check that we can compute between a task ID and the object IDs of its
// return values and puts.
@@ -35,6 +35,18 @@ TEST(TaskSpecTest, TestTaskReturnIds) {
TestTaskPutId(task_id, kMaxTaskPuts);
}
TEST(IdPropertyTest, TestIdProperty) {
TaskID task_id = TaskID::from_random();
ASSERT_EQ(task_id, TaskID::from_binary(task_id.binary()));
ObjectID object_id = ObjectID::from_random();
ASSERT_EQ(object_id, ObjectID::from_binary(object_id.binary()));
ASSERT_TRUE(TaskID().is_nil());
ASSERT_TRUE(TaskID::nil().is_nil());
ASSERT_TRUE(ObjectID().is_nil());
ASSERT_TRUE(ObjectID::nil().is_nil());
}
} // namespace raylet
} // namespace ray