1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <arrow-glib/error.hpp>
21
22 #include <plasma-glib/client.hpp>
23 #include <plasma-glib/object.hpp>
24
25 G_BEGIN_DECLS
26
27 /**
28 * SECTION: object
29 * @section_id: object-classes
30 * @title: Object related classes
31 * @include: plasma-glib/plasma-glib.h
32 *
33 * #GPlasmaObjectID is a class for an object ID.
34 *
35 * #GPlasmaObject is a base class for an object stored in plasma store.
36 *
37 * #GPlasmaCreatedObject is a class for a created object. You can
38 * change data of the object until the object is sealed or aborted.
39 *
40 * #GPlasmaReferredObject is a class for a created object. You can
41 * only refer the data and metadata of the object. You can't change
42 * the data of the object.
43 *
44 * Since: 0.12.0
45 */
46
47 typedef struct GPlasmaObjectIDPrivate_ {
48 plasma::ObjectID id;
49 } GPlasmaObjectIDPrivate;
50
G_DEFINE_TYPE_WITH_PRIVATE(GPlasmaObjectID,gplasma_object_id,G_TYPE_OBJECT)51 G_DEFINE_TYPE_WITH_PRIVATE(GPlasmaObjectID,
52 gplasma_object_id,
53 G_TYPE_OBJECT)
54
55 #define GPLASMA_OBJECT_ID_GET_PRIVATE(object) \
56 static_cast<GPlasmaObjectIDPrivate *>( \
57 gplasma_object_id_get_instance_private( \
58 GPLASMA_OBJECT_ID(object)))
59
60 static void
61 gplasma_object_id_init(GPlasmaObjectID *object)
62 {
63 }
64
65 static void
gplasma_object_id_class_init(GPlasmaObjectIDClass * klass)66 gplasma_object_id_class_init(GPlasmaObjectIDClass *klass)
67 {
68 }
69
70 /**
71 * gplasma_object_id_new:
72 * @id: (array length=size): The raw ID bytes.
73 * @size: The number of bytes of the ID. It must be 1..20.
74 * @error: (nullable): Return location for a #GError or %NULL.
75 *
76 * Returns: (nullable): A newly created #GPlasmaObjectID on success,
77 * %NULL on error.
78 *
79 * Since: 0.12.0
80 */
81 GPlasmaObjectID *
gplasma_object_id_new(const guint8 * id,gsize size,GError ** error)82 gplasma_object_id_new(const guint8 *id,
83 gsize size,
84 GError **error)
85 {
86 if (size == 0 || size > plasma::kUniqueIDSize) {
87 g_set_error(error,
88 GARROW_ERROR,
89 GARROW_ERROR_INVALID,
90 "[plasma][object-id][new] "
91 "ID must be 1..20 bytes: <%" G_GSIZE_FORMAT ">",
92 size);
93 return NULL;
94 }
95
96 auto object_id = g_object_new(GPLASMA_TYPE_OBJECT_ID, NULL);
97 auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(object_id);
98 memcpy(priv->id.mutable_data(), id, size);
99 if (size != plasma::kUniqueIDSize) {
100 memset(priv->id.mutable_data() + size, 0, plasma::kUniqueIDSize - size);
101 }
102 return GPLASMA_OBJECT_ID(object_id);
103 }
104
105 /**
106 * gplasma_object_id_to_binary:
107 * @id: A #GPlasmaObjectID.
108 * @size: (nullable) (out): The number of bytes of the byte string of
109 * the object ID. It's always 20. 20 is `plasma::kUniqueIDSize`.
110 *
111 * Returns: (array length=size): The byte string of the object ID.
112 *
113 * Since: 0.12.0
114 */
115 const guint8 *
gplasma_object_id_to_binary(GPlasmaObjectID * id,gsize * size)116 gplasma_object_id_to_binary(GPlasmaObjectID *id,
117 gsize *size)
118 {
119 auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(id);
120 if (size) {
121 *size = plasma::kUniqueIDSize;
122 }
123 return priv->id.data();
124 }
125
126 /**
127 * gplasma_object_id_to_hex:
128 * @id: A #GPlasmaObjectID.
129 *
130 * Returns: (transfer full): The hex representation of the object ID.
131 *
132 * It should be freed with g_free() when no longer needed.
133 *
134 * Since: 0.12.0
135 */
136 gchar *
gplasma_object_id_to_hex(GPlasmaObjectID * id)137 gplasma_object_id_to_hex(GPlasmaObjectID *id)
138 {
139 auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(id);
140 return g_strdup(priv->id.hex().c_str());
141 }
142
143 typedef struct GPlasmaObjectPrivate_ {
144 GPlasmaClient *client;
145 GPlasmaObjectID *id;
146 std::shared_ptr<arrow::Buffer> raw_data;
147 GArrowBuffer *data;
148 std::shared_ptr<arrow::Buffer> raw_metadata;
149 GArrowBuffer *metadata;
150 gint gpu_device;
151 } GPlasmaObjectPrivate;
152
153 enum {
154 PROP_CLIENT = 1,
155 PROP_ID,
156 PROP_RAW_DATA,
157 PROP_DATA,
158 PROP_RAW_METADATA,
159 PROP_METADATA,
160 PROP_GPU_DEVICE
161 };
162
G_DEFINE_TYPE_WITH_PRIVATE(GPlasmaObject,gplasma_object,G_TYPE_OBJECT)163 G_DEFINE_TYPE_WITH_PRIVATE(GPlasmaObject,
164 gplasma_object,
165 G_TYPE_OBJECT)
166
167 #define GPLASMA_OBJECT_GET_PRIVATE(object) \
168 static_cast<GPlasmaObjectPrivate *>( \
169 gplasma_object_get_instance_private( \
170 GPLASMA_OBJECT(object)))
171
172 static void
173 gplasma_object_dispose(GObject *object)
174 {
175 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
176
177 // Properties except priv->id must be disposed in subclass.
178
179 if (priv->id) {
180 g_object_unref(priv->id);
181 priv->id = nullptr;
182 }
183
184 G_OBJECT_CLASS(gplasma_object_parent_class)->dispose(object);
185 }
186
187 static void
gplasma_object_finalize(GObject * object)188 gplasma_object_finalize(GObject *object)
189 {
190 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
191
192 priv->raw_data.~shared_ptr();
193 priv->raw_metadata.~shared_ptr();
194
195 G_OBJECT_CLASS(gplasma_object_parent_class)->finalize(object);
196 }
197
198 static void
gplasma_object_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)199 gplasma_object_set_property(GObject *object,
200 guint prop_id,
201 const GValue *value,
202 GParamSpec *pspec)
203 {
204 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
205
206 switch (prop_id) {
207 case PROP_CLIENT:
208 priv->client = GPLASMA_CLIENT(g_value_dup_object(value));
209 break;
210 case PROP_ID:
211 priv->id = GPLASMA_OBJECT_ID(g_value_dup_object(value));
212 break;
213 case PROP_RAW_DATA:
214 priv->raw_data =
215 *static_cast<std::shared_ptr<arrow::Buffer> *>(g_value_get_pointer(value));
216 break;
217 case PROP_DATA:
218 priv->data = GARROW_BUFFER(g_value_dup_object(value));
219 break;
220 case PROP_RAW_METADATA:
221 {
222 auto raw_metadata =
223 static_cast<std::shared_ptr<arrow::Buffer> *>(g_value_get_pointer(value));
224 if (raw_metadata) {
225 priv->raw_metadata = *raw_metadata;
226 } else {
227 priv->raw_metadata = nullptr;
228 }
229 }
230 break;
231 case PROP_METADATA:
232 priv->metadata = GARROW_BUFFER(g_value_dup_object(value));
233 break;
234 case PROP_GPU_DEVICE:
235 priv->gpu_device = g_value_get_int(value);
236 break;
237 default:
238 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
239 break;
240 }
241 }
242
243 static void
gplasma_object_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)244 gplasma_object_get_property(GObject *object,
245 guint prop_id,
246 GValue *value,
247 GParamSpec *pspec)
248 {
249 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
250
251 switch (prop_id) {
252 case PROP_CLIENT:
253 g_value_set_object(value, priv->client);
254 break;
255 case PROP_ID:
256 g_value_set_object(value, priv->id);
257 break;
258 case PROP_DATA:
259 g_value_set_object(value, priv->data);
260 break;
261 case PROP_METADATA:
262 g_value_set_object(value, priv->metadata);
263 break;
264 case PROP_GPU_DEVICE:
265 g_value_set_int(value, priv->gpu_device);
266 break;
267 default:
268 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
269 break;
270 }
271 }
272
273 static void
gplasma_object_init(GPlasmaObject * object)274 gplasma_object_init(GPlasmaObject *object)
275 {
276 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
277 new(&priv->raw_data) std::shared_ptr<arrow::Buffer>;
278 new(&priv->raw_metadata) std::shared_ptr<arrow::Buffer>;
279 }
280
281 static void
gplasma_object_class_init(GPlasmaObjectClass * klass)282 gplasma_object_class_init(GPlasmaObjectClass *klass)
283 {
284 auto gobject_class = G_OBJECT_CLASS(klass);
285
286 gobject_class->dispose = gplasma_object_dispose;
287 gobject_class->finalize = gplasma_object_finalize;
288 gobject_class->set_property = gplasma_object_set_property;
289 gobject_class->get_property = gplasma_object_get_property;
290
291 GParamSpec *spec;
292 spec = g_param_spec_object("client",
293 "Client",
294 "The client",
295 GPLASMA_TYPE_CLIENT,
296 static_cast<GParamFlags>(G_PARAM_READWRITE |
297 G_PARAM_CONSTRUCT_ONLY));
298 g_object_class_install_property(gobject_class, PROP_CLIENT, spec);
299
300 spec = g_param_spec_object("id",
301 "ID",
302 "The ID of this object",
303 GPLASMA_TYPE_OBJECT_ID,
304 static_cast<GParamFlags>(G_PARAM_READWRITE |
305 G_PARAM_CONSTRUCT_ONLY));
306 g_object_class_install_property(gobject_class, PROP_ID, spec);
307
308 spec = g_param_spec_pointer("raw-data",
309 "Raw data",
310 "The raw data of this object",
311 static_cast<GParamFlags>(G_PARAM_WRITABLE |
312 G_PARAM_CONSTRUCT_ONLY));
313 g_object_class_install_property(gobject_class, PROP_RAW_DATA, spec);
314
315 spec = g_param_spec_object("data",
316 "Data",
317 "The data of this object",
318 GARROW_TYPE_BUFFER,
319 static_cast<GParamFlags>(G_PARAM_READWRITE |
320 G_PARAM_CONSTRUCT_ONLY));
321 g_object_class_install_property(gobject_class, PROP_DATA, spec);
322
323 spec = g_param_spec_pointer("raw-metadata",
324 "Raw metadata",
325 "The raw metadata of this object",
326 static_cast<GParamFlags>(G_PARAM_WRITABLE |
327 G_PARAM_CONSTRUCT_ONLY));
328 g_object_class_install_property(gobject_class, PROP_RAW_METADATA, spec);
329
330 spec = g_param_spec_object("metadata",
331 "Metadata",
332 "The metadata of this object",
333 GARROW_TYPE_BUFFER,
334 static_cast<GParamFlags>(G_PARAM_READWRITE |
335 G_PARAM_CONSTRUCT_ONLY));
336 g_object_class_install_property(gobject_class, PROP_METADATA, spec);
337
338 spec = g_param_spec_int("gpu-device",
339 "GPU device",
340 "The GPU device number. -1 means GPU isn't used.",
341 -1,
342 G_MAXINT,
343 -1,
344 static_cast<GParamFlags>(G_PARAM_READWRITE |
345 G_PARAM_CONSTRUCT_ONLY));
346 g_object_class_install_property(gobject_class, PROP_GPU_DEVICE, spec);
347 }
348
349 static bool
gplasma_object_check_not_released(GPlasmaObjectPrivate * priv,GError ** error,const gchar * context)350 gplasma_object_check_not_released(GPlasmaObjectPrivate *priv,
351 GError **error,
352 const gchar *context)
353 {
354 if (priv->client) {
355 return true;
356 }
357
358 auto id_priv = GPLASMA_OBJECT_ID_GET_PRIVATE(priv->id);
359 auto id_hex = id_priv->id.hex();
360 g_set_error(error,
361 GARROW_ERROR,
362 GARROW_ERROR_INVALID,
363 "%s: Can't process released object: <%s>",
364 context,
365 id_hex.c_str());
366 return false;
367 }
368
369 static void
gplasma_object_release_resources(GPlasmaObjectPrivate * priv)370 gplasma_object_release_resources(GPlasmaObjectPrivate *priv)
371 {
372 if (priv->client) {
373 g_object_unref(priv->client);
374 priv->client = nullptr;
375 }
376
377 if (priv->data) {
378 g_object_unref(priv->data);
379 priv->data = nullptr;
380 }
381
382 if (priv->metadata) {
383 g_object_unref(priv->metadata);
384 priv->metadata = nullptr;
385 }
386 }
387
G_DEFINE_TYPE(GPlasmaCreatedObject,gplasma_created_object,GPLASMA_TYPE_OBJECT)388 G_DEFINE_TYPE(GPlasmaCreatedObject,
389 gplasma_created_object,
390 GPLASMA_TYPE_OBJECT)
391
392 static void
393 gplasma_created_object_dispose(GObject *object)
394 {
395 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
396
397 if (priv->client) {
398 gplasma_created_object_abort(GPLASMA_CREATED_OBJECT(object), NULL);
399 }
400
401 G_OBJECT_CLASS(gplasma_created_object_parent_class)->dispose(object);
402 }
403
404 static void
gplasma_created_object_init(GPlasmaCreatedObject * object)405 gplasma_created_object_init(GPlasmaCreatedObject *object)
406 {
407 }
408
409 static void
gplasma_created_object_class_init(GPlasmaCreatedObjectClass * klass)410 gplasma_created_object_class_init(GPlasmaCreatedObjectClass *klass)
411 {
412 auto gobject_class = G_OBJECT_CLASS(klass);
413
414 gobject_class->dispose = gplasma_created_object_dispose;
415 }
416
417 /**
418 * gplasma_created_object_seal:
419 * @object: A #GPlasmaCreatedObject.
420 * @error: (nullable): Return location for a #GError or %NULL.
421 *
422 * Seals the object in the object store. You can't use the sealed
423 * object anymore.
424 *
425 * Returns: %TRUE on success, %FALSE on error.
426 *
427 * Since: 0.12.0
428 */
429 gboolean
gplasma_created_object_seal(GPlasmaCreatedObject * object,GError ** error)430 gplasma_created_object_seal(GPlasmaCreatedObject *object,
431 GError **error)
432 {
433 const auto context = "[plasma][created-object][seal]";
434
435 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
436 if (!gplasma_object_check_not_released(priv, error, context)) {
437 return FALSE;
438 }
439
440 auto plasma_client = gplasma_client_get_raw(priv->client);
441 auto id_priv = GPLASMA_OBJECT_ID_GET_PRIVATE(priv->id);
442 auto status = plasma_client->Seal(id_priv->id);
443 auto success = garrow_error_check(error, status, context);
444 if (success) {
445 status = plasma_client->Release(id_priv->id);
446 success = garrow_error_check(error, status, context);
447 gplasma_object_release_resources(priv);
448 }
449 return success;
450 }
451
452 /**
453 * gplasma_created_object_abort:
454 * @object: A #GPlasmaCreatedObject.
455 * @error: (nullable): Return location for a #GError or %NULL.
456 *
457 * Aborts the object in the object store. You can't use the aborted
458 * object anymore.
459 *
460 * Returns: %TRUE on success, %FALSE on error.
461 *
462 * Since: 0.12.0
463 */
464 gboolean
gplasma_created_object_abort(GPlasmaCreatedObject * object,GError ** error)465 gplasma_created_object_abort(GPlasmaCreatedObject *object,
466 GError **error)
467 {
468 const auto context = "[plasma][created-object][abort]";
469
470 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
471 if (!gplasma_object_check_not_released(priv, error, context)) {
472 return FALSE;
473 }
474
475 auto plasma_client = gplasma_client_get_raw(priv->client);
476 auto id_priv = GPLASMA_OBJECT_ID_GET_PRIVATE(priv->id);
477 auto status = plasma_client->Release(id_priv->id);
478 auto success = garrow_error_check(error, status, context);
479 if (success) {
480 status = plasma_client->Abort(id_priv->id);
481 success = garrow_error_check(error, status, context);
482 gplasma_object_release_resources(priv);
483 }
484 return success;
485 }
486
487
G_DEFINE_TYPE(GPlasmaReferredObject,gplasma_referred_object,GPLASMA_TYPE_OBJECT)488 G_DEFINE_TYPE(GPlasmaReferredObject,
489 gplasma_referred_object,
490 GPLASMA_TYPE_OBJECT)
491
492 static void
493 gplasma_referred_object_dispose(GObject *object)
494 {
495 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
496
497 gplasma_object_release_resources(priv);
498
499 G_OBJECT_CLASS(gplasma_referred_object_parent_class)->dispose(object);
500 }
501
502 static void
gplasma_referred_object_init(GPlasmaReferredObject * object)503 gplasma_referred_object_init(GPlasmaReferredObject *object)
504 {
505 }
506
507 static void
gplasma_referred_object_class_init(GPlasmaReferredObjectClass * klass)508 gplasma_referred_object_class_init(GPlasmaReferredObjectClass *klass)
509 {
510 auto gobject_class = G_OBJECT_CLASS(klass);
511
512 gobject_class->dispose = gplasma_referred_object_dispose;
513 }
514
515 /**
516 * gplasma_referred_object_release:
517 * @object: A #GPlasmaReferredObject.
518 * @error: (nullable): Return location for a #GError or %NULL.
519 *
520 * Releases the object explicitly. The object is no longer valid.
521 *
522 * Returns: %TRUE on success, %FALSE on error.
523 *
524 * Since: 0.12.0
525 */
526 gboolean
gplasma_referred_object_release(GPlasmaReferredObject * object,GError ** error)527 gplasma_referred_object_release(GPlasmaReferredObject *object,
528 GError **error)
529 {
530 const auto context = "[plasma][referred-object][release]";
531
532 auto priv = GPLASMA_OBJECT_GET_PRIVATE(object);
533 if (!gplasma_object_check_not_released(priv, error, context)) {
534 return FALSE;
535 }
536
537 gplasma_object_release_resources(priv);
538 return TRUE;
539 }
540
541 G_END_DECLS
542
543 plasma::ObjectID
gplasma_object_id_get_raw(GPlasmaObjectID * id)544 gplasma_object_id_get_raw(GPlasmaObjectID *id)
545 {
546 auto priv = GPLASMA_OBJECT_ID_GET_PRIVATE(id);
547 return priv->id;
548 }
549
550 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)551 gplasma_created_object_new_raw(GPlasmaClient *client,
552 GPlasmaObjectID *id,
553 std::shared_ptr<arrow::Buffer> *raw_data,
554 GArrowBuffer *data,
555 std::shared_ptr<arrow::Buffer> *raw_metadata,
556 GArrowBuffer *metadata,
557 gint gpu_device)
558 {
559 auto object = g_object_new(GPLASMA_TYPE_CREATED_OBJECT,
560 "client", client,
561 "id", id,
562 "raw-data", raw_data,
563 "data", data,
564 "raw-metadata", raw_metadata,
565 "metadata", metadata,
566 "gpu-device", gpu_device,
567 NULL);
568 return GPLASMA_CREATED_OBJECT(object);
569 }
570
571 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)572 gplasma_referred_object_new_raw(GPlasmaClient *client,
573 GPlasmaObjectID *id,
574 std::shared_ptr<arrow::Buffer> *raw_data,
575 GArrowBuffer *data,
576 std::shared_ptr<arrow::Buffer> *raw_metadata,
577 GArrowBuffer *metadata,
578 gint gpu_device)
579 {
580 auto object = g_object_new(GPLASMA_TYPE_REFERRED_OBJECT,
581 "client", client,
582 "id", id,
583 "raw-data", raw_data,
584 "data", data,
585 "raw-metadata", raw_metadata,
586 "metadata", metadata,
587 "gpu-device", gpu_device,
588 NULL);
589 return GPLASMA_REFERRED_OBJECT(object);
590 }
591