Factoring out object_info structure for use in several Ray components (#101)

* change plasma object notifications to carry a struct of information

* factoring out object_info for general use by several Ray components

* fixing a bug in python test

* addressing comments

* handling Robert's comments

* clang format

* Fix valgrind.
This commit is contained in:
atumanov
2016-12-08 19:14:10 -08:00
committed by Philipp Moritz
parent 88206417cb
commit 1c946b2f6a
9 changed files with 99 additions and 38 deletions
+19
View File
@@ -0,0 +1,19 @@
#ifndef OBJECT_H
#define OBJECT_H
#include <stdint.h>
#include "common.h"
/**
* Object information data structure.
*/
typedef struct {
object_id obj_id;
int64_t data_size;
int64_t metadata_size;
int64_t create_time;
int64_t construct_duration;
} object_info;
#endif
+11 -5
View File
@@ -9,6 +9,7 @@
#include "common.h"
#include "event_loop.h"
#include "io.h"
#include "object_info.h"
#include "photon.h"
#include "photon_algorithm.h"
#include "photon_scheduler.h"
@@ -104,8 +105,9 @@ void process_plasma_notification(event_loop *loop,
int events) {
local_scheduler_state *s = context;
/* Read the notification from Plasma. */
object_id obj_id;
int error = read_bytes(client_sock, (uint8_t *) &obj_id, sizeof(obj_id));
object_info object_info;
int error =
read_bytes(client_sock, (uint8_t *) &object_info, sizeof(object_info));
if (error < 0) {
/* The store has closed the socket. */
LOG_DEBUG(
@@ -115,10 +117,12 @@ void process_plasma_notification(event_loop *loop,
close(client_sock);
return;
}
handle_object_available(s, s->algorithm_state, obj_id);
handle_object_available(s, s->algorithm_state, object_info.obj_id);
}
void process_message(event_loop *loop, int client_sock, void *context,
void process_message(event_loop *loop,
int client_sock,
void *context,
int events) {
local_scheduler_state *s = context;
@@ -151,7 +155,9 @@ void process_message(event_loop *loop, int client_sock, void *context,
}
}
void new_client_connection(event_loop *loop, int listener_sock, void *context,
void new_client_connection(event_loop *loop,
int listener_sock,
void *context,
int events) {
local_scheduler_state *s = context;
int new_socket = accept_client(listener_sock);
+5 -3
View File
@@ -211,6 +211,7 @@ class PlasmaClient(object):
"""Subscribe to notifications about sealed objects."""
fd = libplasma.subscribe(self.conn)
self.notification_sock = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM)
self.notification_fd = fd
# Make the socket non-blocking.
self.notification_sock.setblocking(0)
@@ -221,13 +222,14 @@ class PlasmaClient(object):
# Loop until we've read PLASMA_ID_SIZE bytes from the socket.
while True:
try:
message_data = self.notification_sock.recv(PLASMA_ID_SIZE)
rv = libplasma.receive_notification(self.notification_fd)
obj_id, data_size, metadata_size = rv
except socket.error:
time.sleep(0.001)
else:
assert len(message_data) == PLASMA_ID_SIZE
assert len(obj_id) == PLASMA_ID_SIZE
break
return message_data
return obj_id, data_size, metadata_size
DEFAULT_PLASMA_STORE_MEMORY = 10 ** 9
+2 -8
View File
@@ -11,17 +11,11 @@
#include <unistd.h> /* pid_t */
#include "common.h"
#include "object_info.h"
#include "utarray.h"
#include "uthash.h"
typedef struct {
int64_t data_size;
int64_t metadata_size;
int64_t create_time;
int64_t construct_duration;
} plasma_object_info;
/**
* Object request data structure. Used in the plasma_wait_for_objects()
* argument.
@@ -199,7 +193,7 @@ typedef struct {
/** Object id of this object. */
object_id object_id;
/** Object info like size, creation time and owner. */
plasma_object_info info;
object_info info;
/** Memory mapped file containing the object. */
int fd;
/** Size of the underlying map. */
-11
View File
@@ -291,17 +291,6 @@ typedef struct {
uint8_t *metadata;
} object_buffer;
/**
* Object information data structure.
*/
typedef struct {
/** The time when the object was created (sealed). */
time_t last_access_time;
/** The time when the object was last accessed. */
time_t creation_date;
uint64_t refcount;
} object_info;
/**
* Get specified object from the local Plasma Store. This function is
* non-blocking.
+32
View File
@@ -1,7 +1,9 @@
#include <Python.h>
#include "common.h"
#include "io.h"
#include "plasma_client.h"
#include "object_info.h"
static int PyObjectToPlasmaConnection(PyObject *object,
plasma_connection **conn) {
@@ -305,10 +307,38 @@ PyObject *PyPlasma_subscribe(PyObject *self, PyObject *args) {
if (!PyArg_ParseTuple(args, "O&", PyObjectToPlasmaConnection, &conn)) {
return NULL;
}
int sock = plasma_subscribe(conn);
return PyInt_FromLong(sock);
}
PyObject *PyPlasma_receive_notification(PyObject *self, PyObject *args) {
int plasma_sock;
object_info object_info;
if (!PyArg_ParseTuple(args, "i", &plasma_sock)) {
return NULL;
}
/* Receive object notification from the plasma connection socket,
* return a tuple of its fields: object_id, data_size, metadata_size. */
int nbytes =
read_bytes(plasma_sock, (uint8_t *) &object_info, sizeof(object_info));
if (nbytes < 0) {
PyErr_SetString(PyExc_RuntimeError,
"Failed to read object notification from Plasma socket");
return NULL;
}
/* Construct a tuple from object_info and return. */
PyObject *t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyString_FromStringAndSize(
(char *) object_info.obj_id.id, UNIQUE_ID_SIZE));
PyTuple_SetItem(t, 1, PyInt_FromLong(object_info.data_size));
PyTuple_SetItem(t, 2, PyInt_FromLong(object_info.metadata_size));
return t;
}
static PyMethodDef plasma_methods[] = {
{"connect", PyPlasma_connect, METH_VARARGS, "Connect to plasma."},
{"disconnect", PyPlasma_disconnect, METH_VARARGS,
@@ -332,6 +362,8 @@ static PyMethodDef plasma_methods[] = {
"Transfer object to another plasma manager."},
{"subscribe", PyPlasma_subscribe, METH_VARARGS,
"Subscribe to the plasma notification socket."},
{"receive_notification", PyPlasma_receive_notification, METH_VARARGS,
"Receive next notification from plasma notification socket."},
{NULL} /* Sentinel */
};
+4 -1
View File
@@ -1497,13 +1497,15 @@ void process_object_notification(event_loop *loop,
int events) {
plasma_manager_state *state = context;
object_id obj_id;
object_info object_info;
retry_info retry = {
.num_retries = NUM_RETRIES,
.timeout = MANAGER_TIMEOUT,
.fail_callback = NULL,
};
/* Read the notification from Plasma. */
int error = read_bytes(client_sock, (uint8_t *) &obj_id, sizeof(obj_id));
int error =
read_bytes(client_sock, (uint8_t *) &object_info, sizeof(object_info));
if (error < 0) {
/* The store has closed the socket. */
LOG_DEBUG(
@@ -1513,6 +1515,7 @@ void process_object_notification(event_loop *loop,
close(client_sock);
return;
}
obj_id = object_info.obj_id;
/* Add object to locally available object. */
/* TODO(pcm): Where is this deallocated? */
available_object *entry =
+15 -3
View File
@@ -164,7 +164,9 @@ bool create_object(client *client_context,
assert(fd != -1);
entry = malloc(sizeof(object_table_entry));
memset(entry, 0, sizeof(object_table_entry));
memcpy(&entry->object_id, &obj_id, sizeof(entry->object_id));
entry->info.obj_id = obj_id;
entry->info.data_size = data_size;
entry->info.metadata_size = metadata_size;
entry->pointer = pointer;
@@ -399,11 +401,21 @@ void send_notifications(event_loop *loop,
* possible. */
for (int i = 0; i < utarray_len(queue->object_ids); ++i) {
object_id *obj_id = (object_id *) utarray_eltptr(queue->object_ids, i);
object_table_entry *entry = NULL;
/* This object should already exist in plasma store state. */
HASH_FIND(handle, plasma_state->plasma_store_info->objects, obj_id,
sizeof(object_id), entry);
CHECK(entry != NULL);
object_info object_info = entry->info;
/* Attempt to send a notification about this object ID. */
int nbytes = send(client_sock, (char const *) obj_id, sizeof(*obj_id), 0);
int nbytes =
send(client_sock, (char const *) &object_info, sizeof(object_info), 0);
if (nbytes >= 0) {
CHECK(nbytes == sizeof(*obj_id));
} else if (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
CHECK(nbytes == sizeof(object_info));
} else if (nbytes == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
LOG_DEBUG(
"The socket's send buffer is full, so we are caching this "
"notification and will send it later.");
+11 -7
View File
@@ -254,14 +254,18 @@ class TestPlasmaClient(unittest.TestCase):
sock = self.plasma_client.subscribe()
for i in [1, 10, 100, 1000, 10000, 100000]:
object_ids = [random_object_id() for _ in range(i)]
for object_id in object_ids:
# Create an object and seal it to trigger a notification.
self.plasma_client.create(object_id, 1000)
self.plasma_client.seal(object_id)
metadata_sizes = [np.random.randint(1000) for _ in range(i)]
data_sizes = [np.random.randint(1000) for _ in range(i)]
for j in range(i):
self.plasma_client.create(object_ids[j], size=data_sizes[j],
metadata=bytearray(np.random.bytes(metadata_sizes[j])))
self.plasma_client.seal(object_ids[j])
# Check that we received notifications for all of the objects.
for object_id in object_ids:
message_data = self.plasma_client.get_next_notification()
self.assertEqual(object_id, message_data)
for j in range(i):
recv_objid, recv_dsize, recv_msize = self.plasma_client.get_next_notification()
self.assertEqual(object_ids[j], recv_objid)
self.assertEqual(data_sizes[j], recv_dsize)
self.assertEqual(metadata_sizes[j], recv_msize)
class TestPlasmaManager(unittest.TestCase):