1 /** 2 * @file context.h 3 * 4 * @author Ravi Gaddipati 5 * 6 * @section LICENSE 7 * 8 * The MIT License 9 * 10 * @copyright Copyright (c) 2017-2021 TileDB, Inc. 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a copy 13 * of this software and associated documentation files (the "Software"), to deal 14 * in the Software without restriction, including without limitation the rights 15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 * copies of the Software, and to permit persons to whom the Software is 17 * furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included in 20 * all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 * THE SOFTWARE. 29 * 30 * @section DESCRIPTION 31 * 32 * This file declares the C++ API for the TileDB Context object. 33 */ 34 35 #ifndef TILEDB_CPP_API_CONTEXT_H 36 #define TILEDB_CPP_API_CONTEXT_H 37 38 #include "config.h" 39 #include "exception.h" 40 #include "tiledb.h" 41 42 #include <functional> 43 #include <iostream> 44 #include <iterator> 45 #include <memory> 46 #include <string> 47 #include <vector> 48 49 namespace tiledb { 50 51 /** 52 * A TileDB context wraps a TileDB storage manager "instance." 53 * Most objects and functions will require a Context. 54 * 55 * Internal error handling is also defined by the Context; the default error 56 * handler throws a TileDBError with a specific message. 57 * 58 * **Example:** 59 * 60 * @code{.cpp} 61 * tiledb::Context ctx; 62 * // Use ctx when creating other objects: 63 * tiledb::ArraySchema schema(ctx, TILEDB_SPARSE); 64 * 65 * // Set a custom error handler: 66 * ctx.set_error_handler([](const std::string &msg) { 67 * std::cerr << msg << std::endl; 68 * }); 69 * @endcode 70 * 71 */ 72 class Context { 73 public: 74 /* ********************************* */ 75 /* CONSTRUCTORS & DESTRUCTORS */ 76 /* ********************************* */ 77 78 /** 79 * Constructor. Creates a TileDB Context with default configuration. 80 * @throws TileDBError if construction fails 81 */ Context()82 Context() { 83 tiledb_ctx_t* ctx; 84 if (tiledb_ctx_alloc(nullptr, &ctx) != TILEDB_OK) 85 throw TileDBError("[TileDB::C++API] Error: Failed to create context"); 86 ctx_ = std::shared_ptr<tiledb_ctx_t>(ctx, Context::free); 87 error_handler_ = default_error_handler; 88 89 set_tag("x-tiledb-api-language", "c++"); 90 } 91 92 /** 93 * Constructor. Creates a TileDB context with the given configuration. 94 * @throws TileDBError if construction fails 95 */ Context(const Config & config)96 explicit Context(const Config& config) { 97 tiledb_ctx_t* ctx; 98 if (tiledb_ctx_alloc(config.ptr().get(), &ctx) != TILEDB_OK) 99 throw TileDBError("[TileDB::C++API] Error: Failed to create context"); 100 ctx_ = std::shared_ptr<tiledb_ctx_t>(ctx, Context::free); 101 error_handler_ = default_error_handler; 102 103 set_tag("x-tiledb-api-language", "c++"); 104 } 105 106 /** 107 * Constructor. Creates a TileDB context from the given pointer. 108 * @param own=true If false, disables underlying cleanup upon destruction. 109 * @throws TileDBError if construction fails 110 */ 111 Context(tiledb_ctx_t* ctx, bool own = true) { 112 if (ctx == nullptr) 113 throw TileDBError( 114 "[TileDB::C++API] Error: Failed to create Context from pointer"); 115 116 ctx_ = std::shared_ptr<tiledb_ctx_t>(ctx, [own](tiledb_ctx_t* p) { 117 if (own) { 118 Context::free(p); 119 } 120 }); 121 122 error_handler_ = default_error_handler; 123 124 set_tag("x-tiledb-api-language", "c++"); 125 } 126 /* ********************************* */ 127 /* API */ 128 /* ********************************* */ 129 130 /** 131 * Error handler for the TileDB C API calls. Throws an exception 132 * in case of error. 133 * 134 * @param rc If != TILEDB_OK, calls error handler 135 */ handle_error(int rc)136 void handle_error(int rc) const { 137 // Do nothing if there is not error 138 if (rc == TILEDB_OK) 139 return; 140 141 // Get error 142 const auto& ctx = ctx_.get(); 143 tiledb_error_t* err = nullptr; 144 const char* msg = nullptr; 145 rc = tiledb_ctx_get_last_error(ctx, &err); 146 if (rc != TILEDB_OK) { 147 tiledb_error_free(&err); 148 error_handler_("[TileDB::C++API] Error: Non-retrievable error occurred"); 149 } 150 151 // Get error message 152 rc = tiledb_error_message(err, &msg); 153 if (rc != TILEDB_OK) { 154 tiledb_error_free(&err); 155 error_handler_("[TileDB::C++API] Error: Non-retrievable error occurred"); 156 } 157 auto msg_str = std::string(msg); 158 159 // Clean up 160 tiledb_error_free(&err); 161 162 // Throw exception 163 error_handler_(msg_str); 164 } 165 166 /** Returns the C TileDB context object. */ ptr()167 std::shared_ptr<tiledb_ctx_t> ptr() const { 168 return ctx_; 169 } 170 171 /** 172 * Sets the error handler callback. If none is set, the 173 * `default_error_handler` is used. The callback accepts an error 174 * message. 175 * 176 * @param fn Error handler callback function 177 * @return Reference to this Context 178 */ set_error_handler(const std::function<void (const std::string &)> & fn)179 Context& set_error_handler( 180 const std::function<void(const std::string&)>& fn) { 181 error_handler_ = fn; 182 return *this; 183 } 184 185 /** Returns a copy of the configuration of the context. **/ config()186 Config config() const { 187 tiledb_config_t* c; 188 handle_error(tiledb_ctx_get_config(ctx_.get(), &c)); 189 return Config(&c); 190 } 191 192 /** 193 * Return true if the given filesystem backend is supported. 194 * 195 * **Example:** 196 * @code{.cpp} 197 * tiledb::Context ctx; 198 * bool s3_supported = ctx.is_supported_fs(TILEDB_S3); 199 * @endcode 200 * 201 * @param fs Filesystem to check 202 */ is_supported_fs(tiledb_filesystem_t fs)203 bool is_supported_fs(tiledb_filesystem_t fs) const { 204 int ret; 205 handle_error(tiledb_ctx_is_supported_fs(ctx_.get(), fs, &ret)); 206 return ret != 0; 207 } 208 209 /** 210 * Cancels all background or async tasks associated with this context. 211 */ cancel_tasks()212 void cancel_tasks() const { 213 handle_error(tiledb_ctx_cancel_tasks(ctx_.get())); 214 } 215 216 /** Sets a string/string KV tag on the context. */ set_tag(const std::string & key,const std::string & value)217 void set_tag(const std::string& key, const std::string& value) { 218 handle_error(tiledb_ctx_set_tag(ctx_.get(), key.c_str(), value.c_str())); 219 } 220 221 /** Returns a JSON-formatted string of the stats. */ stats()222 std::string stats() { 223 char* c_str; 224 handle_error(tiledb_ctx_get_stats(ctx_.get(), &c_str)); 225 226 // Copy `c_str` into `str`. 227 std::string str(c_str); 228 ::free(c_str); 229 230 return str; 231 } 232 233 /* ********************************* */ 234 /* STATIC FUNCTIONS */ 235 /* ********************************* */ 236 237 /** 238 * The default error handler callback. 239 * @throws TileDBError with the error message 240 */ default_error_handler(const std::string & msg)241 static void default_error_handler(const std::string& msg) { 242 throw TileDBError(msg); 243 } 244 245 private: 246 /* ********************************* */ 247 /* PRIVATE ATTRIBUTES */ 248 /* ********************************* */ 249 250 /** The C TileDB context object. */ 251 std::shared_ptr<tiledb_ctx_t> ctx_; 252 253 /** An error handler callback. */ 254 std::function<void(const std::string&)> error_handler_; 255 256 /** Wrapper function for freeing a context C object. */ free(tiledb_ctx_t * ctx)257 static void free(tiledb_ctx_t* ctx) { 258 tiledb_ctx_free(&ctx); 259 } 260 }; 261 262 } // namespace tiledb 263 264 #endif // TILEDB_CPP_API_CONTEXT_H 265