Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,36 @@ cc_library(
],
)

cc_library(
name = "core_worker_lib",
Comment thread
raulchen marked this conversation as resolved.
srcs = glob(
[
"src/ray/core_worker/*.cc",
],
exclude = [
"src/ray/core_worker/*_test.cc",
],
),
hdrs = glob([
"src/ray/core_worker/*.h",
]),
copts = COPTS,
deps = [
":ray_common",
":ray_util",
],
)

cc_test(
name = "core_worker_test",
srcs = ["src/ray/core_worker/core_worker_test.cc"],
copts = COPTS,
deps = [
":core_worker_lib",
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "lineage_cache_test",
srcs = ["src/ray/raylet/lineage_cache_test.cc"],
Expand Down Expand Up @@ -277,6 +307,7 @@ cc_library(
"src/ray/common/common_protocol.cc",
],
hdrs = [
"src/ray/common/buffer.h",
"src/ray/common/client_connection.h",
"src/ray/common/common_protocol.h",
],
Expand Down Expand Up @@ -637,8 +668,8 @@ genrule(
cp -f $(location //:raylet) $$WORK_DIR/python/ray/core/src/ray/raylet/ &&
for f in $(locations //:python_gcs_fbs); do cp -f $$f $$WORK_DIR/python/ray/core/generated/; done &&
mkdir -p $$WORK_DIR/python/ray/core/generated/ray/protocol/ &&
for f in $(locations //:python_node_manager_fbs); do
cp -f $$f $$WORK_DIR/python/ray/core/generated/ray/protocol/;
for f in $(locations //:python_node_manager_fbs); do
cp -f $$f $$WORK_DIR/python/ray/core/generated/ray/protocol/;
done &&
echo $$WORK_DIR > $@
""",
Expand Down
43 changes: 43 additions & 0 deletions src/ray/common/buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef RAY_COMMON_BUFFER_H
#define RAY_COMMON_BUFFER_H

#include <cstdint>
#include <cstdio>

namespace ray {

/// The interface that represents a buffer of bytes.
class Buffer {
public:
/// Pointer to the data.
virtual uint8_t *Data() const = 0;

/// Size of this buffer.
virtual size_t Size() const = 0;

virtual ~Buffer();

bool operator==(const Buffer &rhs) const {
return this->Data() == rhs.Data() && this->Size() == rhs.Size();
}
};

/// Represents a byte buffer in local memory.
class LocalMemoryBuffer : public Buffer {
public:
LocalMemoryBuffer(uint8_t *data, size_t size) : data_(data), size_(size) {}

uint8_t *Data() const override { return data_; }

size_t Size() const override { return size_; }

private:
/// Pointer to the data.
uint8_t *data_;
/// Size of the buffer.
size_t size_;
};

} // namespace ray

#endif // RAY_COMMON_BUFFER_H
71 changes: 71 additions & 0 deletions src/ray/core_worker/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#ifndef RAY_CORE_WORKER_COMMON_H
#define RAY_CORE_WORKER_COMMON_H

#include <string>

#include "ray/common/buffer.h"
#include "ray/id.h"

namespace ray {

/// Type of this worker.
enum class WorkerType { WORKER, DRIVER };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What other types make sense here, e.g., does it make sense to have an ACTOR type or a LOCAL_MODE_DRIVER type?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, these 2 make sense. That's why WorkerType is an enum, instead of a boolean is_driver. But I'd like to defer adding them when we actually implement the functionalities.


/// Language of Ray tasks and workers.
enum class Language { PYTHON, JAVA };

/// Information about a remote function.
struct RayFunction {
/// Language of the remote function.
const Language language;
/// Function descriptor of the remote function.
const std::vector<std::string> function_descriptor;
};

/// Argument of a task.
class TaskArg {
public:
/// Create a pass-by-reference task argument.
///
/// \param[in] object_id Id of the argument.
/// \return The task argument.
static TaskArg PassByReference(const ObjectID &object_id) {
return TaskArg(std::make_shared<ObjectID>(object_id), nullptr);
}

/// Create a pass-by-reference task argument.
///
/// \param[in] object_id Id of the argument.
/// \return The task argument.
static TaskArg PassByValue(const std::shared_ptr<Buffer> &data) {
return TaskArg(nullptr, data);
}

/// Return true if this argument is passed by reference, false if passed by value.
bool IsPassedByReference() const { return id_ != nullptr; }

/// Get the reference object ID.
ObjectID &GetReference() {
RAY_CHECK(id_ != nullptr) << "This argument isn't passed by reference.";
return *id_;
}

/// Get the value.
std::shared_ptr<Buffer> GetValue() {
RAY_CHECK(data_ != nullptr) << "This argument isn't passed by value.";
return data_;
}

private:
TaskArg(const std::shared_ptr<ObjectID> id, const std::shared_ptr<Buffer> data)
: id_(id), data_(data) {}

/// Id of the argument, if passed by reference, otherwise nullptr.

@jovany-wang jovany-wang May 28, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of adding a flag explicitly to indicate whether we pass args by ref or by value, so that it will have more readability? And we can get rid of if (id != nullptr) {}.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, will do.

const std::shared_ptr<ObjectID> id_;
/// Data of the argument, if passed by value, otherwise nullptr.
const std::shared_ptr<Buffer> data_;
};

} // namespace ray

#endif // RAY_CORE_WORKER_COMMON_H
68 changes: 68 additions & 0 deletions src/ray/core_worker/core_worker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#ifndef RAY_CORE_WORKER_CORE_WORKER_H
#define RAY_CORE_WORKER_CORE_WORKER_H

#include "common.h"
#include "object_interface.h"
#include "ray/common/buffer.h"
#include "task_execution.h"
#include "task_interface.h"

namespace ray {

/// The root class that contains all the core and language-independent functionalities
/// of the worker. This class is supposed to be used to implement app-language (Java,
/// Python, etc) workers.
class CoreWorker {
public:
/// Construct a CoreWorker instance.
///
/// \param[in] worker_type Type of this worker.
/// \param[in] langauge Language of this worker.
CoreWorker(const WorkerType worker_type, const Language language)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since worker_type and language are passed by value, it's unnecessary to declare them as const.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a minor difference. using const can prevent the argument from being modified in the function.

: worker_type_(worker_type),
language_(language),
task_interface_(*this),
object_interface_(*this),
task_execution_interface_(*this){};

/// Connect this worker to Raylet.
Status Connect() { return Status::OK(); }

/// Type of this worker.
WorkerType WorkerType() const { return worker_type_; }

/// Language of this worker.
Language Language() const { return language_; }

/// Return the `CoreWorkerTaskInterface` that contains the methods related to task
/// submisson.
CoreWorkerTaskInterface &Tasks() { return task_interface_; }

/// Return the `CoreWorkerObjectInterface` that contains methods related to object
/// store.
CoreWorkerObjectInterface &Objects() { return object_interface_; }

/// Return the `CoreWorkerTaskExecutionInterface` that contains methods related to
/// task execution.
CoreWorkerTaskExecutionInterface &Execution() { return task_execution_interface_; }

private:
/// Type of this worker.
const enum WorkerType worker_type_;

/// Language of this worker.
const enum Language language_;

/// The `CoreWorkerTaskInterface` instance.
CoreWorkerTaskInterface task_interface_;

/// The `CoreWorkerObjectInterface` instance.
CoreWorkerObjectInterface object_interface_;

/// The `CoreWorkerTaskExecutionInterface` instance.
CoreWorkerTaskExecutionInterface task_execution_interface_;
Comment thread
raulchen marked this conversation as resolved.
};

} // namespace ray

#endif // RAY_CORE_WORKER_CORE_WORKER_H
38 changes: 38 additions & 0 deletions src/ray/core_worker/core_worker_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "core_worker.h"
#include "ray/common/buffer.h"

namespace ray {

class CoreWorkerTest : public ::testing::Test {
public:
CoreWorkerTest() : core_worker_(WorkerType::WORKER, Language::PYTHON) {}

protected:
CoreWorker core_worker_;
};

TEST_F(CoreWorkerTest, TestTaskArg) {
// Test by-reference argument.
ObjectID id = ObjectID::from_random();
TaskArg by_ref = TaskArg::PassByReference(id);
ASSERT_TRUE(by_ref.IsPassedByReference());
ASSERT_EQ(by_ref.GetReference(), id);
// Test by-value argument.
std::shared_ptr<LocalMemoryBuffer> buffer =
std::make_shared<LocalMemoryBuffer>(static_cast<uint8_t *>(0), 0);
TaskArg by_value = TaskArg::PassByValue(buffer);
ASSERT_FALSE(by_value.IsPassedByReference());
auto data = by_value.GetValue();
ASSERT_TRUE(data != nullptr);
ASSERT_EQ(*data, *buffer);
}

TEST_F(CoreWorkerTest, TestAttributeGetters) {
ASSERT_EQ(core_worker_.WorkerType(), WorkerType::WORKER);
ASSERT_EQ(core_worker_.Language(), Language::PYTHON);
}

} // namespace ray
25 changes: 25 additions & 0 deletions src/ray/core_worker/object_interface.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "object_interface.h"

namespace ray {

Status CoreWorkerObjectInterface::Put(const Buffer &buffer, const ObjectID *object_id) {
return Status::OK();
}

Status CoreWorkerObjectInterface::Get(const std::vector<ObjectID> &ids,
int64_t timeout_ms, std::vector<Buffer> *results) {
return Status::OK();
}

Status CoreWorkerObjectInterface::Wait(const std::vector<ObjectID> &object_ids,
int num_objects, int64_t timeout_ms,
std::vector<bool> *results) {
return Status::OK();
}

Status CoreWorkerObjectInterface::Delete(const std::vector<ObjectID> &object_ids,
bool local_only, bool delete_creating_tasks) {
return Status::OK();
}

} // namespace ray
61 changes: 61 additions & 0 deletions src/ray/core_worker/object_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef RAY_CORE_WORKER_OBJECT_INTERFACE_H
#define RAY_CORE_WORKER_OBJECT_INTERFACE_H

#include "common.h"
#include "ray/common/buffer.h"
#include "ray/id.h"
#include "ray/status.h"

namespace ray {

class CoreWorker;

/// The interface that contains all `CoreWorker` methods that are related to object store.
class CoreWorkerObjectInterface {
public:
CoreWorkerObjectInterface(CoreWorker &core_worker) : core_worker_(core_worker) {}

/// Put an object into object store.
///
/// \param[in] buffer Data buffer of the object.
Comment thread
raulchen marked this conversation as resolved.
/// \param[out] object_id Generated ID of the object.
/// \return Status.
Status Put(const Buffer &buffer, const ObjectID *object_id);

/// Get a list of objects from the object store.
///
/// \param[in] ids IDs of the objects to get.
/// \param[in] timeout_ms Timeout in milliseconds, wait infinitely if it's negative.
/// \param[out] results Result list of objects data.
/// \return Status.
Status Get(const std::vector<ObjectID> &ids, int64_t timeout_ms,
std::vector<Buffer> *results);

/// Wait for a list of objects to appear in the object store.
///
/// \param[in] IDs of the objects to wait for.
/// \param[in] num_returns Number of objects that should appear.
/// \param[in] timeout_ms Timeout in milliseconds, wait infinitely if it's negative.
/// \param[out] results A bitset that indicates each object has appeared or not.
/// \return Status.
Status Wait(const std::vector<ObjectID> &object_ids, int num_objects,
int64_t timeout_ms, std::vector<bool> *results);

/// Delete a list of objects from the object store.
///
/// \param[in] object_ids IDs of the objects to delete.
/// \param[in] local_only Whether only delete the objects in local node, or all nodes in
/// the cluster.
/// \param[in] delete_creating_tasks Whether also delete the tasks that
/// created these objects. \return Status.
Status Delete(const std::vector<ObjectID> &object_ids, bool local_only,
bool delete_creating_tasks);

private:
/// Reference to the parent CoreWorker instance.
CoreWorker &core_worker_;
};

} // namespace ray

#endif // RAY_CORE_WORKER_OBJECT_INTERFACE_H
7 changes: 7 additions & 0 deletions src/ray/core_worker/task_execution.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "task_execution.h"

namespace ray {

void CoreWorkerTaskExecutionInterface::Start(const TaskExecutor &executor) {}

} // namespace ray
Loading