blob: 2552d0a9da03ebcd6274c01c07978a92c48cb4ba [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <arrow-glib/error.hpp>
#include <plasma-glib/client.hpp>
#include <plasma-glib/object.hpp>
G_BEGIN_DECLS
/**
* SECTION: object
* @section_id: object-classes
* @title: Object related classes
* @include: plasma-glib/plasma-glib.h
*
* #GPlasmaObjectID is a class for an object ID.
*
* #GPlasmaObject is a base class for an object stored in plasma store.
*
* #GPlasmaCreatedObject is a class for a created object. You can
* change data of the object until the object is sealed or aborted.
*
* #GPlasmaReferredObject is a class for a created object. You can
* only refer the data and metadata of the object. You can't change
* the data of the object.
*
* Since: 0.12.0
*/
typedef struct GPlasmaObjectIDPrivate_ {
plasma::ObjectID id;
} GPlasmaObjectIDPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(GPlasmaObjectID,
gplasma_object_id,
G_TYPE_OBJECT)
#define GPLASMA_OBJECT_ID_GET_PRIVATE(object) \
static_cast<GPlasmaObjectIDPrivate *>( \
gplasma_object_id_get_instance_private( \
GPLASMA_OBJECT_ID(object)))
static void
gplasma_object_id_init(GPlasmaObjectID *object)
{
}
static void
gplasma_object_id_class_init(GPlasmaObjectIDClass *klass)
{
}
/**
* gplasma_object_id_new:
* @id: (array length=size): The raw ID bytes.
* @size: The number of bytes of the ID. It must be 1..20.
* @error: (nullable): Return location for a #GError or %NULL.
*
* Returns: (nullable): A newly created #GPlasmaObjectID on success,
* %NULL on error.
*
* Since: 0.12.0
*/
GPlasmaObjectID *
gplasma_object_id_new(const guint8 *id,
gsize size,
GError **error)
{
if (size == 0 || size > plasma::kUniqueIDSize) {
g_set_error(error,
GARROW_ERROR,
GARROW_ERROR_INVALID,
"[plasma][object-id][new] "
"ID must be 1..20 bytes: <%" G_GSIZE_FORMAT ">",
size);
return NULL;
}
auto object_id = g_object_new(GPLASMA_TYPE_OBJECT_ID, NULL);
auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(object_id);
memcpy(priv->id.mutable_data(), id, size);
if (size != plasma::kUniqueIDSize) {
memset(priv->id.mutable_data() + size, 0, plasma::kUniqueIDSize - size);
}
return GPLASMA_OBJECT_ID(object_id);
}
/**
* gplasma_object_id_to_binary:
* @id: A #GPlasmaObjectID.
* @size: (nullable) (out): The number of bytes of the byte string of
* the object ID. It's always 20. 20 is `plasma::kUniqueIDSize`.
*
* Returns: (array length=size): The byte string of the object ID.
*
* Since: 0.12.0
*/
const guint8 *
gplasma_object_id_to_binary(GPlasmaObjectID *id,
gsize *size)
{
auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(id);
if (size) {
*size = plasma::kUniqueIDSize;
}
return priv->id.data();
}
/**
* gplasma_object_id_to_hex:
* @id: A #GPlasmaObjectID.
*
* Returns: (transfer full): The hex representation of the object ID.
*
* It should be freed with g_free() when no longer needed.
*
* Since: 0.12.0
*/
gchar *
gplasma_object_id_to_hex(GPlasmaObjectID *id)
{
auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(id);
return g_strdup(priv->id.hex().c_str());
}
typedef struct GPlasmaObjectPrivate_ {
GPlasmaClient *client;
GPlasmaObjectID *id;
std::shared_ptr<arrow::Buffer> raw_data;
GArrowBuffer *data;
std::shared_ptr<arrow::Buffer> raw_metadata;
GArrowBuffer *metadata;
gint gpu_device;
} GPlasmaObjectPrivate;
enum {
PROP_CLIENT = 1,
PROP_ID,
PROP_RAW_DATA,
PROP_DATA,
PROP_RAW_METADATA,
PROP_METADATA,
PROP_GPU_DEVICE
};
G_DEFINE_TYPE_WITH_PRIVATE(GPlasmaObject,
gplasma_object,
G_TYPE_OBJECT)
#define GPLASMA_OBJECT_GET_PRIVATE(object) \
static_cast<GPlasmaObjectPrivate *>( \
gplasma_object_get_instance_private( \
GPLASMA_OBJECT(object)))
static void
gplasma_object_dispose(GObject *object)
{
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
// Properties except priv->id must be disposed in subclass.
if (priv->id) {
g_object_unref(priv->id);
priv->id = nullptr;
}
G_OBJECT_CLASS(gplasma_object_parent_class)->dispose(object);
}
static void
gplasma_object_finalize(GObject *object)
{
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
priv->raw_data.~shared_ptr();
priv->raw_metadata.~shared_ptr();
G_OBJECT_CLASS(gplasma_object_parent_class)->finalize(object);
}
static void
gplasma_object_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
switch (prop_id) {
case PROP_CLIENT:
priv->client = GPLASMA_CLIENT(g_value_dup_object(value));
break;
case PROP_ID:
priv->id = GPLASMA_OBJECT_ID(g_value_dup_object(value));
break;
case PROP_RAW_DATA:
priv->raw_data =
*static_cast<std::shared_ptr<arrow::Buffer> *>(g_value_get_pointer(value));
break;
case PROP_DATA:
priv->data = GARROW_BUFFER(g_value_dup_object(value));
break;
case PROP_RAW_METADATA:
{
auto raw_metadata =
static_cast<std::shared_ptr<arrow::Buffer> *>(g_value_get_pointer(value));
if (raw_metadata) {
priv->raw_metadata = *raw_metadata;
} else {
priv->raw_metadata = nullptr;
}
}
break;
case PROP_METADATA:
priv->metadata = GARROW_BUFFER(g_value_dup_object(value));
break;
case PROP_GPU_DEVICE:
priv->gpu_device = g_value_get_int(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gplasma_object_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
switch (prop_id) {
case PROP_CLIENT:
g_value_set_object(value, priv->client);
break;
case PROP_ID:
g_value_set_object(value, priv->id);
break;
case PROP_DATA:
g_value_set_object(value, priv->data);
break;
case PROP_METADATA:
g_value_set_object(value, priv->metadata);
break;
case PROP_GPU_DEVICE:
g_value_set_int(value, priv->gpu_device);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gplasma_object_init(GPlasmaObject *object)
{
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
new(&priv->raw_data) std::shared_ptr<arrow::Buffer>;
new(&priv->raw_metadata) std::shared_ptr<arrow::Buffer>;
}
static void
gplasma_object_class_init(GPlasmaObjectClass *klass)
{
auto gobject_class = G_OBJECT_CLASS(klass);
gobject_class->dispose = gplasma_object_dispose;
gobject_class->finalize = gplasma_object_finalize;
gobject_class->set_property = gplasma_object_set_property;
gobject_class->get_property = gplasma_object_get_property;
GParamSpec *spec;
spec = g_param_spec_object("client",
"Client",
"The client",
GPLASMA_TYPE_CLIENT,
static_cast<GParamFlags>(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_CLIENT, spec);
spec = g_param_spec_object("id",
"ID",
"The ID of this object",
GPLASMA_TYPE_OBJECT_ID,
static_cast<GParamFlags>(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_ID, spec);
spec = g_param_spec_pointer("raw-data",
"Raw data",
"The raw data of this object",
static_cast<GParamFlags>(G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_RAW_DATA, spec);
spec = g_param_spec_object("data",
"Data",
"The data of this object",
GARROW_TYPE_BUFFER,
static_cast<GParamFlags>(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_DATA, spec);
spec = g_param_spec_pointer("raw-metadata",
"Raw metadata",
"The raw metadata of this object",
static_cast<GParamFlags>(G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_RAW_METADATA, spec);
spec = g_param_spec_object("metadata",
"Metadata",
"The metadata of this object",
GARROW_TYPE_BUFFER,
static_cast<GParamFlags>(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_METADATA, spec);
spec = g_param_spec_int("gpu-device",
"GPU device",
"The GPU device number. -1 means GPU isn't used.",
-1,
G_MAXINT,
-1,
static_cast<GParamFlags>(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_GPU_DEVICE, spec);
}
static bool
gplasma_object_check_not_released(GPlasmaObjectPrivate *priv,
GError **error,
const gchar *context)
{
if (priv->client) {
return true;
}
auto id_priv = GPLASMA_OBJECT_ID_GET_PRIVATE(priv->id);
auto id_hex = id_priv->id.hex();
g_set_error(error,
GARROW_ERROR,
GARROW_ERROR_INVALID,
"%s: Can't process released object: <%s>",
context,
id_hex.c_str());
return false;
}
static void
gplasma_object_release_resources(GPlasmaObjectPrivate *priv)
{
if (priv->client) {
g_object_unref(priv->client);
priv->client = nullptr;
}
if (priv->data) {
g_object_unref(priv->data);
priv->data = nullptr;
}
if (priv->metadata) {
g_object_unref(priv->metadata);
priv->metadata = nullptr;
}
}
G_DEFINE_TYPE(GPlasmaCreatedObject,
gplasma_created_object,
GPLASMA_TYPE_OBJECT)
static void
gplasma_created_object_dispose(GObject *object)
{
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
if (priv->client) {
gplasma_created_object_abort(GPLASMA_CREATED_OBJECT(object), NULL);
}
G_OBJECT_CLASS(gplasma_created_object_parent_class)->dispose(object);
}
static void
gplasma_created_object_init(GPlasmaCreatedObject *object)
{
}
static void
gplasma_created_object_class_init(GPlasmaCreatedObjectClass *klass)
{
auto gobject_class = G_OBJECT_CLASS(klass);
gobject_class->dispose = gplasma_created_object_dispose;
}
/**
* gplasma_created_object_seal:
* @object: A #GPlasmaCreatedObject.
* @error: (nullable): Return location for a #GError or %NULL.
*
* Seals the object in the object store. You can't use the sealed
* object anymore.
*
* Returns: %TRUE on success, %FALSE on error.
*
* Since: 0.12.0
*/
gboolean
gplasma_created_object_seal(GPlasmaCreatedObject *object,
GError **error)
{
const auto context = "[plasma][created-object][seal]";
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
if (!gplasma_object_check_not_released(priv, error, context)) {
return FALSE;
}
auto plasma_client = gplasma_client_get_raw(priv->client);
auto id_priv = GPLASMA_OBJECT_ID_GET_PRIVATE(priv->id);
auto status = plasma_client->Seal(id_priv->id);
auto success = garrow_error_check(error, status, context);
if (success) {
status = plasma_client->Release(id_priv->id);
success = garrow_error_check(error, status, context);
gplasma_object_release_resources(priv);
}
return success;
}
/**
* gplasma_created_object_abort:
* @object: A #GPlasmaCreatedObject.
* @error: (nullable): Return location for a #GError or %NULL.
*
* Aborts the object in the object store. You can't use the aborted
* object anymore.
*
* Returns: %TRUE on success, %FALSE on error.
*
* Since: 0.12.0
*/
gboolean
gplasma_created_object_abort(GPlasmaCreatedObject *object,
GError **error)
{
const auto context = "[plasma][created-object][abort]";
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
if (!gplasma_object_check_not_released(priv, error, context)) {
return FALSE;
}
auto plasma_client = gplasma_client_get_raw(priv->client);
auto id_priv = GPLASMA_OBJECT_ID_GET_PRIVATE(priv->id);
auto status = plasma_client->Release(id_priv->id);
auto success = garrow_error_check(error, status, context);
if (success) {
status = plasma_client->Abort(id_priv->id);
success = garrow_error_check(error, status, context);
gplasma_object_release_resources(priv);
}
return success;
}
G_DEFINE_TYPE(GPlasmaReferredObject,
gplasma_referred_object,
GPLASMA_TYPE_OBJECT)
static void
gplasma_referred_object_dispose(GObject *object)
{
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
gplasma_object_release_resources(priv);
G_OBJECT_CLASS(gplasma_referred_object_parent_class)->dispose(object);
}
static void
gplasma_referred_object_init(GPlasmaReferredObject *object)
{
}
static void
gplasma_referred_object_class_init(GPlasmaReferredObjectClass *klass)
{
auto gobject_class = G_OBJECT_CLASS(klass);
gobject_class->dispose = gplasma_referred_object_dispose;
}
/**
* gplasma_referred_object_release:
* @object: A #GPlasmaReferredObject.
* @error: (nullable): Return location for a #GError or %NULL.
*
* Releases the object explicitly. The object is no longer valid.
*
* Returns: %TRUE on success, %FALSE on error.
*
* Since: 0.12.0
*/
gboolean
gplasma_referred_object_release(GPlasmaReferredObject *object,
GError **error)
{
const auto context = "[plasma][referred-object][release]";
auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
if (!gplasma_object_check_not_released(priv, error, context)) {
return FALSE;
}
gplasma_object_release_resources(priv);
return TRUE;
}
G_END_DECLS
plasma::ObjectID
gplasma_object_id_get_raw(GPlasmaObjectID *id)
{
auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(id);
return priv->id;
}
GPlasmaCreatedObject *
gplasma_created_object_new_raw(GPlasmaClient *client,
GPlasmaObjectID *id,
std::shared_ptr<arrow::Buffer> *raw_data,
GArrowBuffer *data,
std::shared_ptr<arrow::Buffer> *raw_metadata,
GArrowBuffer *metadata,
gint gpu_device)
{
auto object = g_object_new(GPLASMA_TYPE_CREATED_OBJECT,
"client", client,
"id", id,
"raw-data", raw_data,
"data", data,
"raw-metadata", raw_metadata,
"metadata", metadata,
"gpu-device", gpu_device,
NULL);
return GPLASMA_CREATED_OBJECT(object);
}
GPlasmaReferredObject *
gplasma_referred_object_new_raw(GPlasmaClient *client,
GPlasmaObjectID *id,
std::shared_ptr<arrow::Buffer> *raw_data,
GArrowBuffer *data,
std::shared_ptr<arrow::Buffer> *raw_metadata,
GArrowBuffer *metadata,
gint gpu_device)
{
auto object = g_object_new(GPLASMA_TYPE_REFERRED_OBJECT,
"client", client,
"id", id,
"raw-data", raw_data,
"data", data,
"raw-metadata", raw_metadata,
"metadata", metadata,
"gpu-device", gpu_device,
NULL);
return GPLASMA_REFERRED_OBJECT(object);
}