Integrate ref count module into local memory store (#6122)

This commit is contained in:
Eric Liang
2019-11-15 10:52:19 -08:00
committed by GitHub
parent 62cbc043b4
commit 7d33e9949b
10 changed files with 190 additions and 61 deletions
+1 -1
View File
@@ -720,7 +720,7 @@ cdef class CoreWorker:
raylet_socket.encode("ascii"), job_id.native(),
gcs_options.native()[0], log_dir.encode("utf-8"),
node_ip_address.encode("utf-8"), node_manager_port,
task_execution_handler, check_signals, exit_handler))
task_execution_handler, check_signals, exit_handler, True))
def disconnect(self):
with nogil:
+2 -1
View File
@@ -65,7 +65,8 @@ cdef extern from "ray/core_worker/core_worker.h" nogil:
const c_vector[CObjectID] &return_ids,
c_vector[shared_ptr[CRayObject]] *returns) nogil,
CRayStatus() nogil,
void () nogil)
void () nogil,
c_bool ref_counting_enabled)
void Disconnect()
CWorkerType &GetWorkerType()
CLanguage &GetLanguage()
+22 -3
View File
@@ -1211,13 +1211,32 @@ def test_direct_call_simple(ray_start_regular):
return x + 1
f_direct = f.options(is_direct_call=True)
print("a")
assert ray.get(f_direct.remote(2)) == 3
print("b")
assert ray.get([f_direct.remote(i) for i in range(100)]) == list(
range(1, 101))
def test_direct_call_refcount(ray_start_regular):
@ray.remote
def f(x):
return x + 1
@ray.remote
def sleep():
time.sleep(.1)
return 1
# Multiple gets should not hang with ref counting enabled.
f_direct = f.options(is_direct_call=True)
x = f_direct.remote(2)
ray.get(x)
ray.get(x)
# Temporary objects should be retained for chained callers.
y = f_direct.remote(sleep.options(is_direct_call=True).remote())
assert ray.get(y) == 2
def test_direct_call_matrix(shutdown_only):
ray.init(object_store_memory=1000 * 1024 * 1024)
@@ -1407,7 +1426,7 @@ def test_direct_actor_recursive(ray_start_regular):
return x * 2
a = Actor._remote(is_direct_call=True)
b = Actor._remote(args=[a], is_direct_call=False)
b = Actor._remote(args=[a], is_direct_call=True)
c = Actor._remote(args=[b], is_direct_call=True)
result = ray.get([c.f.remote(i) for i in range(100)])
+29 -21
View File
@@ -100,16 +100,19 @@ CoreWorker::CoreWorker(const WorkerType worker_type, const Language language,
int node_manager_port,
const TaskExecutionCallback &task_execution_callback,
std::function<Status()> check_signals,
const std::function<void()> exit_handler)
const std::function<void()> exit_handler,
bool ref_counting_enabled)
: worker_type_(worker_type),
language_(language),
log_dir_(log_dir),
ref_counting_enabled_(ref_counting_enabled),
check_signals_(check_signals),
worker_context_(worker_type, job_id),
io_work_(io_service_),
client_call_manager_(new rpc::ClientCallManager(io_service_)),
heartbeat_timer_(io_service_),
core_worker_server_(WorkerTypeString(worker_type), 0 /* let grpc choose a port */),
reference_counter_(std::make_shared<ReferenceCounter>()),
task_execution_service_work_(task_execution_service_),
task_execution_callback_(task_execution_callback),
grpc_service_(io_service_, *this) {
@@ -189,10 +192,11 @@ CoreWorker::CoreWorker(const WorkerType worker_type, const Language language,
plasma_store_provider_.reset(
new CoreWorkerPlasmaStoreProvider(store_socket, raylet_client_, check_signals_));
memory_store_.reset(
new CoreWorkerMemoryStore([this](const RayObject &obj, const ObjectID &obj_id) {
memory_store_.reset(new CoreWorkerMemoryStore(
[this](const RayObject &obj, const ObjectID &obj_id) {
RAY_CHECK_OK(plasma_store_provider_->Put(obj, obj_id));
}));
},
ref_counting_enabled ? reference_counter_ : nullptr));
memory_store_provider_.reset(new CoreWorkerMemoryStoreProvider(memory_store_));
// Create an entry for the driver task in the task table. This task is
@@ -282,7 +286,7 @@ void CoreWorker::SetCurrentTaskId(const TaskID &task_id) {
void CoreWorker::ReportActiveObjectIDs() {
std::unordered_set<ObjectID> active_object_ids =
reference_counter_.GetAllInScopeObjectIDs();
reference_counter_->GetAllInScopeObjectIDs();
RAY_LOG(DEBUG) << "Sending " << active_object_ids.size() << " object IDs to raylet.";
if (active_object_ids.size() > RayConfig::instance().raylet_max_active_object_ids()) {
RAY_LOG(WARNING) << active_object_ids.size() << "object IDs are currently in scope. "
@@ -542,9 +546,8 @@ TaskID CoreWorker::GetCallerId() const {
return caller_id;
}
Status CoreWorker::SubmitTaskToRaylet(const TaskSpecification &task_spec) {
RAY_RETURN_NOT_OK(raylet_client_->SubmitTask(task_spec));
void CoreWorker::PinObjectReferences(const TaskSpecification &task_spec,
const TaskTransportType transport_type) {
size_t num_returns = task_spec.NumReturns();
if (task_spec.IsActorCreationTask() || task_spec.IsActorTask()) {
num_returns--;
@@ -560,13 +563,10 @@ Status CoreWorker::SubmitTaskToRaylet(const TaskSpecification &task_spec) {
}
}
if (task_deps->size() > 0) {
for (size_t i = 0; i < num_returns; i++) {
reference_counter_.SetDependencies(task_spec.ReturnIdForPlasma(i), task_deps);
}
// Note that we call this even if task_deps.size() == 0, in order to pin the return id.
for (size_t i = 0; i < num_returns; i++) {
reference_counter_->SetDependencies(task_spec.ReturnId(i, transport_type), task_deps);
}
return Status::OK();
}
Status CoreWorker::SubmitTask(const RayFunction &function,
@@ -586,10 +586,13 @@ Status CoreWorker::SubmitTask(const RayFunction &function,
function, args, task_options.num_returns, task_options.resources, {},
task_options.is_direct_call ? TaskTransportType::DIRECT : TaskTransportType::RAYLET,
return_ids);
TaskSpecification task_spec = builder.Build();
if (task_options.is_direct_call) {
return direct_task_submitter_->SubmitTask(builder.Build());
PinObjectReferences(task_spec, TaskTransportType::DIRECT);
return direct_task_submitter_->SubmitTask(task_spec);
} else {
return raylet_client_->SubmitTask(builder.Build());
PinObjectReferences(task_spec, TaskTransportType::RAYLET);
return raylet_client_->SubmitTask(task_spec);
}
}
@@ -623,7 +626,9 @@ Status CoreWorker::CreateActor(const RayFunction &function,
<< "Actor " << actor_id << " already exists";
*return_actor_id = actor_id;
return SubmitTaskToRaylet(builder.Build());
TaskSpecification task_spec = builder.Build();
PinObjectReferences(task_spec, TaskTransportType::RAYLET);
return raylet_client_->SubmitTask(task_spec);
}
Status CoreWorker::SubmitActorTask(const ActorID &actor_id, const RayFunction &function,
@@ -659,10 +664,13 @@ Status CoreWorker::SubmitActorTask(const ActorID &actor_id, const RayFunction &f
// Submit task.
Status status;
TaskSpecification task_spec = builder.Build();
if (is_direct_call) {
status = direct_actor_submitter_->SubmitTask(builder.Build());
PinObjectReferences(task_spec, TaskTransportType::DIRECT);
status = direct_actor_submitter_->SubmitTask(task_spec);
} else {
status = SubmitTaskToRaylet(builder.Build());
PinObjectReferences(task_spec, TaskTransportType::RAYLET);
RAY_CHECK_OK(raylet_client_->SubmitTask(task_spec));
}
return status;
}
@@ -830,9 +838,9 @@ Status CoreWorker::ExecuteTask(const TaskSpecification &task_spec,
}
}
if (task_spec.IsNormalTask() && reference_counter_.NumObjectIDsInScope() != 0) {
if (task_spec.IsNormalTask() && reference_counter_->NumObjectIDsInScope() != 0) {
RAY_LOG(DEBUG)
<< "There were " << reference_counter_.NumObjectIDsInScope()
<< "There were " << reference_counter_->NumObjectIDsInScope()
<< " ObjectIDs left in scope after executing task " << task_spec.TaskId()
<< ". This is either caused by keeping references to ObjectIDs in Python between "
"tasks (e.g., in global variables) or indicates a problem with Ray's "
+19 -8
View File
@@ -61,11 +61,12 @@ class CoreWorker {
/// \param[in] node_ip_address IP address of the node.
/// \param[in] node_manager_port Port of the local raylet.
/// \param[in] task_execution_callback Language worker callback to execute tasks.
/// \parma[in] check_signals Language worker function to check for signals and handle
/// \param[in] check_signals Language worker function to check for signals and handle
/// them. If the function returns anything but StatusOK, any long-running
/// operations in the core worker will short circuit and return that status.
/// \parma[in] exit_handler Language worker function to orderly shutdown the worker.
/// \param[in] exit_handler Language worker function to orderly shutdown the worker.
/// We guarantee this will be run on the main thread of the worker.
/// \param[in] ref_counting_enabled Whether to enable object ref counting.
///
/// NOTE(zhijunfu): the constructor would throw if a failure happens.
CoreWorker(const WorkerType worker_type, const Language language,
@@ -74,7 +75,8 @@ class CoreWorker {
const std::string &log_dir, const std::string &node_ip_address,
int node_manager_port, const TaskExecutionCallback &task_execution_callback,
std::function<Status()> check_signals = nullptr,
std::function<void()> exit_handler = nullptr);
std::function<void()> exit_handler = nullptr,
bool ref_counting_enabled = false);
~CoreWorker();
@@ -103,14 +105,18 @@ class CoreWorker {
///
/// \param[in] object_id The object ID to increase the reference count for.
void AddObjectIDReference(const ObjectID &object_id) {
reference_counter_.AddReference(object_id);
reference_counter_->AddReference(object_id);
}
/// Decrease the reference count for this object ID.
///
/// \param[in] object_id The object ID to decrease the reference count for.
void RemoveObjectIDReference(const ObjectID &object_id) {
reference_counter_.RemoveReference(object_id);
std::vector<ObjectID> deleted;
reference_counter_->RemoveReference(object_id, &deleted);
if (ref_counting_enabled_) {
memory_store_->Delete(deleted);
}
}
/// Promote an object to plasma. If it already exists locally, it will be
@@ -369,8 +375,10 @@ class CoreWorker {
/// Private methods related to task submission.
///
/// Submit the task to the raylet and add its dependencies to the reference counter.
Status SubmitTaskToRaylet(const TaskSpecification &task_spec);
/// Add task dependencies to the reference counter. This prevents the argument
/// objects from early eviction, and also adds the return object.
void PinObjectReferences(const TaskSpecification &task_spec,
const TaskTransportType transport_type);
/// Give this worker a handle to an actor.
///
@@ -434,6 +442,9 @@ class CoreWorker {
/// Directory where log files are written.
const std::string log_dir_;
/// Whether local reference counting is enabled.
const bool ref_counting_enabled_;
/// Application-language callback to check for signals that have been received
/// since calling into C++. This will be called periodically (at least every
/// 1s) during long-running operations.
@@ -481,7 +492,7 @@ class CoreWorker {
std::thread io_thread_;
// Keeps track of object ID reference counts.
ReferenceCounter reference_counter_;
std::shared_ptr<ReferenceCounter> reference_counter_;
///
/// Fields related to storing and retrieving objects.
+12 -4
View File
@@ -36,12 +36,14 @@ void ReferenceCounter::SetDependencies(
}
}
void ReferenceCounter::RemoveReference(const ObjectID &object_id) {
void ReferenceCounter::RemoveReference(const ObjectID &object_id,
std::vector<ObjectID> *deleted) {
absl::MutexLock lock(&mutex_);
RemoveReferenceRecursive(object_id);
RemoveReferenceRecursive(object_id, deleted);
}
void ReferenceCounter::RemoveReferenceRecursive(const ObjectID &object_id) {
void ReferenceCounter::RemoveReferenceRecursive(const ObjectID &object_id,
std::vector<ObjectID> *deleted) {
auto entry = object_id_refs_.find(object_id);
if (entry == object_id_refs_.end()) {
RAY_LOG(WARNING) << "Tried to decrease ref count for nonexistent object ID: "
@@ -52,13 +54,19 @@ void ReferenceCounter::RemoveReferenceRecursive(const ObjectID &object_id) {
// If the reference count reached 0, decrease the reference count for each dependency.
if (entry->second.second) {
for (const ObjectID &pending_task_object_id : *entry->second.second) {
RemoveReferenceRecursive(pending_task_object_id);
RemoveReferenceRecursive(pending_task_object_id, deleted);
}
}
object_id_refs_.erase(object_id);
deleted->push_back(object_id);
}
}
bool ReferenceCounter::HasReference(const ObjectID &object_id) {
absl::MutexLock lock(&mutex_);
return object_id_refs_.find(object_id) != object_id_refs_.end();
}
size_t ReferenceCounter::NumObjectIDsInScope() const {
absl::MutexLock lock(&mutex_);
return object_id_refs_.size();
+12 -2
View File
@@ -25,7 +25,11 @@ class ReferenceCounter {
/// Decrease the reference count for the ObjectID by one. If the reference count reaches
/// zero, it will be erased from the map and the reference count for all of its
/// dependencies will be decreased be one.
void RemoveReference(const ObjectID &object_id) LOCKS_EXCLUDED(mutex_);
///
/// \param[in] object_id The object to to decrement the count for.
/// \param[in] deleted List to store objects that hit zero ref count.
void RemoveReference(const ObjectID &object_id, std::vector<ObjectID> *deleted)
LOCKS_EXCLUDED(mutex_);
/// Set the dependencies for the ObjectID. Dependencies for each ObjectID must be
/// set at most once. The direct reference count for the ObjectID is set to zero and the
@@ -37,6 +41,9 @@ class ReferenceCounter {
/// Returns the total number of ObjectIDs currently in scope.
size_t NumObjectIDsInScope() const LOCKS_EXCLUDED(mutex_);
/// Returns whether this object has an active reference.
bool HasReference(const ObjectID &object_id) LOCKS_EXCLUDED(mutex_);
/// Returns a set of all ObjectIDs currently in scope (i.e., nonzero reference count).
std::unordered_set<ObjectID> GetAllInScopeObjectIDs() const LOCKS_EXCLUDED(mutex_);
@@ -51,7 +58,10 @@ class ReferenceCounter {
/// Recursive helper function for decreasing reference counts. Will recursively call
/// itself on any dependencies whose reference count reaches zero as a result of
/// removing the reference.
void RemoveReferenceRecursive(const ObjectID &object_id)
///
/// \param[in] object_id The object to to decrement the count for.
/// \param[in] deleted List to store objects that hit zero ref count.
void RemoveReferenceRecursive(const ObjectID &object_id, std::vector<ObjectID> *deleted)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
/// Protects access to the reference counting state.
+56 -12
View File
@@ -1,7 +1,9 @@
#include <vector>
#include "gtest/gtest.h"
#include "ray/common/ray_object.h"
#include "ray/core_worker/reference_count.h"
#include "ray/core_worker/store_provider/memory_store/memory_store.h"
namespace ray {
@@ -16,6 +18,7 @@ class ReferenceCountTest : public ::testing::Test {
// Tests basic incrementing/decrementing of direct reference counts. An entry should only
// be removed once its reference count reaches zero.
TEST_F(ReferenceCountTest, TestBasic) {
std::vector<ObjectID> out;
ObjectID id = ObjectID::FromRandom();
rc->AddReference(id);
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
@@ -23,18 +26,22 @@ TEST_F(ReferenceCountTest, TestBasic) {
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
rc->AddReference(id);
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
rc->RemoveReference(id);
rc->RemoveReference(id, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
rc->RemoveReference(id);
ASSERT_EQ(out.size(), 0);
rc->RemoveReference(id, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
rc->RemoveReference(id);
ASSERT_EQ(out.size(), 0);
rc->RemoveReference(id, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 0);
ASSERT_EQ(out.size(), 1);
}
// Tests the basic logic for dependencies - when an ObjectID with dependencies
// goes out of scope (i.e., reference count reaches zero), all of its dependencies
// should have their reference count decremented and be removed if it reaches zero.
TEST_F(ReferenceCountTest, TestDependencies) {
std::vector<ObjectID> out;
ObjectID id1 = ObjectID::FromRandom();
ObjectID id2 = ObjectID::FromRandom();
ObjectID id3 = ObjectID::FromRandom();
@@ -49,13 +56,16 @@ TEST_F(ReferenceCountTest, TestDependencies) {
rc->AddReference(id3);
ASSERT_EQ(rc->NumObjectIDsInScope(), 3);
rc->RemoveReference(id1);
rc->RemoveReference(id1, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 3);
rc->RemoveReference(id1);
ASSERT_EQ(out.size(), 0);
rc->RemoveReference(id1, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
ASSERT_EQ(out.size(), 2);
rc->RemoveReference(id3);
rc->RemoveReference(id3, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 0);
ASSERT_EQ(out.size(), 3);
}
// Tests the case where two entries share the same set of dependencies. When one
@@ -63,6 +73,7 @@ TEST_F(ReferenceCountTest, TestDependencies) {
// but they should still be nonzero until the second entry goes out of scope and all
// direct dependencies to the dependencies are removed.
TEST_F(ReferenceCountTest, TestSharedDependencies) {
std::vector<ObjectID> out;
ObjectID id1 = ObjectID::FromRandom();
ObjectID id2 = ObjectID::FromRandom();
ObjectID id3 = ObjectID::FromRandom();
@@ -79,13 +90,16 @@ TEST_F(ReferenceCountTest, TestSharedDependencies) {
rc->AddReference(id4);
ASSERT_EQ(rc->NumObjectIDsInScope(), 4);
rc->RemoveReference(id1);
rc->RemoveReference(id1, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 3);
rc->RemoveReference(id2);
ASSERT_EQ(out.size(), 1);
rc->RemoveReference(id2, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
ASSERT_EQ(out.size(), 3);
rc->RemoveReference(id4);
rc->RemoveReference(id4, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 0);
ASSERT_EQ(out.size(), 4);
}
// Tests the case when an entry has a dependency that itself has a
@@ -93,6 +107,7 @@ TEST_F(ReferenceCountTest, TestSharedDependencies) {
// it should decrease the reference count for its dependency, causing
// that entry to go out of scope and decrease its dependencies' reference counts.
TEST_F(ReferenceCountTest, TestRecursiveDependencies) {
std::vector<ObjectID> out;
ObjectID id1 = ObjectID::FromRandom();
ObjectID id2 = ObjectID::FromRandom();
ObjectID id3 = ObjectID::FromRandom();
@@ -114,13 +129,42 @@ TEST_F(ReferenceCountTest, TestRecursiveDependencies) {
rc->AddReference(id4);
ASSERT_EQ(rc->NumObjectIDsInScope(), 4);
rc->RemoveReference(id2);
rc->RemoveReference(id2, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 4);
rc->RemoveReference(id1);
ASSERT_EQ(out.size(), 0);
rc->RemoveReference(id1, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 1);
ASSERT_EQ(out.size(), 3);
rc->RemoveReference(id4);
rc->RemoveReference(id4, &out);
ASSERT_EQ(rc->NumObjectIDsInScope(), 0);
ASSERT_EQ(out.size(), 4);
}
// Tests that the ref counts are properly integrated into the local
// object memory store.
TEST(MemoryStoreIntegrationTest, TestSimple) {
ObjectID id1 = ObjectID::FromRandom().WithDirectTransportType();
ObjectID id2 = ObjectID::FromRandom().WithDirectTransportType();
uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8};
RayObject buffer(std::make_shared<LocalMemoryBuffer>(data, sizeof(data)), nullptr);
auto rc = std::shared_ptr<ReferenceCounter>(new ReferenceCounter());
CoreWorkerMemoryStore store(nullptr, rc);
// Tests putting an object with no references is ignored.
RAY_CHECK_OK(store.Put(id2, buffer));
ASSERT_EQ(store.Size(), 0);
// Tests ref counting overrides remove after get option.
rc->AddReference(id1);
RAY_CHECK_OK(store.Put(id1, buffer));
ASSERT_EQ(store.Size(), 1);
std::vector<std::shared_ptr<RayObject>> results;
RAY_CHECK_OK(store.Get({id1}, /*num_objects*/ 1, /*timeout_ms*/ -1,
/*remove_after_get*/ true, &results));
ASSERT_EQ(results.size(), 1);
ASSERT_EQ(store.Size(), 1);
}
} // namespace ray
@@ -108,8 +108,9 @@ std::shared_ptr<RayObject> GetRequest::Get(const ObjectID &object_id) const {
}
CoreWorkerMemoryStore::CoreWorkerMemoryStore(
std::function<void(const RayObject &, const ObjectID &)> store_in_plasma)
: store_in_plasma_(store_in_plasma) {}
std::function<void(const RayObject &, const ObjectID &)> store_in_plasma,
std::shared_ptr<ReferenceCounter> counter)
: store_in_plasma_(store_in_plasma), ref_counter_(counter) {}
void CoreWorkerMemoryStore::GetAsync(
const ObjectID &object_id, std::function<void(std::shared_ptr<RayObject>)> callback) {
@@ -154,6 +155,7 @@ Status CoreWorkerMemoryStore::Put(const ObjectID &object_id, const RayObject &ob
{
absl::MutexLock lock(&mu_);
auto iter = objects_.find(object_id);
if (iter != objects_.end()) {
return Status::ObjectExists("object already exists in the memory store");
@@ -179,11 +181,16 @@ Status CoreWorkerMemoryStore::Put(const ObjectID &object_id, const RayObject &ob
auto &get_requests = object_request_iter->second;
for (auto &get_request : get_requests) {
get_request->Set(object_id, object_entry);
if (get_request->ShouldRemoveObjects()) {
// If ref counting is enabled, override the removal behaviour.
if (get_request->ShouldRemoveObjects() && ref_counter_ == nullptr) {
should_add_entry = false;
}
}
}
// Don't put it in the store, since we won't get a callback for deletion.
if (ref_counter_ != nullptr && !ref_counter_->HasReference(object_id)) {
should_add_entry = false;
}
if (should_add_entry) {
// If there is no existing get request, then add the `RayObject` to map.
@@ -231,8 +238,11 @@ Status CoreWorkerMemoryStore::Get(const std::vector<ObjectID> &object_ids,
}
RAY_CHECK(count <= num_objects);
for (const auto &object_id : ids_to_remove) {
objects_.erase(object_id);
// Clean up the objects if ref counting is off.
if (ref_counter_ == nullptr) {
for (const auto &object_id : ids_to_remove) {
objects_.erase(object_id);
}
}
// Return if all the objects are obtained.
@@ -298,8 +308,7 @@ void CoreWorkerMemoryStore::Delete(const std::vector<ObjectID> &object_ids) {
bool CoreWorkerMemoryStore::Contains(const ObjectID &object_id) {
absl::MutexLock lock(&mu_);
auto it = objects_.find(object_id);
// If obj is in plasma, we defer to the plasma store for the Contains() call.
return it != objects_.end() && !it->second->IsInPlasmaError();
return it != objects_.end();
}
} // namespace ray
@@ -7,6 +7,7 @@
#include "ray/common/id.h"
#include "ray/common/status.h"
#include "ray/core_worker/common.h"
#include "ray/core_worker/reference_count.h"
namespace ray {
@@ -18,8 +19,14 @@ class CoreWorkerMemoryStore;
/// actor call (see direct_actor_transport.cc).
class CoreWorkerMemoryStore {
public:
/// Create a memory store.
///
/// \param[in] store_in_plasma If not null, this is used to spill to plasma.
/// \param[in] counter If not null, this enables ref counting for local objects,
/// and the `remove_after_get` flag for Get() will be ignored.
CoreWorkerMemoryStore(
std::function<void(const RayObject &, const ObjectID &)> store_in_plasma = nullptr);
std::function<void(const RayObject &, const ObjectID &)> store_in_plasma = nullptr,
std::shared_ptr<ReferenceCounter> counter = nullptr);
~CoreWorkerMemoryStore(){};
/// Put an object with specified ID into object store.
@@ -35,7 +42,7 @@ class CoreWorkerMemoryStore {
/// \param[in] num_objects Number of objects that should appear.
/// \param[in] timeout_ms Timeout in milliseconds, wait infinitely if it's negative.
/// \param[in] remove_after_get When to remove the objects from store after `Get`
/// finishes.
/// finishes. This has no effect if ref counting is enabled.
/// \param[out] results Result list of objects data.
/// \return Status.
Status Get(const std::vector<ObjectID> &object_ids, int num_objects, int64_t timeout_ms,
@@ -70,10 +77,22 @@ class CoreWorkerMemoryStore {
/// \return Whether the store has the object.
bool Contains(const ObjectID &object_id);
/// Returns the number of objects in this store.
///
/// \return Count of objects in the store.
int Size() {
absl::MutexLock lock(&mu_);
return objects_.size();
}
private:
/// Optional callback for putting objects into the plasma store.
std::function<void(const RayObject &, const ObjectID &)> store_in_plasma_;
/// If enabled, holds a reference to local worker ref counter. TODO(ekl) make this
/// mandatory once Java is supported.
std::shared_ptr<ReferenceCounter> ref_counter_ = nullptr;
/// Protects the data structures below.
absl::Mutex mu_;