quasardb 3.14.1.dev4__cp39-cp39-win_amd64.whl → 3.14.1.dev6__cp39-cp39-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of quasardb might be problematic. Click here for more details.
- quasardb/CMakeLists.txt +4 -0
- quasardb/cluster.cpp +89 -0
- quasardb/cluster.hpp +113 -33
- quasardb/error.hpp +25 -1
- quasardb/handle.cpp +29 -0
- quasardb/handle.hpp +28 -11
- quasardb/logger.cpp +3 -0
- quasardb/metrics.cpp +103 -0
- quasardb/metrics.hpp +112 -0
- quasardb/module.cpp +2 -0
- quasardb/options.hpp +15 -0
- quasardb/qdb_api.dll +0 -0
- quasardb/quasardb.cp39-win_amd64.pyd +0 -0
- quasardb/query.cpp +13 -2
- quasardb/table.cpp +42 -0
- quasardb/table.hpp +7 -19
- quasardb/table_reader.hpp +5 -1
- quasardb/writer.cpp +6 -0
- {quasardb-3.14.1.dev4.dist-info → quasardb-3.14.1.dev6.dist-info}/METADATA +1 -1
- {quasardb-3.14.1.dev4.dist-info → quasardb-3.14.1.dev6.dist-info}/RECORD +23 -20
- quasardb/add_boost_test.cmake +0 -43
- {quasardb-3.14.1.dev4.dist-info → quasardb-3.14.1.dev6.dist-info}/LICENSE.md +0 -0
- {quasardb-3.14.1.dev4.dist-info → quasardb-3.14.1.dev6.dist-info}/WHEEL +0 -0
- {quasardb-3.14.1.dev4.dist-info → quasardb-3.14.1.dev6.dist-info}/top_level.txt +0 -0
quasardb/CMakeLists.txt
CHANGED
|
@@ -325,6 +325,7 @@ set(QDB_FILES
|
|
|
325
325
|
batch_inserter.hpp
|
|
326
326
|
blob.hpp
|
|
327
327
|
cluster.hpp
|
|
328
|
+
cluster.cpp
|
|
328
329
|
concepts.hpp
|
|
329
330
|
continuous.cpp
|
|
330
331
|
continuous.hpp
|
|
@@ -333,9 +334,12 @@ set(QDB_FILES
|
|
|
333
334
|
error.hpp
|
|
334
335
|
entry.hpp
|
|
335
336
|
handle.hpp
|
|
337
|
+
handle.cpp
|
|
336
338
|
logger.hpp
|
|
337
339
|
logger.cpp
|
|
338
340
|
masked_array.hpp
|
|
341
|
+
metrics.hpp
|
|
342
|
+
metrics.cpp
|
|
339
343
|
module.hpp
|
|
340
344
|
module.cpp
|
|
341
345
|
node.hpp
|
quasardb/cluster.cpp
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#include "cluster.hpp"
|
|
2
|
+
#include "metrics.hpp"
|
|
3
|
+
#include <chrono>
|
|
4
|
+
#include <thread>
|
|
5
|
+
|
|
6
|
+
namespace qdb
|
|
7
|
+
{
|
|
8
|
+
|
|
9
|
+
cluster::cluster(const std::string & uri,
|
|
10
|
+
const std::string & user_name,
|
|
11
|
+
const std::string & user_private_key,
|
|
12
|
+
const std::string & cluster_public_key,
|
|
13
|
+
const std::string & user_security_file,
|
|
14
|
+
const std::string & cluster_public_key_file,
|
|
15
|
+
std::chrono::milliseconds timeout,
|
|
16
|
+
bool do_version_check)
|
|
17
|
+
: _uri{uri}
|
|
18
|
+
, _handle{make_handle_ptr()}
|
|
19
|
+
, _json_loads{pybind11::module::import("json").attr("loads")}
|
|
20
|
+
, _logger("quasardb.cluster")
|
|
21
|
+
{
|
|
22
|
+
if (do_version_check == true)
|
|
23
|
+
{
|
|
24
|
+
_logger.warn(
|
|
25
|
+
"do_version_check parameter has been deprecated and a no-op. It will be removed from a "
|
|
26
|
+
"future release");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
options().apply_credentials(user_name, user_private_key, cluster_public_key, //
|
|
30
|
+
user_security_file, cluster_public_key_file);
|
|
31
|
+
|
|
32
|
+
options().set_timeout(timeout);
|
|
33
|
+
|
|
34
|
+
// HACKS(leon): we need to ensure there is always one callback active
|
|
35
|
+
// for qdb. Callbacks can be lost when the last active session
|
|
36
|
+
// gets closed. As such, the most pragmatic place to 'check'
|
|
37
|
+
// for this callback is when establishing a new connection.
|
|
38
|
+
qdb::native::swap_callback();
|
|
39
|
+
|
|
40
|
+
_logger.info("Connecting to cluster %s", _uri);
|
|
41
|
+
_handle->connect(_uri);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void cluster::close()
|
|
45
|
+
{
|
|
46
|
+
_logger.info("Closing connection to cluster");
|
|
47
|
+
|
|
48
|
+
try
|
|
49
|
+
{
|
|
50
|
+
if (is_open() == true) [[likely]]
|
|
51
|
+
{
|
|
52
|
+
_handle->close();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (qdb::invalid_handle_exception const & e)
|
|
56
|
+
{
|
|
57
|
+
// This can happen if, for example, we call close() after an error occured; in those
|
|
58
|
+
// circumstances, we fully expect the connection to already be invalid, and we should
|
|
59
|
+
// not care if this specific exception is raised.
|
|
60
|
+
_logger.warn("Connection already closed");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
_handle.reset();
|
|
64
|
+
|
|
65
|
+
assert(is_open() == false);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void cluster::wait_for_compaction()
|
|
69
|
+
{
|
|
70
|
+
|
|
71
|
+
// We define this function in the .cpp file so we can avoid including chrono and thread
|
|
72
|
+
// in the header file.
|
|
73
|
+
|
|
74
|
+
using namespace std::chrono_literals;
|
|
75
|
+
|
|
76
|
+
for (;;)
|
|
77
|
+
{
|
|
78
|
+
std::uint64_t progress = compact_progress();
|
|
79
|
+
|
|
80
|
+
if (progress == 0) [[unlikely]]
|
|
81
|
+
{
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
std::this_thread::sleep_for(100ms);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
}; // namespace qdb
|
quasardb/cluster.hpp
CHANGED
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
#include <pybind11/operators.h>
|
|
58
58
|
#include <pybind11/stl.h>
|
|
59
59
|
#include <chrono>
|
|
60
|
+
#include <iostream>
|
|
60
61
|
|
|
61
62
|
namespace qdb
|
|
62
63
|
{
|
|
@@ -71,39 +72,30 @@ public:
|
|
|
71
72
|
const std::string & user_security_file = {},
|
|
72
73
|
const std::string & cluster_public_key_file = {},
|
|
73
74
|
std::chrono::milliseconds timeout = std::chrono::minutes{1},
|
|
74
|
-
bool do_version_check = false)
|
|
75
|
-
: _uri{uri}
|
|
76
|
-
, _handle{make_handle_ptr()}
|
|
77
|
-
, _json_loads{pybind11::module::import("json").attr("loads")}
|
|
78
|
-
, _logger("quasardb.cluster")
|
|
79
|
-
{
|
|
80
|
-
if (do_version_check == true)
|
|
81
|
-
{
|
|
82
|
-
_logger.warn(
|
|
83
|
-
"do_version_check parameter has been deprecated and a no-op. It will be removed from a "
|
|
84
|
-
"future release");
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
options().apply_credentials(user_name, user_private_key, cluster_public_key, //
|
|
88
|
-
user_security_file, cluster_public_key_file);
|
|
75
|
+
bool do_version_check = false);
|
|
89
76
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// HACKS(leon): we need to ensure there is always one callback active
|
|
93
|
-
// for qdb. Callbacks can be lost when the last active session
|
|
94
|
-
// gets closed. As such, the most pragmatic place to 'check'
|
|
95
|
-
// for this callback is when establishing a new connection.
|
|
96
|
-
qdb::native::swap_callback();
|
|
77
|
+
public:
|
|
78
|
+
void close();
|
|
97
79
|
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
bool is_open() const
|
|
81
|
+
{
|
|
82
|
+
return _handle.get() != nullptr && _handle->is_open();
|
|
100
83
|
}
|
|
101
84
|
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Throws exception if the connection is not open. Should be invoked before any operation
|
|
87
|
+
* is done on the handle, as the QuasarDB C API only checks for a canary presence in the
|
|
88
|
+
* handle's memory arena. If a compiler is optimizing enough, the handle can be closed but
|
|
89
|
+
* the canary still present in memory, so it's UB.
|
|
90
|
+
*
|
|
91
|
+
* As such, we should check on a higher level.
|
|
92
|
+
*/
|
|
93
|
+
void check_open() const
|
|
104
94
|
{
|
|
105
|
-
|
|
106
|
-
|
|
95
|
+
if (is_open() == false) [[unlikely]]
|
|
96
|
+
{
|
|
97
|
+
throw qdb::invalid_handle_exception{};
|
|
98
|
+
}
|
|
107
99
|
}
|
|
108
100
|
|
|
109
101
|
void tidy_memory()
|
|
@@ -153,11 +145,6 @@ public:
|
|
|
153
145
|
return *this;
|
|
154
146
|
}
|
|
155
147
|
|
|
156
|
-
bool is_open() const
|
|
157
|
-
{
|
|
158
|
-
return _handle.get() != nullptr;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
148
|
void exit(pybind11::object type, pybind11::object value, pybind11::object traceback)
|
|
162
149
|
{
|
|
163
150
|
return close();
|
|
@@ -165,6 +152,8 @@ public:
|
|
|
165
152
|
|
|
166
153
|
pybind11::object node_config(const std::string & uri)
|
|
167
154
|
{
|
|
155
|
+
check_open();
|
|
156
|
+
|
|
168
157
|
const char * content = nullptr;
|
|
169
158
|
qdb_size_t content_length = 0;
|
|
170
159
|
|
|
@@ -176,6 +165,8 @@ public:
|
|
|
176
165
|
|
|
177
166
|
pybind11::object node_status(const std::string & uri)
|
|
178
167
|
{
|
|
168
|
+
check_open();
|
|
169
|
+
|
|
179
170
|
const char * content = nullptr;
|
|
180
171
|
qdb_size_t content_length = 0;
|
|
181
172
|
|
|
@@ -187,6 +178,8 @@ public:
|
|
|
187
178
|
|
|
188
179
|
pybind11::object node_topology(const std::string & uri)
|
|
189
180
|
{
|
|
181
|
+
check_open();
|
|
182
|
+
|
|
190
183
|
const char * content = nullptr;
|
|
191
184
|
qdb_size_t content_length = 0;
|
|
192
185
|
|
|
@@ -199,64 +192,88 @@ public:
|
|
|
199
192
|
public:
|
|
200
193
|
qdb::tag tag(const std::string & alias)
|
|
201
194
|
{
|
|
195
|
+
check_open();
|
|
196
|
+
|
|
202
197
|
return qdb::tag{_handle, alias};
|
|
203
198
|
}
|
|
204
199
|
|
|
205
200
|
qdb::blob_entry blob(const std::string & alias)
|
|
206
201
|
{
|
|
202
|
+
check_open();
|
|
203
|
+
|
|
207
204
|
return qdb::blob_entry{_handle, alias};
|
|
208
205
|
}
|
|
209
206
|
|
|
210
207
|
qdb::string_entry string(const std::string & alias)
|
|
211
208
|
{
|
|
209
|
+
check_open();
|
|
210
|
+
|
|
212
211
|
return qdb::string_entry{_handle, alias};
|
|
213
212
|
}
|
|
214
213
|
|
|
215
214
|
qdb::integer_entry integer(const std::string & alias)
|
|
216
215
|
{
|
|
216
|
+
check_open();
|
|
217
|
+
|
|
217
218
|
return qdb::integer_entry{_handle, alias};
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
qdb::double_entry double_(const std::string & alias)
|
|
221
222
|
{
|
|
223
|
+
check_open();
|
|
224
|
+
|
|
222
225
|
return qdb::double_entry{_handle, alias};
|
|
223
226
|
}
|
|
224
227
|
|
|
225
228
|
qdb::timestamp_entry timestamp(const std::string & alias)
|
|
226
229
|
{
|
|
230
|
+
check_open();
|
|
231
|
+
|
|
227
232
|
return qdb::timestamp_entry{_handle, alias};
|
|
228
233
|
}
|
|
229
234
|
|
|
230
235
|
qdb::table table(const std::string & alias)
|
|
231
236
|
{
|
|
237
|
+
check_open();
|
|
238
|
+
|
|
232
239
|
return qdb::table{_handle, alias};
|
|
233
240
|
}
|
|
234
241
|
|
|
235
242
|
// the batch_inserter_ptr is non-copyable
|
|
236
243
|
qdb::batch_inserter_ptr inserter(const std::vector<batch_column_info> & ci)
|
|
237
244
|
{
|
|
245
|
+
check_open();
|
|
246
|
+
|
|
238
247
|
return std::make_unique<qdb::batch_inserter>(_handle, ci);
|
|
239
248
|
}
|
|
240
249
|
|
|
241
250
|
// the batch_inserter_ptr is non-copyable
|
|
242
251
|
qdb::writer_ptr writer()
|
|
243
252
|
{
|
|
253
|
+
check_open();
|
|
254
|
+
|
|
244
255
|
return std::make_unique<qdb::writer>(_handle);
|
|
245
256
|
}
|
|
246
257
|
|
|
247
258
|
// the batch_inserter_ptr is non-copyable
|
|
248
259
|
qdb::writer_ptr pinned_writer()
|
|
249
260
|
{
|
|
261
|
+
check_open();
|
|
262
|
+
|
|
250
263
|
return writer();
|
|
251
264
|
}
|
|
252
265
|
|
|
253
266
|
qdb::options options()
|
|
254
267
|
{
|
|
268
|
+
check_open();
|
|
269
|
+
|
|
255
270
|
return qdb::options{_handle};
|
|
256
271
|
}
|
|
257
272
|
|
|
258
273
|
qdb::perf perf()
|
|
259
274
|
{
|
|
275
|
+
check_open();
|
|
276
|
+
|
|
260
277
|
return qdb::perf{_handle};
|
|
261
278
|
}
|
|
262
279
|
|
|
@@ -268,6 +285,8 @@ public:
|
|
|
268
285
|
public:
|
|
269
286
|
std::vector<std::string> prefix_get(const std::string & prefix, qdb_int_t max_count)
|
|
270
287
|
{
|
|
288
|
+
check_open();
|
|
289
|
+
|
|
271
290
|
const char ** result = nullptr;
|
|
272
291
|
size_t count = 0;
|
|
273
292
|
|
|
@@ -283,6 +302,8 @@ public:
|
|
|
283
302
|
|
|
284
303
|
qdb_uint_t prefix_count(const std::string & prefix)
|
|
285
304
|
{
|
|
305
|
+
check_open();
|
|
306
|
+
|
|
286
307
|
qdb_uint_t count = 0;
|
|
287
308
|
|
|
288
309
|
const qdb_error_t err = qdb_prefix_count(*_handle, prefix.c_str(), &count);
|
|
@@ -294,22 +315,30 @@ public:
|
|
|
294
315
|
public:
|
|
295
316
|
qdb::find_query find(const std::string & query_string)
|
|
296
317
|
{
|
|
318
|
+
check_open();
|
|
319
|
+
|
|
297
320
|
return qdb::find_query{_handle, query_string};
|
|
298
321
|
}
|
|
299
322
|
|
|
300
323
|
py::object query(const std::string & query_string, const py::object & blobs)
|
|
301
324
|
{
|
|
325
|
+
check_open();
|
|
326
|
+
|
|
302
327
|
return py::cast(qdb::dict_query(_handle, query_string, blobs));
|
|
303
328
|
}
|
|
304
329
|
|
|
305
330
|
py::object query_numpy(const std::string & query_string)
|
|
306
331
|
{
|
|
332
|
+
check_open();
|
|
333
|
+
|
|
307
334
|
return py::cast(qdb::numpy_query(_handle, query_string));
|
|
308
335
|
}
|
|
309
336
|
|
|
310
337
|
std::shared_ptr<qdb::query_continuous> query_continuous_full(
|
|
311
338
|
const std::string & query_string, std::chrono::milliseconds pace, const py::object & blobs)
|
|
312
339
|
{
|
|
340
|
+
check_open();
|
|
341
|
+
|
|
313
342
|
return std::make_shared<qdb::query_continuous>(
|
|
314
343
|
_handle, qdb_query_continuous_full, pace, query_string, blobs);
|
|
315
344
|
}
|
|
@@ -317,6 +346,8 @@ public:
|
|
|
317
346
|
std::shared_ptr<qdb::query_continuous> query_continuous_new_values(
|
|
318
347
|
const std::string & query_string, std::chrono::milliseconds pace, const py::object & blobs)
|
|
319
348
|
{
|
|
349
|
+
check_open();
|
|
350
|
+
|
|
320
351
|
return std::make_shared<qdb::query_continuous>(
|
|
321
352
|
_handle, qdb_query_continuous_new_values_only, pace, query_string, blobs);
|
|
322
353
|
}
|
|
@@ -324,6 +355,8 @@ public:
|
|
|
324
355
|
public:
|
|
325
356
|
std::vector<std::string> suffix_get(const std::string & suffix, qdb_int_t max_count)
|
|
326
357
|
{
|
|
358
|
+
check_open();
|
|
359
|
+
|
|
327
360
|
const char ** result = nullptr;
|
|
328
361
|
size_t count = 0;
|
|
329
362
|
|
|
@@ -339,6 +372,8 @@ public:
|
|
|
339
372
|
|
|
340
373
|
qdb_uint_t suffix_count(const std::string & suffix)
|
|
341
374
|
{
|
|
375
|
+
check_open();
|
|
376
|
+
|
|
342
377
|
qdb_uint_t count = 0;
|
|
343
378
|
|
|
344
379
|
const qdb_error_t err = qdb_suffix_count(*_handle, suffix.c_str(), &count);
|
|
@@ -350,31 +385,72 @@ public:
|
|
|
350
385
|
public:
|
|
351
386
|
void purge_all(std::chrono::milliseconds timeout_ms)
|
|
352
387
|
{
|
|
388
|
+
check_open();
|
|
389
|
+
|
|
353
390
|
qdb::qdb_throw_if_error(
|
|
354
391
|
*_handle, qdb_purge_all(*_handle, static_cast<int>(timeout_ms.count())));
|
|
355
392
|
}
|
|
356
393
|
|
|
357
394
|
void purge_cache(std::chrono::milliseconds timeout_ms)
|
|
358
395
|
{
|
|
396
|
+
check_open();
|
|
397
|
+
|
|
359
398
|
qdb::qdb_throw_if_error(
|
|
360
399
|
*_handle, qdb_purge_cache(*_handle, static_cast<int>(timeout_ms.count())));
|
|
361
400
|
}
|
|
362
401
|
|
|
363
402
|
void wait_for_stabilization(std::chrono::milliseconds timeout_ms)
|
|
364
403
|
{
|
|
404
|
+
check_open();
|
|
405
|
+
|
|
365
406
|
qdb::qdb_throw_if_error(
|
|
366
407
|
*_handle, qdb_wait_for_stabilization(*_handle, static_cast<int>(timeout_ms.count())));
|
|
367
408
|
}
|
|
368
409
|
|
|
369
410
|
void trim_all(std::chrono::milliseconds pause_ms, std::chrono::milliseconds timeout_ms)
|
|
370
411
|
{
|
|
412
|
+
check_open();
|
|
413
|
+
|
|
371
414
|
qdb::qdb_throw_if_error(*_handle, qdb_trim_all(*_handle, static_cast<int>(pause_ms.count()),
|
|
372
415
|
static_cast<int>(timeout_ms.count())));
|
|
373
416
|
}
|
|
374
417
|
|
|
418
|
+
void compact_full()
|
|
419
|
+
{
|
|
420
|
+
check_open();
|
|
421
|
+
|
|
422
|
+
qdb_compact_params_t params{};
|
|
423
|
+
params.options = qdb_compact_full;
|
|
424
|
+
|
|
425
|
+
qdb::qdb_throw_if_error(*_handle, qdb_cluster_compact(*_handle, ¶ms));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Returns 0 when finished / no compaction running
|
|
429
|
+
std::uint64_t compact_progress()
|
|
430
|
+
{
|
|
431
|
+
check_open();
|
|
432
|
+
|
|
433
|
+
std::uint64_t progress;
|
|
434
|
+
|
|
435
|
+
qdb::qdb_throw_if_error(*_handle, qdb_cluster_get_compact_progress(*_handle, &progress));
|
|
436
|
+
|
|
437
|
+
return progress;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
void compact_abort()
|
|
441
|
+
{
|
|
442
|
+
check_open();
|
|
443
|
+
|
|
444
|
+
qdb::qdb_throw_if_error(*_handle, qdb_cluster_abort_compact(*_handle));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
void wait_for_compaction();
|
|
448
|
+
|
|
375
449
|
public:
|
|
376
450
|
std::vector<std::string> endpoints()
|
|
377
451
|
{
|
|
452
|
+
check_open();
|
|
453
|
+
|
|
378
454
|
qdb_remote_node_t * endpoints = nullptr;
|
|
379
455
|
qdb_size_t count = 0;
|
|
380
456
|
|
|
@@ -465,6 +541,10 @@ static inline void register_cluster(Module & m)
|
|
|
465
541
|
.def("purge_all", &qdb::cluster::purge_all) //
|
|
466
542
|
.def("trim_all", &qdb::cluster::trim_all) //
|
|
467
543
|
.def("purge_cache", &qdb::cluster::purge_cache) //
|
|
544
|
+
.def("compact_full", &qdb::cluster::compact_full) //
|
|
545
|
+
.def("compact_progress", &qdb::cluster::compact_progress) //
|
|
546
|
+
.def("compact_abort", &qdb::cluster::compact_abort) //
|
|
547
|
+
.def("wait_for_compaction", &qdb::cluster::wait_for_compaction) //
|
|
468
548
|
.def("endpoints", &qdb::cluster::endpoints); //
|
|
469
549
|
}
|
|
470
550
|
|
quasardb/error.hpp
CHANGED
|
@@ -78,6 +78,17 @@ public:
|
|
|
78
78
|
{}
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
+
class invalid_handle_exception : public exception
|
|
82
|
+
{
|
|
83
|
+
public:
|
|
84
|
+
invalid_handle_exception() noexcept
|
|
85
|
+
: exception(qdb_e_invalid_handle,
|
|
86
|
+
std::string("Invalid handle: the connection to the cluster has been closed. Please "
|
|
87
|
+
"re-establish a new connection"
|
|
88
|
+
"with the QuasarDB cluster."))
|
|
89
|
+
{}
|
|
90
|
+
};
|
|
91
|
+
|
|
81
92
|
class incompatible_type_exception : public exception
|
|
82
93
|
{
|
|
83
94
|
public:
|
|
@@ -218,7 +229,15 @@ inline void qdb_throw_if_error(
|
|
|
218
229
|
{
|
|
219
230
|
// Error context returned is not the same, which means this thread already made
|
|
220
231
|
// another call to the QDB API, or the QDB API itself
|
|
221
|
-
|
|
232
|
+
|
|
233
|
+
switch (err)
|
|
234
|
+
{
|
|
235
|
+
case qdb_e_not_connected:
|
|
236
|
+
case qdb_e_invalid_handle:
|
|
237
|
+
throw qdb::invalid_handle_exception{};
|
|
238
|
+
default:
|
|
239
|
+
throw qdb::exception{err, qdb_error(err)};
|
|
240
|
+
}
|
|
222
241
|
}
|
|
223
242
|
assert(err_ == err);
|
|
224
243
|
assert(msg_ != nullptr);
|
|
@@ -233,6 +252,10 @@ inline void qdb_throw_if_error(
|
|
|
233
252
|
case qdb_e_invalid_query:
|
|
234
253
|
throw qdb::invalid_query_exception{msg_data_};
|
|
235
254
|
|
|
255
|
+
case qdb_e_not_connected:
|
|
256
|
+
case qdb_e_invalid_handle:
|
|
257
|
+
throw qdb::invalid_handle_exception{};
|
|
258
|
+
|
|
236
259
|
case qdb_e_alias_already_exists:
|
|
237
260
|
throw qdb::alias_already_exists_exception{msg_data_};
|
|
238
261
|
|
|
@@ -289,6 +312,7 @@ static inline void register_errors(Module & m)
|
|
|
289
312
|
py::register_exception<qdb::internal_local_exception>(m, "InternalLocalError", base_class);
|
|
290
313
|
py::register_exception<qdb::invalid_argument_exception>(m, "InvalidArgumentError", base_class);
|
|
291
314
|
py::register_exception<qdb::invalid_query_exception>(m, "InvalidQueryError", base_class);
|
|
315
|
+
py::register_exception<qdb::invalid_handle_exception>(m, "InvalidHandleError", base_class);
|
|
292
316
|
}
|
|
293
317
|
|
|
294
318
|
} // namespace qdb
|
quasardb/handle.cpp
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#include "handle.hpp"
|
|
2
|
+
#include "metrics.hpp"
|
|
3
|
+
|
|
4
|
+
namespace qdb
|
|
5
|
+
{
|
|
6
|
+
|
|
7
|
+
void handle::connect(const std::string & uri)
|
|
8
|
+
{
|
|
9
|
+
qdb_error_t err;
|
|
10
|
+
{
|
|
11
|
+
metrics::scoped_capture{"qdb_connect"};
|
|
12
|
+
err = qdb_connect(handle_, uri.c_str());
|
|
13
|
+
}
|
|
14
|
+
qdb::qdb_throw_if_error(handle_, err);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void handle::close()
|
|
18
|
+
{
|
|
19
|
+
if (handle_ != nullptr)
|
|
20
|
+
{
|
|
21
|
+
metrics::scoped_capture{"qdb_close"};
|
|
22
|
+
qdb_close(handle_);
|
|
23
|
+
handle_ = nullptr;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
assert(handle_ == nullptr);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}; // namespace qdb
|
quasardb/handle.hpp
CHANGED
|
@@ -42,33 +42,50 @@ class handle
|
|
|
42
42
|
{
|
|
43
43
|
public:
|
|
44
44
|
handle() noexcept
|
|
45
|
+
: handle_{nullptr}
|
|
45
46
|
{}
|
|
46
47
|
|
|
47
48
|
explicit handle(qdb_handle_t h) noexcept
|
|
48
|
-
:
|
|
49
|
+
: handle_{h}
|
|
49
50
|
{}
|
|
50
51
|
|
|
51
52
|
~handle()
|
|
52
53
|
{
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
qdb_close(_handle);
|
|
56
|
-
_handle = nullptr;
|
|
57
|
-
}
|
|
54
|
+
close();
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
void connect(const std::string & uri)
|
|
57
|
+
void connect(const std::string & uri);
|
|
58
|
+
|
|
59
|
+
operator qdb_handle_t() const noexcept
|
|
61
60
|
{
|
|
62
|
-
|
|
61
|
+
return handle_;
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
void close();
|
|
65
|
+
|
|
66
|
+
constexpr inline bool is_open() const
|
|
66
67
|
{
|
|
67
|
-
return
|
|
68
|
+
return handle_ != nullptr;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Throws exception if the connection is not open. Should be invoked before any operation
|
|
73
|
+
* is done on the handle, as the QuasarDB C API only checks for a canary presence in the
|
|
74
|
+
* handle's memory arena. If a compiler is optimizing enough, the handle can be closed but
|
|
75
|
+
* the canary still present in memory, so it's UB.
|
|
76
|
+
*
|
|
77
|
+
* As such, we should check on a higher level.
|
|
78
|
+
*/
|
|
79
|
+
inline void check_open() const
|
|
80
|
+
{
|
|
81
|
+
if (is_open() == false) [[unlikely]]
|
|
82
|
+
{
|
|
83
|
+
throw qdb::invalid_handle_exception{};
|
|
84
|
+
}
|
|
68
85
|
}
|
|
69
86
|
|
|
70
87
|
private:
|
|
71
|
-
qdb_handle_t
|
|
88
|
+
qdb_handle_t handle_{nullptr};
|
|
72
89
|
};
|
|
73
90
|
|
|
74
91
|
using handle_ptr = std::shared_ptr<handle>;
|
quasardb/logger.cpp
CHANGED
|
@@ -11,6 +11,8 @@ void qdb::native::swap_callback()
|
|
|
11
11
|
{
|
|
12
12
|
// Potential race condition avoidance!
|
|
13
13
|
std::lock_guard<std::mutex> guard(_buffer_lock);
|
|
14
|
+
|
|
15
|
+
#ifndef NDEBUG
|
|
14
16
|
qdb_error_t error;
|
|
15
17
|
|
|
16
18
|
error = qdb_log_remove_callback(local_callback_id);
|
|
@@ -26,6 +28,7 @@ void qdb::native::swap_callback()
|
|
|
26
28
|
// fprintf(stderr, "unable to add new callback: %s (%#x)\n", qdb_error(error), error);
|
|
27
29
|
// fflush(stderr);
|
|
28
30
|
}
|
|
31
|
+
#endif
|
|
29
32
|
|
|
30
33
|
_logger = qdb::logger("quasardb.native");
|
|
31
34
|
}
|
quasardb/metrics.cpp
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#include "metrics.hpp"
|
|
2
|
+
#include <mutex>
|
|
3
|
+
|
|
4
|
+
namespace qdb
|
|
5
|
+
{
|
|
6
|
+
|
|
7
|
+
static metrics_container_t metrics_totals_ = metrics_container_t{};
|
|
8
|
+
static std::mutex metrics_lock_ = std::mutex{};
|
|
9
|
+
|
|
10
|
+
metrics::scoped_capture::~scoped_capture()
|
|
11
|
+
{
|
|
12
|
+
using std::chrono::nanoseconds;
|
|
13
|
+
|
|
14
|
+
time_point_t stop = clock_t::now();
|
|
15
|
+
|
|
16
|
+
auto duration = std::chrono::duration_cast<nanoseconds>(stop - start_);
|
|
17
|
+
|
|
18
|
+
metrics::record(test_id_, duration.count());
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
metrics::measure::measure()
|
|
22
|
+
: start_{metrics::totals()}
|
|
23
|
+
{}
|
|
24
|
+
|
|
25
|
+
metrics_container_t metrics::measure::get() const
|
|
26
|
+
{
|
|
27
|
+
metrics_container_t cur = metrics::totals();
|
|
28
|
+
|
|
29
|
+
metrics_container_t ret{};
|
|
30
|
+
|
|
31
|
+
for (auto i : cur)
|
|
32
|
+
{
|
|
33
|
+
assert(ret.find(i.first) == ret.end());
|
|
34
|
+
|
|
35
|
+
metrics_container_t::const_iterator prev = start_.find(i.first);
|
|
36
|
+
|
|
37
|
+
if (prev == start_.end())
|
|
38
|
+
{
|
|
39
|
+
// Previously, metric didn't exist yet, as such it's entirely new
|
|
40
|
+
// and all accumulated time was within the scope.
|
|
41
|
+
ret.emplace(i.first, i.second);
|
|
42
|
+
}
|
|
43
|
+
else if (i.second > prev->second)
|
|
44
|
+
{
|
|
45
|
+
// Accumulated time actually increased, record difference
|
|
46
|
+
ret.emplace(i.first, i.second - prev->second);
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
{
|
|
50
|
+
// Integrity check: we can only increase totals over time, never decrease
|
|
51
|
+
assert(i.second == prev->second);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return ret;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/* static */ void metrics::record(std::string const & test_id, std::uint64_t nsec)
|
|
59
|
+
{
|
|
60
|
+
std::lock_guard<std::mutex> guard(metrics_lock_);
|
|
61
|
+
|
|
62
|
+
metrics_container_t::iterator pos = metrics_totals_.lower_bound(test_id);
|
|
63
|
+
|
|
64
|
+
if (pos == metrics_totals_.end() || pos->first != test_id) [[unlikely]]
|
|
65
|
+
{
|
|
66
|
+
pos = metrics_totals_.emplace_hint(pos, test_id, 0);
|
|
67
|
+
|
|
68
|
+
assert(pos->second == 0);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
assert(pos->first == test_id);
|
|
72
|
+
pos->second += nsec;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* static */ metrics_container_t metrics::totals()
|
|
76
|
+
{
|
|
77
|
+
std::lock_guard<std::mutex> guard(metrics_lock_);
|
|
78
|
+
return metrics_totals_;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* static */ void metrics::clear()
|
|
82
|
+
{
|
|
83
|
+
std::lock_guard<std::mutex> guard(metrics_lock_);
|
|
84
|
+
metrics_totals_.clear();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
void register_metrics(py::module_ & m)
|
|
88
|
+
{
|
|
89
|
+
|
|
90
|
+
py::module_ metrics_module =
|
|
91
|
+
m.def_submodule("metrics", "Keep track of low-level performance metrics")
|
|
92
|
+
.def("totals", &qdb::metrics::totals)
|
|
93
|
+
.def("clear", &qdb::metrics::clear);
|
|
94
|
+
|
|
95
|
+
auto metrics_measure = py::class_<qdb::metrics::measure>(
|
|
96
|
+
metrics_module, "Measure", "Track all metrics within a block of code")
|
|
97
|
+
.def(py::init())
|
|
98
|
+
.def("__enter__", &qdb::metrics::measure::enter)
|
|
99
|
+
.def("__exit__", &qdb::metrics::measure::exit)
|
|
100
|
+
.def("get", &qdb::metrics::measure::get);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
}; // namespace qdb
|
quasardb/metrics.hpp
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* Official Python API
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2009-2023, quasardb SAS. All rights reserved.
|
|
6
|
+
* All rights reserved.
|
|
7
|
+
*
|
|
8
|
+
* Redistribution and use in source and binary forms, with or without
|
|
9
|
+
* modification, are permitted provided that the following conditions are met:
|
|
10
|
+
*
|
|
11
|
+
* * Redistributions of source code must retain the above copyright
|
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
|
13
|
+
* * Redistributions in binary form must reproduce the above copyright
|
|
14
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
15
|
+
* documentation and/or other materials provided with the distribution.
|
|
16
|
+
* * Neither the name of quasardb nor the names of its contributors may
|
|
17
|
+
* be used to endorse or promote products derived from this software
|
|
18
|
+
* without specific prior written permission.
|
|
19
|
+
*
|
|
20
|
+
* THIS SOFTWARE IS PROVIDED BY QUASARDB AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
21
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
22
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
24
|
+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
25
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
26
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
27
|
+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
28
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
29
|
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
+
*/
|
|
31
|
+
#pragma once
|
|
32
|
+
|
|
33
|
+
#include <pybind11/pybind11.h>
|
|
34
|
+
#include <pybind11/stl.h>
|
|
35
|
+
#include <cassert>
|
|
36
|
+
#include <chrono>
|
|
37
|
+
#include <map>
|
|
38
|
+
#include <string>
|
|
39
|
+
|
|
40
|
+
namespace qdb
|
|
41
|
+
{
|
|
42
|
+
namespace py = pybind11;
|
|
43
|
+
using metrics_container_t = std::map<std::string, std::uint64_t>;
|
|
44
|
+
|
|
45
|
+
class metrics
|
|
46
|
+
{
|
|
47
|
+
private:
|
|
48
|
+
public:
|
|
49
|
+
/**
|
|
50
|
+
* Utility fixture that automatically records timings for a certain block of code.
|
|
51
|
+
* This is intended to be used from native C++ code only.
|
|
52
|
+
*/
|
|
53
|
+
class scoped_capture
|
|
54
|
+
{
|
|
55
|
+
using clock_t = std::chrono::high_resolution_clock;
|
|
56
|
+
using time_point_t = std::chrono::time_point<clock_t>;
|
|
57
|
+
|
|
58
|
+
public:
|
|
59
|
+
scoped_capture(std::string const & test_id) noexcept
|
|
60
|
+
: test_id_{test_id}
|
|
61
|
+
, start_{clock_t::now()} {};
|
|
62
|
+
~scoped_capture();
|
|
63
|
+
|
|
64
|
+
private:
|
|
65
|
+
std::string test_id_;
|
|
66
|
+
time_point_t start_;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Utility class that's exposed to Python which can be used to record metrics in
|
|
71
|
+
* a scope. It makes it easy to track the difference between the beginning and end
|
|
72
|
+
* of execution.
|
|
73
|
+
*/
|
|
74
|
+
class measure
|
|
75
|
+
{
|
|
76
|
+
public:
|
|
77
|
+
measure();
|
|
78
|
+
~measure(){};
|
|
79
|
+
|
|
80
|
+
public:
|
|
81
|
+
measure enter()
|
|
82
|
+
{
|
|
83
|
+
// No-op, all initialization is done in the constructor.
|
|
84
|
+
return *this;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
void exit(py::object /* type */, py::object /* value */, py::object /* traceback */)
|
|
88
|
+
{}
|
|
89
|
+
|
|
90
|
+
metrics_container_t get() const;
|
|
91
|
+
|
|
92
|
+
private:
|
|
93
|
+
metrics_container_t start_;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
public:
|
|
97
|
+
metrics() noexcept {};
|
|
98
|
+
|
|
99
|
+
~metrics() noexcept {};
|
|
100
|
+
|
|
101
|
+
public:
|
|
102
|
+
static void record(std::string const & test_id, std::uint64_t nsec);
|
|
103
|
+
|
|
104
|
+
static metrics_container_t totals();
|
|
105
|
+
static void clear();
|
|
106
|
+
|
|
107
|
+
private:
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
void register_metrics(py::module_ & m);
|
|
111
|
+
|
|
112
|
+
} // namespace qdb
|
quasardb/module.cpp
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "module.hpp"
|
|
2
2
|
#include "cluster.hpp"
|
|
3
|
+
#include "metrics.hpp"
|
|
3
4
|
#include "node.hpp"
|
|
4
5
|
#include "writer.hpp"
|
|
5
6
|
#include <functional>
|
|
@@ -62,6 +63,7 @@ PYBIND11_MODULE(quasardb, m)
|
|
|
62
63
|
qdb::register_table_reader(m);
|
|
63
64
|
qdb::register_masked_array(m);
|
|
64
65
|
qdb::register_writer(m);
|
|
66
|
+
qdb::register_metrics(m);
|
|
65
67
|
|
|
66
68
|
qdb::detail::register_ts_column(m);
|
|
67
69
|
qdb::reader::register_ts_value(m);
|
quasardb/options.hpp
CHANGED
|
@@ -184,6 +184,18 @@ public:
|
|
|
184
184
|
return max_parallelism;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
void set_query_max_length(size_t query_max_length)
|
|
188
|
+
{
|
|
189
|
+
qdb::qdb_throw_if_error(*_handle, qdb_option_set_query_max_length(*_handle, query_max_length));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
size_t get_query_max_length()
|
|
193
|
+
{
|
|
194
|
+
size_t query_max_length = 0;
|
|
195
|
+
qdb::qdb_throw_if_error(*_handle, qdb_option_get_query_max_length(*_handle, &query_max_length));
|
|
196
|
+
return query_max_length;
|
|
197
|
+
}
|
|
198
|
+
|
|
187
199
|
private:
|
|
188
200
|
qdb::handle_ptr _handle;
|
|
189
201
|
};
|
|
@@ -221,6 +233,9 @@ static inline void register_options(Module & m)
|
|
|
221
233
|
.def("set_client_max_parallelism", &qdb::options::set_client_max_parallelism, //
|
|
222
234
|
py::arg("parallelism")) //
|
|
223
235
|
.def("get_client_max_parallelism", &qdb::options::get_client_max_parallelism) //
|
|
236
|
+
.def("set_query_max_length", &qdb::options::set_query_max_length, //
|
|
237
|
+
py::arg("query_max_length")) //
|
|
238
|
+
.def("get_query_max_length", &qdb::options::get_query_max_length) //
|
|
224
239
|
.def("set_client_soft_memory_limit", &qdb::options::set_client_soft_memory_limit, //
|
|
225
240
|
py::arg("limit")) //
|
|
226
241
|
;
|
quasardb/qdb_api.dll
CHANGED
|
Binary file
|
|
Binary file
|
quasardb/query.cpp
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
#include "query.hpp"
|
|
33
33
|
#include "masked_array.hpp"
|
|
34
|
+
#include "metrics.hpp"
|
|
34
35
|
#include "numpy.hpp"
|
|
35
36
|
#include "traits.hpp"
|
|
36
37
|
#include "utils.hpp"
|
|
@@ -390,7 +391,12 @@ numpy_query_result_t numpy_query_results(const qdb_query_result_t * r)
|
|
|
390
391
|
dict_query_result_t dict_query(qdb::handle_ptr h, const std::string & q, const py::object & blobs)
|
|
391
392
|
{
|
|
392
393
|
detail::qdb_resource<qdb_query_result_t> r{*h};
|
|
393
|
-
|
|
394
|
+
|
|
395
|
+
qdb_error_t err;
|
|
396
|
+
{
|
|
397
|
+
metrics::scoped_capture capture{"qdb_query"};
|
|
398
|
+
err = qdb_query(*h, q.c_str(), &r);
|
|
399
|
+
}
|
|
394
400
|
|
|
395
401
|
qdb::qdb_throw_if_query_error(*h, err, r.get());
|
|
396
402
|
|
|
@@ -400,7 +406,12 @@ dict_query_result_t dict_query(qdb::handle_ptr h, const std::string & q, const p
|
|
|
400
406
|
numpy_query_result_t numpy_query(qdb::handle_ptr h, const std::string & q)
|
|
401
407
|
{
|
|
402
408
|
detail::qdb_resource<qdb_query_result_t> r{*h};
|
|
403
|
-
|
|
409
|
+
|
|
410
|
+
qdb_error_t err;
|
|
411
|
+
{
|
|
412
|
+
metrics::scoped_capture capture{"qdb_query"};
|
|
413
|
+
err = qdb_query(*h, q.c_str(), &r);
|
|
414
|
+
}
|
|
404
415
|
qdb::qdb_throw_if_query_error(*h, err, r.get());
|
|
405
416
|
|
|
406
417
|
return numpy_query_results(r);
|
quasardb/table.cpp
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "table.hpp"
|
|
2
2
|
#include "dispatch.hpp"
|
|
3
|
+
#include "metrics.hpp"
|
|
3
4
|
#include "object_tracker.hpp"
|
|
4
5
|
#include "table_reader.hpp"
|
|
5
6
|
#include "traits.hpp"
|
|
@@ -29,6 +30,8 @@ struct column_inserter;
|
|
|
29
30
|
pybind11::array const & timestamps, \
|
|
30
31
|
qdb::masked_array const & values) \
|
|
31
32
|
{ \
|
|
33
|
+
handle->check_open(); \
|
|
34
|
+
\
|
|
32
35
|
qdb::object_tracker::scoped_repository ctx{}; \
|
|
33
36
|
qdb::object_tracker::scoped_capture capture{ctx}; \
|
|
34
37
|
numpy::array::ensure<traits::datetime64_ns_dtype>(timestamps); \
|
|
@@ -66,9 +69,36 @@ inline void insert_column_dispatch(handle_ptr handle,
|
|
|
66
69
|
|
|
67
70
|
}; // namespace detail
|
|
68
71
|
|
|
72
|
+
void table::_cache_columns() const
|
|
73
|
+
{
|
|
74
|
+
_handle->check_open();
|
|
75
|
+
|
|
76
|
+
detail::qdb_resource<qdb_ts_column_info_ex_t> columns{*_handle};
|
|
77
|
+
qdb_size_t count = 0;
|
|
78
|
+
|
|
79
|
+
qdb_error_t err;
|
|
80
|
+
|
|
81
|
+
{
|
|
82
|
+
metrics::scoped_capture("qdb_ts_list_columns");
|
|
83
|
+
err = qdb_ts_list_columns_ex(*_handle, _alias.c_str(), &columns, &count);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (err == qdb_e_alias_not_found) [[unlikely]]
|
|
87
|
+
{
|
|
88
|
+
// Can happen if table does not yet exist, do nothing.
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
qdb::qdb_throw_if_error(*_handle, err);
|
|
93
|
+
|
|
94
|
+
_columns = detail::convert_columns(columns.get(), count);
|
|
95
|
+
}
|
|
96
|
+
|
|
69
97
|
py::object table::reader(
|
|
70
98
|
const std::vector<std::string> & columns, py::object ranges, bool dict_mode) const
|
|
71
99
|
{
|
|
100
|
+
_handle->check_open();
|
|
101
|
+
|
|
72
102
|
auto ranges_ = qdb::convert_ranges(ranges);
|
|
73
103
|
|
|
74
104
|
std::vector<detail::column_info> c_columns;
|
|
@@ -102,6 +132,8 @@ py::object table::reader(
|
|
|
102
132
|
|
|
103
133
|
qdb_uint_t table::erase_ranges(const std::string & column, py::object ranges)
|
|
104
134
|
{
|
|
135
|
+
_handle->check_open();
|
|
136
|
+
|
|
105
137
|
auto ranges_ = qdb::convert_ranges(ranges);
|
|
106
138
|
|
|
107
139
|
qdb_uint_t erased_count = 0;
|
|
@@ -149,6 +181,8 @@ void table::timestamp_insert(
|
|
|
149
181
|
std::pair<pybind11::array, masked_array> table::blob_get_ranges(
|
|
150
182
|
const std::string & column, py::object ranges)
|
|
151
183
|
{
|
|
184
|
+
_handle->check_open();
|
|
185
|
+
|
|
152
186
|
qdb_ts_blob_point * points = nullptr;
|
|
153
187
|
qdb_size_t count = 0;
|
|
154
188
|
|
|
@@ -167,6 +201,8 @@ std::pair<pybind11::array, masked_array> table::blob_get_ranges(
|
|
|
167
201
|
std::pair<pybind11::array, masked_array> table::string_get_ranges(
|
|
168
202
|
const std::string & column, py::object ranges)
|
|
169
203
|
{
|
|
204
|
+
_handle->check_open();
|
|
205
|
+
|
|
170
206
|
qdb_ts_string_point * points = nullptr;
|
|
171
207
|
qdb_size_t count = 0;
|
|
172
208
|
|
|
@@ -185,6 +221,8 @@ std::pair<pybind11::array, masked_array> table::string_get_ranges(
|
|
|
185
221
|
std::pair<pybind11::array, masked_array> table::double_get_ranges(
|
|
186
222
|
const std::string & column, py::object ranges)
|
|
187
223
|
{
|
|
224
|
+
_handle->check_open();
|
|
225
|
+
|
|
188
226
|
qdb_ts_double_point * points = nullptr;
|
|
189
227
|
qdb_size_t count = 0;
|
|
190
228
|
|
|
@@ -203,6 +241,8 @@ std::pair<pybind11::array, masked_array> table::double_get_ranges(
|
|
|
203
241
|
std::pair<pybind11::array, masked_array> table::int64_get_ranges(
|
|
204
242
|
const std::string & column, py::object ranges)
|
|
205
243
|
{
|
|
244
|
+
_handle->check_open();
|
|
245
|
+
|
|
206
246
|
qdb_ts_int64_point * points = nullptr;
|
|
207
247
|
qdb_size_t count = 0;
|
|
208
248
|
|
|
@@ -221,6 +261,8 @@ std::pair<pybind11::array, masked_array> table::int64_get_ranges(
|
|
|
221
261
|
std::pair<pybind11::array, masked_array> table::timestamp_get_ranges(
|
|
222
262
|
const std::string & column, py::object ranges)
|
|
223
263
|
{
|
|
264
|
+
_handle->check_open();
|
|
265
|
+
|
|
224
266
|
qdb_ts_timestamp_point * points = nullptr;
|
|
225
267
|
qdb_size_t count = 0;
|
|
226
268
|
|
quasardb/table.hpp
CHANGED
|
@@ -40,7 +40,7 @@ namespace qdb
|
|
|
40
40
|
class table : public entry
|
|
41
41
|
{
|
|
42
42
|
public:
|
|
43
|
-
table(handle_ptr h, std::string a)
|
|
43
|
+
table(handle_ptr h, std::string a)
|
|
44
44
|
: entry{h, a}
|
|
45
45
|
, _has_indexed_columns(false)
|
|
46
46
|
{
|
|
@@ -64,13 +64,17 @@ public:
|
|
|
64
64
|
void create(const std::vector<detail::column_info> & columns,
|
|
65
65
|
std::chrono::milliseconds shard_size = std::chrono::hours{24})
|
|
66
66
|
{
|
|
67
|
+
_handle->check_open();
|
|
68
|
+
|
|
67
69
|
const auto c_columns = detail::convert_columns_ex(columns);
|
|
68
70
|
qdb::qdb_throw_if_error(*_handle, qdb_ts_create_ex(*_handle, _alias.c_str(), shard_size.count(),
|
|
69
|
-
c_columns.data(), c_columns.size()));
|
|
71
|
+
c_columns.data(), c_columns.size(), qdb_ttl_disabled));
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
void insert_columns(const std::vector<detail::column_info> & columns)
|
|
73
75
|
{
|
|
76
|
+
_handle->check_open();
|
|
77
|
+
|
|
74
78
|
const auto c_columns = detail::convert_columns_ex(columns);
|
|
75
79
|
qdb::qdb_throw_if_error(*_handle,
|
|
76
80
|
qdb_ts_insert_columns_ex(*_handle, _alias.c_str(), c_columns.data(), c_columns.size()));
|
|
@@ -152,23 +156,7 @@ private:
|
|
|
152
156
|
/**
|
|
153
157
|
* Loads column info / metadata from server and caches it locally.
|
|
154
158
|
*/
|
|
155
|
-
void _cache_columns() const
|
|
156
|
-
{
|
|
157
|
-
detail::qdb_resource<qdb_ts_column_info_ex_t> columns{*_handle};
|
|
158
|
-
qdb_size_t count = 0;
|
|
159
|
-
|
|
160
|
-
auto err = qdb_ts_list_columns_ex(*_handle, _alias.c_str(), &columns, &count);
|
|
161
|
-
|
|
162
|
-
if (err == qdb_e_alias_not_found) [[unlikely]]
|
|
163
|
-
{
|
|
164
|
-
// Can happen if table does not yet exist, do nothing.
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
qdb::qdb_throw_if_error(*_handle, err);
|
|
169
|
-
|
|
170
|
-
_columns = detail::convert_columns(columns.get(), count);
|
|
171
|
-
}
|
|
159
|
+
void _cache_columns() const;
|
|
172
160
|
|
|
173
161
|
/**
|
|
174
162
|
* Loads column info / metadata from server if not yet cached locally.
|
quasardb/table_reader.hpp
CHANGED
|
@@ -88,8 +88,10 @@ public:
|
|
|
88
88
|
return _the_row;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
table_reader_iterator & operator++()
|
|
91
|
+
table_reader_iterator & operator++()
|
|
92
92
|
{
|
|
93
|
+
_handle->check_open();
|
|
94
|
+
|
|
93
95
|
qdb_error_t err = qdb_ts_table_next_row(_local_table, &_the_row.mutable_timestamp());
|
|
94
96
|
|
|
95
97
|
if (err == qdb_e_iterator_end)
|
|
@@ -144,6 +146,8 @@ public:
|
|
|
144
146
|
, _columns{c}
|
|
145
147
|
, _local_table{nullptr}
|
|
146
148
|
{
|
|
149
|
+
_handle->check_open();
|
|
150
|
+
|
|
147
151
|
auto c_columns = convert_columns(c);
|
|
148
152
|
|
|
149
153
|
qdb::qdb_throw_if_error(*_handle, qdb_ts_local_table_init(*_handle, t.c_str(), c_columns.data(),
|
quasardb/writer.cpp
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#include "writer.hpp"
|
|
2
2
|
#include "concepts.hpp"
|
|
3
3
|
#include "dispatch.hpp"
|
|
4
|
+
#include "metrics.hpp"
|
|
4
5
|
#include "numpy.hpp"
|
|
5
6
|
#include "traits.hpp"
|
|
6
7
|
#include "convert/array.hpp"
|
|
@@ -460,6 +461,8 @@ void writer::_push_impl(writer::staged_tables_t & staged_tables,
|
|
|
460
461
|
detail::deduplicate_options deduplicate_options,
|
|
461
462
|
qdb_ts_range_t * ranges)
|
|
462
463
|
{
|
|
464
|
+
_handle->check_open();
|
|
465
|
+
|
|
463
466
|
if (staged_tables.empty())
|
|
464
467
|
{
|
|
465
468
|
throw qdb::invalid_argument_exception{"No data written to batch writer."};
|
|
@@ -489,6 +492,9 @@ void writer::_push_impl(writer::staged_tables_t & staged_tables,
|
|
|
489
492
|
batch_table.data.column_count, table_name);
|
|
490
493
|
}
|
|
491
494
|
|
|
495
|
+
// Make sure to measure the time it takes to do the actual push
|
|
496
|
+
qdb::metrics::scoped_capture capture{"qdb_batch_push"};
|
|
497
|
+
|
|
492
498
|
qdb::qdb_throw_if_error(
|
|
493
499
|
*_handle, qdb_exp_batch_push(*_handle, mode, batch.data(), nullptr, batch.size()));
|
|
494
500
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
quasardb/CMakeLists.txt,sha256=
|
|
1
|
+
quasardb/CMakeLists.txt,sha256=Rdpd6_7EfVD7F81k7OgxH57cVFIGZzz57O2haCTSrs8,15237
|
|
2
2
|
quasardb/INSTALL.vcxproj,sha256=wXGzzzxKqlbKbm3sC-67s1p7BBbJHU2ToOIcyYKryk4,10405
|
|
3
3
|
quasardb/INSTALL.vcxproj.filters,sha256=Zi6Rf6BuzpXIana9k87Eha4xNbqM5Scj8SMuy1cBI7k,564
|
|
4
4
|
quasardb/__init__.py,sha256=S5HGH9idLoUES_9XSqHnEixEC6VKwzcubJlnVvWi22E,3801
|
|
5
|
-
quasardb/add_boost_test.cmake,sha256=A-r1WMqPO12BwWA1N-nGwtdemRWBNIOmH_eBy0pLn6w,1208
|
|
6
5
|
quasardb/batch_column.hpp,sha256=txW9kYMgQzJiJlM5nD7LIVuAZpyidpS4MopPGKE95u0,3388
|
|
7
6
|
quasardb/batch_inserter.hpp,sha256=bM73Z-IKow89GqoYaxDLDd0YuaN5Il4C5TjIVx9bI-Y,9803
|
|
8
7
|
quasardb/blob.hpp,sha256=PObdSJxKNLIihBCLBxQHHH20t7VOmZG02wOfy8rB1-w,5846
|
|
9
|
-
quasardb/cluster.
|
|
8
|
+
quasardb/cluster.cpp,sha256=ytPCLRZVA7eTZgqIbLWKsmiugYLq80v9rSuoksKTE3c,2500
|
|
9
|
+
quasardb/cluster.hpp,sha256=AYZY2myVI1eeG3Cxe7yCPb7Kmlh1Ij_go4ryZdIEJHc,19405
|
|
10
10
|
quasardb/cmake_install.cmake,sha256=xWyEkkQzuazTRxgmMiJa6JJ3UtWPMsU8oNIwF96u3WY,1500
|
|
11
11
|
quasardb/concepts.hpp,sha256=Ao-UKFVjh7kRqeqsYXioV1LXiKXBR_1l54hRvUCjxKU,9574
|
|
12
12
|
quasardb/continuous.cpp,sha256=18-VX7BZA60wkUq75ADU7yfgmwzT_CkG_tEAKxAVkLU,4566
|
|
@@ -18,41 +18,44 @@ quasardb/direct_integer.hpp,sha256=jHwNnAcB9wodgju8SBOsyPKWlifM094kENKSwySrSb8,3
|
|
|
18
18
|
quasardb/dispatch.hpp,sha256=YWqTq9ehXWpphJ9piWwrKUzy3IgA5d9An0loAYQsUlg,5508
|
|
19
19
|
quasardb/double.hpp,sha256=SW1z9QW09mC_8ggvleMZolivu2BHjF157IVKT_Jw638,3239
|
|
20
20
|
quasardb/entry.hpp,sha256=IE6uL341x6U5dos40LhVKSJPuYZwod-oRy4PoF5a_80,9451
|
|
21
|
-
quasardb/error.hpp,sha256=
|
|
21
|
+
quasardb/error.hpp,sha256=b3BvBn0wYqHlrkH48pZod6CMjtxFu6l7SQjt88zXlwc,10807
|
|
22
22
|
quasardb/firehose.py,sha256=DHYsew-aL1j5PKZonH30CrhXnwHEX1XIAhGbPrzd4PY,3593
|
|
23
|
-
quasardb/handle.
|
|
23
|
+
quasardb/handle.cpp,sha256=oyhzAj1k8UFhpLhwU5RL4cbdqt82KZexWacMFz5uXA0,536
|
|
24
|
+
quasardb/handle.hpp,sha256=o26dxmrXtfbxgj66QgKjW8wviUPbcZvmIAZ4L4CcdoQ,3051
|
|
24
25
|
quasardb/integer.hpp,sha256=H5x8SEqlyI2nQZL9iv4GnCL0uWYuq8l8YYUzI83t0aE,3304
|
|
25
|
-
quasardb/logger.cpp,sha256=
|
|
26
|
+
quasardb/logger.cpp,sha256=UThEO2V6UI-tbpG9suud7olmMjIMfHr3tNt-nM48DIE,3056
|
|
26
27
|
quasardb/logger.hpp,sha256=4trngfo31-OizuEkQUoYob77PVeXC283tPGaX3JRpPY,7278
|
|
27
28
|
quasardb/masked_array.hpp,sha256=nfuvkFZnNoGqqtJzBZ95h4e4PguhIr5kj3tVO4y8W4U,18988
|
|
28
|
-
quasardb/
|
|
29
|
+
quasardb/metrics.cpp,sha256=NuEBVYlIHQRgmPy4g9Eosq1Q28Z1jySSZHKDAMLURIA,2942
|
|
30
|
+
quasardb/metrics.hpp,sha256=oz_XDbcMCJ9fiaYi043rFakM-mmzsuONskDfMPDf4_U,3533
|
|
31
|
+
quasardb/module.cpp,sha256=Nx0d3xyqCb2Red1WgsGUotaXxX6NHoDCcp9PnUzmcB0,2236
|
|
29
32
|
quasardb/module.hpp,sha256=-zRcQ_lgVz4IEP3tokX4AeA33DYJ3jsq8vWX6OnE0Ic,604
|
|
30
33
|
quasardb/node.hpp,sha256=_rcwUA9mOFW7b7I3B3Ll3aaBO0RoKV3LS19JITaIi6A,4771
|
|
31
34
|
quasardb/numpy.cpp,sha256=0brRs6lnIpsCNvpu3twIcjizy3lMOvCBT0O4rjKAn0I,189
|
|
32
35
|
quasardb/numpy.hpp,sha256=j2xGIFn98L4AAirxnkF6JaAwUBL1McfUBNsf4tlKPA0,15668
|
|
33
36
|
quasardb/object_tracker.hpp,sha256=m0S0vp3WX2kFsr6cE8iPmXXO-3qRo4lcVc6TgFa-MbM,7709
|
|
34
|
-
quasardb/options.hpp,sha256=
|
|
37
|
+
quasardb/options.hpp,sha256=hXNBVTQdrDwWkxGyFBOuRGYyJoD_IpqpitJPbDnabi0,10158
|
|
35
38
|
quasardb/perf.hpp,sha256=C7dM0ZZZ4Ln5pDnZpvvUMgdwLUp4Tom51JuZICSYGGI,11364
|
|
36
39
|
quasardb/pool.py,sha256=lqVZPFejmNHU7EdyeoPkl7yy_-N3BRyuLhNTzIdtg8g,8743
|
|
37
40
|
quasardb/pytypes.hpp,sha256=YTc6xdmxMGMWtrZHitAl3vudZxYctOX1NwL-QDuzz1g,6894
|
|
38
|
-
quasardb/qdb_api.dll,sha256=
|
|
39
|
-
quasardb/quasardb.cp39-win_amd64.pyd,sha256=
|
|
40
|
-
quasardb/query.cpp,sha256=
|
|
41
|
+
quasardb/qdb_api.dll,sha256=JZRkdNtMmCDpr7_ZSkHYX1PWi3N5fH74SSh0D-7RWMk,15067136
|
|
42
|
+
quasardb/quasardb.cp39-win_amd64.pyd,sha256=QKiV_3n0uKZopH3b2QqWacBlCp9etVGmWfMVELgm9Rw,1329152
|
|
43
|
+
quasardb/query.cpp,sha256=FhsA93s-mXqw6WnzQgYLooy02P-haTEHkTMpdgMbdKw,12752
|
|
41
44
|
quasardb/query.hpp,sha256=dBFJ0FVNJN-WdCwbHU1iNbEzDHarGGDQaZ5gto-xwkY,3357
|
|
42
45
|
quasardb/remove_cvref.hpp,sha256=vKUecNoA2-BIiZeP8NuO3GgBOMF-OVSn_43LJCuDozA,611
|
|
43
46
|
quasardb/stats.py,sha256=LDV4F5KTpEXa5sS_syFo_TYn9_W2X1D32Eb43GLutOs,7620
|
|
44
47
|
quasardb/string.hpp,sha256=xgvRf1TXy3nl45WeCHHhtO8toUYZ2Zo7RuvTAntIgZM,6071
|
|
45
|
-
quasardb/table.cpp,sha256=
|
|
46
|
-
quasardb/table.hpp,sha256=
|
|
48
|
+
quasardb/table.cpp,sha256=_LAltQoycIzkqg4Id4u5MHN9Uy4OD-wWZMtdxzReMDs,10725
|
|
49
|
+
quasardb/table.hpp,sha256=bu3n9jjNW_dH01vbXkCbl4TmwfbyQS_0a4_fitbcrUI,10941
|
|
47
50
|
quasardb/table_cache.py,sha256=t7FFQkms7pFlYDkOhCcLnLS8bWglZjlzX3Qs6gyBG6Q,1559
|
|
48
|
-
quasardb/table_reader.hpp,sha256=
|
|
51
|
+
quasardb/table_reader.hpp,sha256=UYqpLtdMFr4MKho0A9y6sKb1-KoNLtYPdypl6zOrwm0,6941
|
|
49
52
|
quasardb/tag.hpp,sha256=gIs8LDa4o0JJBGuSQXsnyVeORax7KH0jHCyt0Zx6JMs,2732
|
|
50
53
|
quasardb/timestamp.hpp,sha256=f2TLql7D-gTQbJMUdC9QKbHpbnkMPoDi0dHAF2IVrqc,3889
|
|
51
54
|
quasardb/traits.hpp,sha256=RLSJBeZbFsWRQAsZSm6GbV2a2-5jounsJ_TX0iSvyHI,16383
|
|
52
55
|
quasardb/ts_iterator.hpp,sha256=faP1HVGYbWubKr98yhkS6gqvyMiKWkl3tgedJfj2u1E,4395
|
|
53
56
|
quasardb/utils.cpp,sha256=PkuVxrj1cQfeVujA-kefx9-P0B6IJNtYDQzedCAMjKY,634
|
|
54
57
|
quasardb/utils.hpp,sha256=ZedlY9Ahdphyi8tm2CySYb2k1RJTaDFqDBy3dvg-rJ8,4724
|
|
55
|
-
quasardb/writer.cpp,sha256=
|
|
58
|
+
quasardb/writer.cpp,sha256=5jPLFvOcJydiyBSbbtB-SDspKVoXcV9squEOQLuOvp0,19571
|
|
56
59
|
quasardb/writer.hpp,sha256=08S7HDgdCajNSwro4i0i1lzyvUkHFh6M1vn8TJpAz_A,12933
|
|
57
60
|
quasardb/CMakeFiles/generate.stamp,sha256=MC9-mgyGPAS3QAZa3gHSQ8dYfXJy_Hn7AChwEoqVWOs,55
|
|
58
61
|
quasardb/CMakeFiles/generate.stamp.depend,sha256=uY8FV-ceJ2Kk-6JfOnsIesDV7jKoUNfkKHNY2Nf7_E8,117
|
|
@@ -108,8 +111,8 @@ quasardb/utils/ostream.hpp,sha256=KYFwqXuZoxuZblHUM-z5xrd74P2Y5zWJqVpaQ9oedAo,39
|
|
|
108
111
|
quasardb/utils/permutation.hpp,sha256=BwJzgZmpS4G-oS7249GvnUFj_cmqSAbF2Fzb8wuihLo,1552
|
|
109
112
|
quasardb/utils/stable_sort.hpp,sha256=luIK9T76mT0NyDxpLxXjTt1eSSKEOY29jRANJNysJCo,489
|
|
110
113
|
quasardb/utils/unzip_view.hpp,sha256=nn6BSAI_cGsKgBh8WXhAUJ6Zzn3N0AnhtE6ePmhPeQM,2476
|
|
111
|
-
quasardb-3.14.1.
|
|
112
|
-
quasardb-3.14.1.
|
|
113
|
-
quasardb-3.14.1.
|
|
114
|
-
quasardb-3.14.1.
|
|
115
|
-
quasardb-3.14.1.
|
|
114
|
+
quasardb-3.14.1.dev6.dist-info/LICENSE.md,sha256=yqGeNifkwT_AQEPv0TwLxEdD9TgORqUjS01rgzG5EGY,1477
|
|
115
|
+
quasardb-3.14.1.dev6.dist-info/METADATA,sha256=E41lG6VbSKiA00UKf7Xkp6_zRTbJhIxReJ3HZs62N-o,1496
|
|
116
|
+
quasardb-3.14.1.dev6.dist-info/WHEEL,sha256=J_4V_gB-O6Y7Pn6lk91K27JaIhI-q07YM5J8Ufzqla4,100
|
|
117
|
+
quasardb-3.14.1.dev6.dist-info/top_level.txt,sha256=wlprix4hCywuF1PkgKWYdZeJKq_kgJOqkAvukm_sZQ8,9
|
|
118
|
+
quasardb-3.14.1.dev6.dist-info/RECORD,,
|
quasardb/add_boost_test.cmake
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
function(add_boost_test_executable NAME COMPONENT)
|
|
2
|
-
add_executable(${NAME}
|
|
3
|
-
${ARGN}
|
|
4
|
-
)
|
|
5
|
-
|
|
6
|
-
# set_target_properties(${NAME} PROPERTIES
|
|
7
|
-
# DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
|
8
|
-
|
|
9
|
-
target_link_libraries(${NAME}
|
|
10
|
-
boost_unit_test_framework
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
if($<CONFIG:SanitizeValgrind>)
|
|
14
|
-
add_test(
|
|
15
|
-
NAME ${NAME}
|
|
16
|
-
COMMAND
|
|
17
|
-
valgrind>
|
|
18
|
-
$<$<PLATFORM_ID:Darwin>:--dsymutil=yes>
|
|
19
|
-
--gen-suppressions=all
|
|
20
|
-
./${NAME}
|
|
21
|
-
--log_level=test_suite
|
|
22
|
-
--report_level=detailed
|
|
23
|
-
--build_info=yes
|
|
24
|
-
--detect_memory_leaks=0
|
|
25
|
-
)
|
|
26
|
-
else()
|
|
27
|
-
add_test(
|
|
28
|
-
NAME ${NAME}
|
|
29
|
-
COMMAND
|
|
30
|
-
${NAME}
|
|
31
|
-
--log_level=test_suite
|
|
32
|
-
--report_level=detailed
|
|
33
|
-
--build_info=yes
|
|
34
|
-
--detect_memory_leaks=0
|
|
35
|
-
)
|
|
36
|
-
endif()
|
|
37
|
-
|
|
38
|
-
install(TARGETS ${NAME}
|
|
39
|
-
RUNTIME DESTINATION bin COMPONENT ${COMPONENT}
|
|
40
|
-
LIBRARY DESTINATION lib COMPONENT ${COMPONENT}
|
|
41
|
-
ARCHIVE DESTINATION lib COMPONENT ${COMPONENT}
|
|
42
|
-
)
|
|
43
|
-
endfunction()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|