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 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "tiledbmultidim.h"
30 :
31 : /************************************************************************/
32 : /* TileDBSingleArrayGroup::SanitizeNameForPath() */
33 : /************************************************************************/
34 :
35 : /* static */
36 34 : std::string TileDBSharedResource::SanitizeNameForPath(const std::string &osName)
37 : {
38 68 : CPLString osSanitized(osName);
39 : // Reserved characters on Windows
40 340 : for (char ch : {'<', '>', ':', '"', '/', '\\', '|', '?', '*'})
41 306 : osSanitized.replaceAll(ch, '_');
42 34 : std::string osRet = std::move(osSanitized);
43 68 : return osRet;
44 : }
45 :
46 : /************************************************************************/
47 : /* TileDBArrayGroup::Create() */
48 : /************************************************************************/
49 :
50 2 : std::shared_ptr<GDALGroup> TileDBArrayGroup::Create(
51 : const std::shared_ptr<TileDBSharedResource> &poSharedResource,
52 : const std::string &osArrayPath)
53 : {
54 : auto poTileDBArray = std::make_unique<tiledb::Array>(
55 4 : poSharedResource->GetCtx(), osArrayPath, TILEDB_READ);
56 4 : auto schema = poTileDBArray->schema();
57 2 : const auto nAttributes = schema.attribute_num();
58 4 : const std::string osBaseName(CPLGetFilename(osArrayPath.c_str()));
59 4 : std::vector<std::shared_ptr<GDALMDArray>> apoArrays;
60 2 : if (nAttributes == 1)
61 : {
62 : auto poArray = TileDBArray::OpenFromDisk(poSharedResource, nullptr, "/",
63 1 : osBaseName, std::string(),
64 2 : osArrayPath, nullptr);
65 1 : if (!poArray)
66 0 : return nullptr;
67 1 : apoArrays.emplace_back(poArray);
68 : }
69 : else
70 : {
71 4 : for (uint32_t i = 0; i < nAttributes; ++i)
72 : {
73 : auto poArray = TileDBArray::OpenFromDisk(
74 : poSharedResource, nullptr, "/",
75 6 : osBaseName + "." + schema.attribute(i).name(),
76 12 : schema.attribute(i).name(), osArrayPath, nullptr);
77 3 : if (!poArray)
78 0 : return nullptr;
79 3 : apoArrays.emplace_back(poArray);
80 : }
81 : }
82 2 : return std::make_shared<TileDBArrayGroup>(apoArrays);
83 : }
84 :
85 : /************************************************************************/
86 : /* TileDBArrayGroup::GetMDArrayNames() */
87 : /************************************************************************/
88 :
89 : std::vector<std::string>
90 3 : TileDBArrayGroup::GetMDArrayNames(CSLConstList /*papszOptions*/) const
91 : {
92 3 : std::vector<std::string> aosNames;
93 10 : for (const auto &poArray : m_apoArrays)
94 7 : aosNames.emplace_back(poArray->GetName());
95 3 : return aosNames;
96 : }
97 :
98 : /************************************************************************/
99 : /* TileDBArrayGroup::OpenMDArray() */
100 : /************************************************************************/
101 :
102 : std::shared_ptr<GDALMDArray>
103 2 : TileDBArrayGroup::OpenMDArray(const std::string &osName,
104 : CSLConstList /*papszOptions*/) const
105 : {
106 2 : for (const auto &poArray : m_apoArrays)
107 : {
108 2 : if (poArray->GetName() == osName)
109 2 : return poArray;
110 : }
111 0 : return nullptr;
112 : }
113 :
114 : /************************************************************************/
115 : /* OpenMultiDimensional() */
116 : /************************************************************************/
117 :
118 27 : GDALDataset *TileDBDataset::OpenMultiDimensional(GDALOpenInfo *poOpenInfo)
119 : {
120 : const char *pszConfig =
121 27 : CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILEDB_CONFIG");
122 :
123 27 : std::unique_ptr<tiledb::Context> pCtxt;
124 27 : if (pszConfig != nullptr)
125 : {
126 0 : tiledb::Config cfg(pszConfig);
127 0 : pCtxt.reset(new tiledb::Context(cfg));
128 : }
129 : else
130 : {
131 27 : pCtxt.reset(new tiledb::Context());
132 : }
133 :
134 : const std::string osPath =
135 54 : TileDBDataset::VSI_to_tiledb_uri(poOpenInfo->pszFilename);
136 :
137 27 : const auto eType = tiledb::Object::object(*(pCtxt.get()), osPath).type();
138 :
139 : auto poSharedResource = std::make_shared<TileDBSharedResource>(
140 54 : std::move(pCtxt), poOpenInfo->eAccess == GA_Update);
141 :
142 54 : poSharedResource->SetDumpStats(CPLTestBool(
143 27 : CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "STATS", "FALSE")));
144 :
145 : const char *pszTimestamp =
146 27 : CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILEDB_TIMESTAMP");
147 27 : if (pszTimestamp)
148 0 : poSharedResource->SetTimestamp(
149 0 : std::strtoull(pszTimestamp, nullptr, 10));
150 :
151 27 : std::shared_ptr<GDALGroup> poRG;
152 27 : if (eType == tiledb::Object::Type::Array)
153 : {
154 2 : poRG = TileDBArrayGroup::Create(poSharedResource, osPath);
155 : }
156 : else
157 : {
158 50 : poRG = TileDBGroup::OpenFromDisk(poSharedResource, std::string(), "/",
159 25 : osPath);
160 : }
161 27 : if (!poRG)
162 0 : return nullptr;
163 :
164 27 : auto poDS = new TileDBMultiDimDataset(poRG);
165 27 : poDS->SetDescription(poOpenInfo->pszFilename);
166 27 : return poDS;
167 : }
168 :
169 : /************************************************************************/
170 : /* CreateMultiDimensional() */
171 : /************************************************************************/
172 :
173 : GDALDataset *
174 25 : TileDBDataset::CreateMultiDimensional(const char *pszFilename,
175 : CSLConstList /*papszRootGroupOptions*/,
176 : CSLConstList papszOptions)
177 : {
178 25 : const char *pszConfig = CSLFetchNameValue(papszOptions, "TILEDB_CONFIG");
179 :
180 25 : std::unique_ptr<tiledb::Context> pCtxt;
181 25 : if (pszConfig != nullptr)
182 : {
183 0 : tiledb::Config cfg(pszConfig);
184 0 : pCtxt.reset(new tiledb::Context(cfg));
185 : }
186 : else
187 : {
188 25 : pCtxt.reset(new tiledb::Context());
189 : }
190 :
191 50 : const std::string osPath = TileDBDataset::VSI_to_tiledb_uri(pszFilename);
192 :
193 : auto poSharedResource =
194 50 : std::make_shared<TileDBSharedResource>(std::move(pCtxt), true);
195 :
196 25 : poSharedResource->SetDumpStats(
197 25 : CPLTestBool(CSLFetchNameValueDef(papszOptions, "STATS", "FALSE")));
198 :
199 : const char *pszTimestamp =
200 25 : CSLFetchNameValue(papszOptions, "TILEDB_TIMESTAMP");
201 25 : if (pszTimestamp)
202 0 : poSharedResource->SetTimestamp(
203 0 : std::strtoull(pszTimestamp, nullptr, 10));
204 :
205 : auto poRG =
206 75 : TileDBGroup::CreateOnDisk(poSharedResource, std::string(), "/", osPath);
207 25 : if (!poRG)
208 0 : return nullptr;
209 :
210 25 : auto poDS = new TileDBMultiDimDataset(poRG);
211 25 : poDS->SetDescription(pszFilename);
212 25 : return poDS;
213 : }
|