2
2
#include " chdb.h"
3
3
4
4
#include < sys/resource.h>
5
+ #include " Common/Logger.h"
5
6
#include < Common/Config/getLocalConfigPath.h>
6
7
#include < Common/logger_useful.h>
7
8
#include < Common/formatReadable.h>
56
57
#include < boost/program_options/options_description.hpp>
57
58
#include < base/argsToConfig.h>
58
59
#include < filesystem>
60
+ #include < math.h>
59
61
60
62
#include " config.h"
61
63
@@ -1289,7 +1291,7 @@ void free_result_v2(local_result_v2 * result)
1289
1291
1290
1292
chdb_conn ** connect_chdb (int argc, char ** argv)
1291
1293
{
1292
- std::lock_guard<std::mutex> glock (global_connection_mutex);
1294
+ std::lock_guard<std::mutex> global_lock (global_connection_mutex);
1293
1295
1294
1296
std::string path = " :memory:" ; // Default path
1295
1297
for (int i = 1 ; i < argc; i++)
@@ -1349,27 +1351,26 @@ chdb_conn ** connect_chdb(int argc, char ** argv)
1349
1351
auto * queue = static_cast <query_queue *>(conn->queue );
1350
1352
while (true )
1351
1353
{
1352
- auto result = std::make_unique<local_result_v2>();
1353
- try
1354
+ query_request req;
1354
1355
{
1355
- query_request req;
1356
- {
1357
- std::unique_lock<std::mutex> lock (queue->mutex );
1358
- queue->cv .wait (lock, [queue]() { return !queue->queries .empty () || queue->shutdown ; });
1359
-
1360
- if (queue->shutdown && queue->queries .empty ())
1361
- {
1362
- server->cleanup ();
1363
- delete server;
1364
- queue->cleanup_done = true ;
1365
- queue->cv .notify_all ();
1366
- break ;
1367
- }
1356
+ std::unique_lock<std::mutex> lock (queue->mutex );
1357
+ queue->query_cv .wait (lock, [queue]() { return queue->has_query || queue->shutdown ; });
1368
1358
1369
- req = queue->queries .front ();
1370
- queue->queries .pop ();
1359
+ if (queue->shutdown )
1360
+ {
1361
+ server->cleanup ();
1362
+ delete server;
1363
+ queue->cleanup_done = true ;
1364
+ queue->query_cv .notify_all ();
1365
+ break ;
1371
1366
}
1372
1367
1368
+ req = queue->current_query ;
1369
+ }
1370
+
1371
+ auto result = std::make_unique<local_result_v2>();
1372
+ try
1373
+ {
1373
1374
if (!server->parseQueryTextWithOutputFormat (req.query , req.format ))
1374
1375
{
1375
1376
std::string error = server->getErrorMsg ();
@@ -1378,11 +1379,12 @@ chdb_conn ** connect_chdb(int argc, char ** argv)
1378
1379
}
1379
1380
else
1380
1381
{
1381
- auto output_span = server->getQueryOutputSpan ();
1382
- if (!output_span. empty () )
1382
+ auto * query_output_vec = server->stealQueryOutputVector ();
1383
+ if (query_output_vec )
1383
1384
{
1384
- result->buf = output_span.data ();
1385
- result->len = output_span.size ();
1385
+ result->_vec = query_output_vec;
1386
+ result->len = query_output_vec->size ();
1387
+ result->buf = query_output_vec->data ();
1386
1388
}
1387
1389
result->rows_read = server->getProcessedRows ();
1388
1390
result->bytes_read = server->getProcessedBytes ();
@@ -1404,9 +1406,10 @@ chdb_conn ** connect_chdb(int argc, char ** argv)
1404
1406
1405
1407
{
1406
1408
std::lock_guard<std::mutex> lock (queue->mutex );
1407
- queue->results .push (result.release ());
1409
+ queue->current_result = result.release ();
1410
+ queue->has_query = false ;
1408
1411
}
1409
- queue->cv .notify_one ();
1412
+ queue->result_cv .notify_one ();
1410
1413
}
1411
1414
}
1412
1415
catch (...)
@@ -1425,8 +1428,8 @@ chdb_conn ** connect_chdb(int argc, char ** argv)
1425
1428
// Wait for initialization to complete
1426
1429
{
1427
1430
std::unique_lock<std::mutex> init_lock (init_mutex);
1428
- init_cv.wait (init_lock, [&init_done] { return init_done; });
1429
- // If initialization failed, clean up and rethrow the exception
1431
+ init_cv.wait (init_lock, [&init_done]() { return init_done; });
1432
+
1430
1433
if (!init_success)
1431
1434
{
1432
1435
delete q_queue;
@@ -1442,11 +1445,11 @@ chdb_conn ** connect_chdb(int argc, char ** argv)
1442
1445
1443
1446
void close_conn (chdb_conn ** conn)
1444
1447
{
1448
+ std::lock_guard<std::mutex> global_lock (global_connection_mutex);
1449
+
1445
1450
if (!conn || !*conn)
1446
1451
return ;
1447
1452
1448
- std::lock_guard<std::mutex> lock (global_connection_mutex);
1449
-
1450
1453
if ((*conn)->connected )
1451
1454
{
1452
1455
if ((*conn)->queue )
@@ -1456,20 +1459,23 @@ void close_conn(chdb_conn ** conn)
1456
1459
{
1457
1460
std::unique_lock<std::mutex> queue_lock (queue->mutex );
1458
1461
queue->shutdown = true ;
1459
- queue->cv .notify_all ();
1462
+ queue->query_cv .notify_all (); // Wake up query processing thread
1463
+ queue->result_cv .notify_all (); // Wake up any waiting result threads
1460
1464
1461
1465
// Wait for server cleanup
1462
- queue->cv .wait (queue_lock, [queue] { return queue->cleanup_done ; });
1466
+ queue->query_cv .wait (queue_lock, [queue] { return queue->cleanup_done ; });
1463
1467
1464
- // Clean up remaining results
1465
- while (! queue->results . empty () )
1468
+ // Clean up current result if any
1469
+ if ( queue->current_result )
1466
1470
{
1467
- auto * result = queue->results .front ();
1468
- queue->results .pop ();
1469
- free_result_v2 (result);
1471
+ free_result_v2 (queue->current_result );
1472
+ queue->current_result = nullptr ;
1470
1473
}
1471
1474
}
1472
1475
1476
+ // Mark as disconnected before deleting queue
1477
+ (*conn)->connected = false ;
1478
+
1473
1479
delete queue;
1474
1480
(*conn)->queue = nullptr ;
1475
1481
}
@@ -1487,29 +1493,50 @@ void close_conn(chdb_conn ** conn)
1487
1493
1488
1494
struct local_result_v2 * query_conn (chdb_conn * conn, const char * query, const char * format)
1489
1495
{
1496
+ std::lock_guard<std::mutex> global_lock (global_connection_mutex);
1497
+
1490
1498
if (!conn || !conn->connected || !conn->queue )
1491
1499
return new local_result_v2{nullptr , 0 , nullptr , 0 , 0 , 0 , nullptr };
1492
1500
1493
1501
auto * queue = static_cast <query_queue *>(conn->queue );
1494
1502
1495
1503
{
1496
- std::lock_guard<std::mutex> lock (queue->mutex );
1497
- queue->queries .push ({query, format});
1504
+ std::unique_lock<std::mutex> lock (queue->mutex );
1505
+ // Wait until any ongoing query completes
1506
+ queue->query_cv .wait (lock, [queue]() { return !queue->has_query || queue->shutdown ; });
1507
+
1508
+ if (queue->shutdown )
1509
+ {
1510
+ auto * result = new local_result_v2{};
1511
+ const char * error = " Connection is shutting down" ;
1512
+ result->error_message = new char [strlen (error) + 1 ];
1513
+ std::strcpy (result->error_message , error);
1514
+ return result;
1515
+ }
1516
+
1517
+ queue->current_query = {query, format};
1518
+ queue->has_query = true ;
1519
+ queue->current_result = nullptr ;
1498
1520
}
1499
- queue->cv .notify_one ();
1521
+ queue->query_cv .notify_one ();
1500
1522
1501
1523
local_result_v2 * result = nullptr ;
1502
1524
{
1503
1525
std::unique_lock<std::mutex> lock (queue->mutex );
1504
- queue->cv .wait (lock, [queue]() { return ! queue->results . empty () || queue->shutdown ; });
1526
+ queue->result_cv .wait (lock, [queue]() { return queue->current_result != nullptr || queue->shutdown ; });
1505
1527
1506
- if (!queue->shutdown && ! queue->results . empty () )
1528
+ if (!queue->shutdown && queue->current_result )
1507
1529
{
1508
- result = queue->results .front ();
1509
- queue->results .pop ();
1530
+ result = queue->current_result ;
1531
+ if (result->len == 0 )
1532
+ {
1533
+ LOG_WARNING (getLogger (" CHDB" ), " Empty result returned for query: {}" , query);
1534
+ }
1535
+ queue->current_result = nullptr ;
1510
1536
}
1511
1537
}
1512
1538
1539
+ queue->query_cv .notify_one ();
1513
1540
if (result == nullptr )
1514
1541
{
1515
1542
result = new local_result_v2{};
0 commit comments