Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL TileDB Driver
4 : * Purpose: Implement GDAL TileDB multidimensional support based on https://www.tiledb.io
5 : * Author: TileDB, Inc
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, TileDB, Inc
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef TILEDBMULTIDIM_H_INCLUDED
14 : #define TILEDBMULTIDIM_H_INCLUDED
15 :
16 : #include "tiledbheaders.h"
17 :
18 : #include <set>
19 :
20 : constexpr const char *CRS_ATTRIBUTE_NAME = "_CRS";
21 : constexpr const char *UNIT_ATTRIBUTE_NAME = "_UNIT";
22 : constexpr const char *DIM_TYPE_ATTRIBUTE_NAME = "_DIM_TYPE";
23 : constexpr const char *DIM_DIRECTION_ATTRIBUTE_NAME = "_DIM_DIRECTION";
24 :
25 : /************************************************************************/
26 : /* TileDBSharedResource */
27 : /************************************************************************/
28 :
29 : class TileDBSharedResource
30 : {
31 : std::unique_ptr<tiledb::Context> m_ctx{};
32 : bool m_bUpdatable = false;
33 : bool m_bStats = false;
34 : uint64_t m_nTimestamp = 0;
35 :
36 : public:
37 55 : TileDBSharedResource(std::unique_ptr<tiledb::Context> &&ctx,
38 : bool bUpdatable)
39 55 : : m_ctx(std::move(ctx)), m_bUpdatable(bUpdatable)
40 : {
41 55 : }
42 :
43 106 : inline bool IsUpdatable() const
44 : {
45 106 : return m_bUpdatable;
46 : }
47 :
48 518 : inline tiledb::Context &GetCtx() const
49 : {
50 518 : return *(m_ctx.get());
51 : }
52 :
53 : static std::string SanitizeNameForPath(const std::string &osName);
54 :
55 55 : void SetDumpStats(bool b)
56 : {
57 55 : m_bStats = b;
58 55 : }
59 :
60 75 : bool GetDumpStats() const
61 : {
62 75 : return m_bStats;
63 : }
64 :
65 0 : void SetTimestamp(uint64_t t)
66 : {
67 0 : m_nTimestamp = t;
68 0 : }
69 :
70 75 : uint64_t GetTimestamp() const
71 : {
72 75 : return m_nTimestamp;
73 : }
74 : };
75 :
76 : /************************************************************************/
77 : /* TileDBAttributeHolder */
78 : /************************************************************************/
79 :
80 137 : class TileDBAttributeHolder
81 : {
82 : private:
83 : mutable std::map<std::string, std::shared_ptr<GDALAttribute>>
84 : m_oMapAttributes{};
85 :
86 : virtual uint64_t metadata_num() const = 0;
87 : virtual void get_metadata_from_index(uint64_t index, std::string *key,
88 : tiledb_datatype_t *value_type,
89 : uint32_t *value_num,
90 : const void **value) const = 0;
91 : virtual bool has_metadata(const std::string &key,
92 : tiledb_datatype_t *value_type) const = 0;
93 : virtual void get_metadata(const std::string &key,
94 : tiledb_datatype_t *value_type,
95 : uint32_t *value_num,
96 : const void **value) const = 0;
97 : virtual void put_metadata(const std::string &key,
98 : tiledb_datatype_t value_type, uint32_t value_num,
99 : const void *value) = 0;
100 : virtual void delete_metadata(const std::string &key) = 0;
101 :
102 : virtual bool EnsureOpenAs(tiledb_query_type_t mode) const = 0;
103 : virtual std::shared_ptr<TileDBAttributeHolder>
104 : AsAttributeHolderSharedPtr() const = 0;
105 :
106 : static std::shared_ptr<GDALAttribute>
107 : CreateAttribute(const std::shared_ptr<TileDBAttributeHolder> &poSelf,
108 : const std::string &osName, tiledb_datatype_t value_type,
109 : uint32_t value_num, const void *value);
110 :
111 : public:
112 : virtual ~TileDBAttributeHolder() = 0;
113 :
114 : virtual bool IIsWritable() const = 0;
115 : virtual const std::string &IGetFullName() const = 0;
116 :
117 : std::shared_ptr<GDALAttribute>
118 : CreateAttributeImpl(const std::string &osName,
119 : const std::vector<GUInt64> &anDimensions,
120 : const GDALExtendedDataType &oDataType,
121 : CSLConstList papszOptions = nullptr);
122 :
123 : std::shared_ptr<GDALAttribute>
124 : GetAttributeImpl(const std::string &osName) const;
125 :
126 : std::vector<std::shared_ptr<GDALAttribute>>
127 : GetAttributesImpl(CSLConstList papszOptions = nullptr) const;
128 :
129 : bool DeleteAttributeImpl(const std::string &osName,
130 : CSLConstList papszOptions = nullptr);
131 :
132 : bool GetMetadata(const std::string &key, tiledb_datatype_t *value_type,
133 : uint32_t *value_num, const void **value) const;
134 : bool PutMetadata(const std::string &key, tiledb_datatype_t value_type,
135 : uint32_t value_num, const void *value);
136 : };
137 :
138 : /************************************************************************/
139 : /* TileDBGroup */
140 : /************************************************************************/
141 :
142 : class TileDBArray;
143 :
144 : class TileDBGroup final : public GDALGroup, public TileDBAttributeHolder
145 : {
146 : std::shared_ptr<TileDBSharedResource> m_poSharedResource{};
147 : const std::string m_osPath;
148 : mutable std::unique_ptr<tiledb::Group> m_poTileDBGroup{};
149 : mutable std::map<std::string, std::shared_ptr<TileDBGroup>> m_oMapGroups{};
150 : mutable std::map<std::string, std::shared_ptr<TileDBArray>> m_oMapArrays{};
151 : mutable std::map<std::string, std::shared_ptr<GDALDimension>>
152 : m_oMapDimensions{};
153 :
154 : //! To prevent OpenMDArray() to indefinitely recursing
155 : mutable std::set<std::string> m_oSetArrayInOpening{};
156 :
157 62 : TileDBGroup(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
158 : const std::string &osParentName, const std::string &osName,
159 : const std::string &osPath)
160 62 : : GDALGroup(osParentName, osName), m_poSharedResource(poSharedResource),
161 62 : m_osPath(osPath)
162 : {
163 62 : }
164 :
165 : static std::shared_ptr<TileDBGroup>
166 62 : Create(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
167 : const std::string &osParentName, const std::string &osName,
168 : const std::string &osPath)
169 : {
170 : auto poGroup = std::shared_ptr<TileDBGroup>(
171 62 : new TileDBGroup(poSharedResource, osParentName, osName, osPath));
172 62 : poGroup->SetSelf(poGroup);
173 62 : return poGroup;
174 : }
175 :
176 : bool HasObjectOfSameName(const std::string &osName) const;
177 :
178 : protected:
179 : // BEGIN: interfaces of TileDBAttributeHolder
180 :
181 : bool EnsureOpenAs(tiledb_query_type_t mode) const override;
182 :
183 4 : uint64_t metadata_num() const override
184 : {
185 4 : return m_poTileDBGroup->metadata_num();
186 : }
187 :
188 3 : void get_metadata_from_index(uint64_t index, std::string *key,
189 : tiledb_datatype_t *value_type,
190 : uint32_t *value_num,
191 : const void **value) const override
192 : {
193 3 : m_poTileDBGroup->get_metadata_from_index(index, key, value_type,
194 : value_num, value);
195 3 : }
196 :
197 4 : bool has_metadata(const std::string &key,
198 : tiledb_datatype_t *value_type) const override
199 : {
200 4 : return m_poTileDBGroup->has_metadata(key, value_type);
201 : }
202 :
203 4 : void get_metadata(const std::string &key, tiledb_datatype_t *value_type,
204 : uint32_t *value_num, const void **value) const override
205 : {
206 4 : m_poTileDBGroup->get_metadata(key, value_type, value_num, value);
207 4 : }
208 :
209 3 : void put_metadata(const std::string &key, tiledb_datatype_t value_type,
210 : uint32_t value_num, const void *value) override
211 : {
212 3 : m_poTileDBGroup->put_metadata(key, value_type, value_num, value);
213 3 : }
214 :
215 2 : void delete_metadata(const std::string &key) override
216 : {
217 2 : m_poTileDBGroup->delete_metadata(key);
218 2 : }
219 :
220 : std::shared_ptr<TileDBAttributeHolder>
221 8 : AsAttributeHolderSharedPtr() const override
222 : {
223 8 : return std::dynamic_pointer_cast<TileDBAttributeHolder>(m_pSelf.lock());
224 : }
225 :
226 12 : bool IIsWritable() const override
227 : {
228 12 : return m_poSharedResource->IsUpdatable();
229 : }
230 :
231 14 : const std::string &IGetFullName() const override
232 : {
233 14 : return GetFullName();
234 : }
235 :
236 : // END: interfaces of TileDBAttributeHolder
237 :
238 : public:
239 : ~TileDBGroup() override;
240 :
241 : static std::shared_ptr<TileDBGroup>
242 : CreateOnDisk(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
243 : const std::string &osParentName, const std::string &osName,
244 : const std::string &osPath);
245 :
246 : static std::shared_ptr<TileDBGroup>
247 : OpenFromDisk(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
248 : const std::string &osParentName, const std::string &osName,
249 : const std::string &osPath);
250 :
251 61 : const std::string &GetPath() const
252 : {
253 61 : return m_osPath;
254 : }
255 :
256 : std::vector<std::string>
257 : GetMDArrayNames(CSLConstList papszOptions = nullptr) const override;
258 :
259 : std::vector<std::string>
260 : GetGroupNames(CSLConstList papszOptions = nullptr) const override;
261 :
262 : std::shared_ptr<GDALDimension>
263 : CreateDimension(const std::string &osName, const std::string &osType,
264 : const std::string &osDirection, GUInt64 nSize,
265 : CSLConstList) override;
266 :
267 : std::shared_ptr<GDALGroup>
268 : CreateGroup(const std::string &osName,
269 : CSLConstList papszOptions = nullptr) override;
270 :
271 : std::shared_ptr<GDALGroup>
272 : OpenGroup(const std::string &osName,
273 : CSLConstList papszOptions = nullptr) const override;
274 :
275 : std::shared_ptr<GDALMDArray> CreateMDArray(
276 : const std::string &osName,
277 : const std::vector<std::shared_ptr<GDALDimension>> &aoDimensions,
278 : const GDALExtendedDataType &oDataType,
279 : CSLConstList papszOptions = nullptr) override;
280 :
281 : std::shared_ptr<GDALMDArray>
282 : OpenMDArray(const std::string &osName,
283 : CSLConstList papszOptions = nullptr) const override;
284 :
285 : bool AddMember(const std::string &osPath, const std::string &osName);
286 :
287 : std::shared_ptr<GDALAttribute>
288 : CreateAttribute(const std::string &osName,
289 : const std::vector<GUInt64> &anDimensions,
290 : const GDALExtendedDataType &oDataType,
291 : CSLConstList papszOptions = nullptr) override;
292 :
293 : std::shared_ptr<GDALAttribute>
294 : GetAttribute(const std::string &osName) const override;
295 :
296 : std::vector<std::shared_ptr<GDALAttribute>>
297 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
298 :
299 : bool DeleteAttribute(const std::string &osName,
300 : CSLConstList papszOptions = nullptr) override;
301 : };
302 :
303 : /************************************************************************/
304 : /* TileDBArray */
305 : /************************************************************************/
306 :
307 : class TileDBArray final : public GDALMDArray, public TileDBAttributeHolder
308 : {
309 : std::shared_ptr<TileDBSharedResource> m_poSharedResource{};
310 : const std::vector<std::shared_ptr<GDALDimension>> m_aoDims;
311 : const GDALExtendedDataType m_oType;
312 : const std::string m_osPath;
313 : std::vector<GUInt64> m_anBlockSize{};
314 : // Starting offset of each dimension (if not zero)
315 : std::vector<uint64_t> m_anStartDimOffset{};
316 : mutable bool m_bFinalized = true;
317 : mutable std::unique_ptr<tiledb::ArraySchema> m_poSchema{};
318 :
319 : std::string m_osAttrName{}; // (TileDB) attribute name
320 : mutable std::unique_ptr<tiledb::Attribute> m_poAttr{};
321 : mutable std::unique_ptr<tiledb::Array> m_poTileDBArray{};
322 : mutable std::vector<GByte> m_abyNoData{};
323 : std::shared_ptr<OGRSpatialReference> m_poSRS{};
324 : std::string m_osUnit{};
325 : bool m_bStats = false;
326 :
327 : // inclusive ending timestamp when opening this array
328 : uint64_t m_nTimestamp = 0;
329 :
330 : std::weak_ptr<TileDBGroup> m_poParent{}; // used for creation path
331 : std::string m_osParentPath{}; // used for creation path
332 : // used for creation path.
333 : // To keep a reference on the indexing variables in CreateOnDisk(),
334 : // so they are still alive at Finalize() time
335 : std::vector<std::shared_ptr<GDALMDArray>> m_apoIndexingVariables{};
336 :
337 : CPLStringList m_aosStructuralInfo{};
338 :
339 : TileDBArray(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
340 : const std::string &osParentName, const std::string &osName,
341 : const std::vector<std::shared_ptr<GDALDimension>> &aoDims,
342 : const GDALExtendedDataType &oType, const std::string &osPath);
343 :
344 : static std::shared_ptr<TileDBArray>
345 : Create(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
346 : const std::string &osParentName, const std::string &osName,
347 : const std::vector<std::shared_ptr<GDALDimension>> &aoDims,
348 : const GDALExtendedDataType &oType, const std::string &osPath);
349 :
350 : bool Finalize() const;
351 :
352 : protected:
353 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
354 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
355 : const GDALExtendedDataType &bufferDataType,
356 : void *pDstBuffer) const override;
357 :
358 : bool IWrite(const GUInt64 *arrayStartIdx, const size_t *count,
359 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
360 : const GDALExtendedDataType &bufferDataType,
361 : const void *pSrcBuffer) override;
362 :
363 : // BEGIN: interfaces of TileDBAttributeHolder
364 :
365 : bool EnsureOpenAs(tiledb_query_type_t mode) const override;
366 :
367 40 : uint64_t metadata_num() const override
368 : {
369 40 : return m_poTileDBArray->metadata_num();
370 : }
371 :
372 51 : void get_metadata_from_index(uint64_t index, std::string *key,
373 : tiledb_datatype_t *value_type,
374 : uint32_t *value_num,
375 : const void **value) const override
376 : {
377 51 : m_poTileDBArray->get_metadata_from_index(index, key, value_type,
378 : value_num, value);
379 51 : }
380 :
381 11 : bool has_metadata(const std::string &key,
382 : tiledb_datatype_t *value_type) const override
383 : {
384 11 : return m_poTileDBArray->has_metadata(key, value_type);
385 : }
386 :
387 64 : void get_metadata(const std::string &key, tiledb_datatype_t *value_type,
388 : uint32_t *value_num, const void **value) const override
389 : {
390 64 : m_poTileDBArray->get_metadata(key, value_type, value_num, value);
391 64 : }
392 :
393 10 : void put_metadata(const std::string &key, tiledb_datatype_t value_type,
394 : uint32_t value_num, const void *value) override
395 : {
396 10 : m_poTileDBArray->put_metadata(key, value_type, value_num, value);
397 10 : }
398 :
399 0 : void delete_metadata(const std::string &key) override
400 : {
401 0 : m_poTileDBArray->delete_metadata(key);
402 0 : }
403 :
404 : std::shared_ptr<TileDBAttributeHolder>
405 61 : AsAttributeHolderSharedPtr() const override
406 : {
407 61 : return std::dynamic_pointer_cast<TileDBAttributeHolder>(m_pSelf.lock());
408 : }
409 :
410 22 : bool IIsWritable() const override
411 : {
412 22 : return IsWritable();
413 : }
414 :
415 132 : const std::string &IGetFullName() const override
416 : {
417 132 : return GetFullName();
418 : }
419 :
420 : // END: interfaces of TileDBAttributeHolder
421 :
422 : public:
423 : ~TileDBArray() override;
424 :
425 : static std::shared_ptr<TileDBArray>
426 : OpenFromDisk(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
427 : const std::shared_ptr<GDALGroup> &poParent,
428 : const std::string &osParentName, const std::string &osName,
429 : const std::string &osAttributeName, const std::string &osPath,
430 : CSLConstList papszOptions);
431 :
432 : static std::shared_ptr<TileDBArray> CreateOnDisk(
433 : const std::shared_ptr<TileDBSharedResource> &poSharedResource,
434 : const std::shared_ptr<TileDBGroup> &poParent, const std::string &osName,
435 : const std::vector<std::shared_ptr<GDALDimension>> &aoDimensions,
436 : const GDALExtendedDataType &oDataType, CSLConstList papszOptions);
437 :
438 53 : bool IsWritable() const override
439 : {
440 53 : return m_poSharedResource->IsUpdatable();
441 : }
442 :
443 61 : const std::string &GetFilename() const override
444 : {
445 61 : return m_osPath;
446 : }
447 :
448 : const std::vector<std::shared_ptr<GDALDimension>> &
449 490 : GetDimensions() const override
450 : {
451 490 : return m_aoDims;
452 : }
453 :
454 369 : const GDALExtendedDataType &GetDataType() const override
455 : {
456 369 : return m_oType;
457 : }
458 :
459 15 : std::vector<GUInt64> GetBlockSize() const override
460 : {
461 15 : return m_anBlockSize;
462 : }
463 :
464 : const void *GetRawNoDataValue() const override;
465 :
466 : bool SetRawNoDataValue(const void *pRawNoData) override;
467 :
468 10 : std::shared_ptr<OGRSpatialReference> GetSpatialRef() const override
469 : {
470 10 : return m_poSRS;
471 : }
472 :
473 : bool SetSpatialRef(const OGRSpatialReference *poSRS) override;
474 :
475 7 : const std::string &GetUnit() const override
476 : {
477 7 : return m_osUnit;
478 : }
479 :
480 : bool SetUnit(const std::string &osUnit) override;
481 :
482 : CSLConstList GetStructuralInfo() const override;
483 :
484 : std::shared_ptr<GDALAttribute>
485 : CreateAttribute(const std::string &osName,
486 : const std::vector<GUInt64> &anDimensions,
487 : const GDALExtendedDataType &oDataType,
488 : CSLConstList papszOptions = nullptr) override;
489 :
490 : std::shared_ptr<GDALAttribute>
491 : GetAttribute(const std::string &osName) const override;
492 :
493 : std::vector<std::shared_ptr<GDALAttribute>>
494 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
495 :
496 : bool DeleteAttribute(const std::string &osName,
497 : CSLConstList papszOptions = nullptr) override;
498 : static GDALDataType
499 : TileDBDataTypeToGDALDataType(tiledb_datatype_t tiledb_dt);
500 :
501 : static bool GDALDataTypeToTileDB(GDALDataType dt,
502 : tiledb_datatype_t &tiledb_dt);
503 : };
504 :
505 : /************************************************************************/
506 : /* TileDBAttribute */
507 : /************************************************************************/
508 :
509 : // Caution: TileDBAttribute implements a GDAL multidim attribute, which
510 : // in TileDB terminology maps to a TileDB metadata item.
511 : class TileDBAttribute final : public GDALAttribute
512 : {
513 : std::shared_ptr<GDALAttribute> m_poMemAttribute;
514 : std::weak_ptr<TileDBAttributeHolder> m_poParent;
515 :
516 : TileDBAttribute(const std::string &osParentName, const std::string &osName);
517 :
518 : protected:
519 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
520 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
521 : const GDALExtendedDataType &bufferDataType,
522 : void *pDstBuffer) const override;
523 :
524 : bool IWrite(const GUInt64 *arrayStartIdx, const size_t *count,
525 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
526 : const GDALExtendedDataType &bufferDataType,
527 : const void *pSrcBuffer) override;
528 :
529 : const std::vector<std::shared_ptr<GDALDimension>> &
530 150 : GetDimensions() const override
531 : {
532 150 : return m_poMemAttribute->GetDimensions();
533 : }
534 :
535 213 : const GDALExtendedDataType &GetDataType() const override
536 : {
537 213 : return m_poMemAttribute->GetDataType();
538 : }
539 :
540 : public:
541 : static std::shared_ptr<GDALAttribute>
542 : Create(const std::shared_ptr<TileDBAttributeHolder> &poParent,
543 : const std::string &osName, const std::vector<GUInt64> &anDimensions,
544 : const GDALExtendedDataType &oDataType);
545 : };
546 :
547 : /************************************************************************/
548 : /* TileDBDimension */
549 : /************************************************************************/
550 :
551 : class TileDBDimension final : public GDALDimension
552 : {
553 : // OK as a shared_ptr rather a weak_ptr, given that for the use we make
554 : // of it, m_poIndexingVariable doesn't point to a TileDBDimension
555 : std::shared_ptr<GDALMDArray> m_poIndexingVariable{};
556 :
557 : public:
558 77 : TileDBDimension(const std::string &osParentName, const std::string &osName,
559 : const std::string &osType, const std::string &osDirection,
560 : GUInt64 nSize)
561 77 : : GDALDimension(osParentName, osName, osType, osDirection, nSize)
562 : {
563 77 : }
564 :
565 29 : std::shared_ptr<GDALMDArray> GetIndexingVariable() const override
566 : {
567 29 : return m_poIndexingVariable;
568 : }
569 :
570 18 : void SetIndexingVariableOneTime(
571 : const std::shared_ptr<GDALMDArray> &poIndexingVariable)
572 : {
573 18 : m_poIndexingVariable = poIndexingVariable;
574 18 : }
575 : };
576 :
577 : /************************************************************************/
578 : /* TileDBArrayGroup */
579 : /************************************************************************/
580 :
581 : class TileDBArrayGroup final : public GDALGroup
582 : {
583 : std::vector<std::shared_ptr<GDALMDArray>> m_apoArrays;
584 :
585 : public:
586 1 : explicit TileDBArrayGroup(
587 : const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays)
588 1 : : GDALGroup(std::string(), "/"), m_apoArrays(apoArrays)
589 : {
590 1 : }
591 :
592 : static std::shared_ptr<GDALGroup>
593 : Create(const std::shared_ptr<TileDBSharedResource> &poSharedResource,
594 : const std::string &osArrayPath);
595 :
596 : std::vector<std::string>
597 : GetMDArrayNames(CSLConstList /*papszOptions*/ = nullptr) const override;
598 :
599 : std::shared_ptr<GDALMDArray>
600 : OpenMDArray(const std::string &osName,
601 : CSLConstList /*papszOptions*/ = nullptr) const override;
602 : };
603 :
604 : /************************************************************************/
605 : /* TileDBMultiDimDataset */
606 : /************************************************************************/
607 :
608 : class TileDBMultiDimDataset final : public GDALDataset
609 : {
610 : friend class TileDBDataset;
611 :
612 : std::shared_ptr<GDALGroup> m_poRG{};
613 :
614 : public:
615 55 : explicit TileDBMultiDimDataset(const std::shared_ptr<GDALGroup> &poRG)
616 55 : : m_poRG(poRG)
617 : {
618 55 : }
619 :
620 58 : std::shared_ptr<GDALGroup> GetRootGroup() const override
621 : {
622 58 : return m_poRG;
623 : }
624 : };
625 :
626 : #endif // TILEDBMULTIDIM_H_INCLUDED
|