This is an automated email from the ASF dual-hosted git repository.
hxd pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 48c5488 [ISSUE-2919] Fix C++ client memory leak bug (#2937)
48c5488 is described below
commit 48c5488195c17b49cdaac0116a4754e0cad702b2
Author: wshao08 <[email protected]>
AuthorDate: Thu Apr 1 14:42:22 2021 +0800
[ISSUE-2919] Fix C++ client memory leak bug (#2937)
---
client-cpp/src/main/Session.cpp | 30 +-
client-cpp/src/main/Session.h | 27 +-
example/client-cpp-example/src/SessionExample.cpp | 329 +++++++++++-----------
3 files changed, 195 insertions(+), 191 deletions(-)
diff --git a/client-cpp/src/main/Session.cpp b/client-cpp/src/main/Session.cpp
index 176af63..dccf784 100644
--- a/client-cpp/src/main/Session.cpp
+++ b/client-cpp/src/main/Session.cpp
@@ -251,13 +251,12 @@ bool SessionDataSet::hasNext()
}
void SessionDataSet::constructOneRow() {
- vector<Field*> outFields;
+ vector<Field> outFields;
int loc = 0;
- Field* field;
for (int i = 0; i < columnSize; i++) {
-
+ Field field;
if (duplicateLocation.find(i) != duplicateLocation.end()) {
- field = new Field(*outFields[duplicateLocation[i]]);
+ field = outFields[duplicateLocation[i]];
} else {
MyStringBuffer *bitmapBuffer = bitmapBuffers[loc].get();
// another new 8 row, should move the bitmap buffer position to
next byte
@@ -268,36 +267,36 @@ void SessionDataSet::constructOneRow() {
if (!isNull(loc, rowsIndex)) {
MyStringBuffer *valueBuffer = valueBuffers[loc].get();
TSDataType::TSDataType dataType =
getTSDataTypeFromString(columnTypeDeduplicatedList[loc]);
- field = new Field(dataType);
+ field.dataType = dataType;
switch (dataType) {
case TSDataType::BOOLEAN: {
bool booleanValue = valueBuffer->getBool();
- field->boolV = booleanValue;
+ field.boolV = booleanValue;
break;
}
case TSDataType::INT32: {
int intValue = valueBuffer->getInt();
- field->intV = intValue;
+ field.intV = intValue;
break;
}
case TSDataType::INT64: {
int64_t longValue = valueBuffer->getLong();
- field->longV = longValue;
+ field.longV = longValue;
break;
}
case TSDataType::FLOAT: {
float floatValue = valueBuffer->getFloat();
- field->floatV = floatValue;
+ field.floatV = floatValue;
break;
}
case TSDataType::DOUBLE: {
double doubleValue = valueBuffer->getDouble();
- field->doubleV = doubleValue;
+ field.doubleV = doubleValue;
break;
}
case TSDataType::TEXT: {
string stringValue = valueBuffer->getString();
- field->stringV = stringValue;
+ field.stringV = stringValue;
break;
}
default: {
@@ -307,7 +306,7 @@ void SessionDataSet::constructOneRow() {
}
}
} else {
- field = new Field(TSDataType::NULLTYPE);
+ field.dataType = TSDataType::NULLTYPE;
}
loc++;
}
@@ -1125,7 +1124,7 @@ void Session::setTimeZone(string zoneId)
this->zoneId = zoneId;
}
-SessionDataSet* Session::executeQueryStatement(string sql)
+unique_ptr<SessionDataSet> Session::executeQueryStatement(string sql)
{
shared_ptr<TSExecuteStatementReq> req(new TSExecuteStatementReq());
req->__set_sessionId(sessionId);
@@ -1143,7 +1142,8 @@ SessionDataSet* Session::executeQueryStatement(string sql)
throw IoTDBConnectionException(e.what());
}
shared_ptr<TSQueryDataSet> queryDataSet(new
TSQueryDataSet(resp->queryDataSet));
- return new SessionDataSet(sql, resp->columns, resp->dataTypeList,
resp->queryId, client, sessionId, queryDataSet);
+ return unique_ptr<SessionDataSet>(new SessionDataSet(
+ sql, resp->columns, resp->dataTypeList, resp->queryId, client,
sessionId, queryDataSet));
}
void Session::executeNonQueryStatement(string sql)
@@ -1162,4 +1162,4 @@ void Session::executeNonQueryStatement(string sql)
{
throw IoTDBConnectionException(e.what());
}
-}
\ No newline at end of file
+}
diff --git a/client-cpp/src/main/Session.h b/client-cpp/src/main/Session.h
index 45ee51c..4e8aba7 100644
--- a/client-cpp/src/main/Session.h
+++ b/client-cpp/src/main/Session.h
@@ -427,12 +427,12 @@ class RowRecord
{
public:
int64_t timestamp;
- std::vector<Field*> fields;
+ std::vector<Field> fields;
RowRecord(int64_t timestamp)
{
this->timestamp = timestamp;
}
- RowRecord(int64_t timestamp, std::vector<Field*> fields) {
+ RowRecord(int64_t timestamp, std::vector<Field> &fields) {
this->timestamp = timestamp;
this->fields = fields;
}
@@ -440,6 +440,11 @@ public:
{
this->timestamp = -1;
}
+
+ void addField(Field &f) {
+ this->fields.push_back(f);
+ }
+
std::string toString()
{
char buf[111];
@@ -448,40 +453,40 @@ public:
for (int i = 0; i < fields.size(); i++)
{
ret.append("\t");
- TSDataType::TSDataType dataType = fields[i]->dataType;
+ TSDataType::TSDataType dataType = fields[i].dataType;
switch (dataType)
{
case TSDataType::BOOLEAN:{
- if (fields[i]->boolV) ret.append("true");
+ if (fields[i].boolV) ret.append("true");
else ret.append("false");
break;
}
case TSDataType::INT32:{
char buf[111];
- sprintf(buf,"%d",fields[i]->intV);
+ sprintf(buf,"%d",fields[i].intV);
ret.append(buf);
break;
}
case TSDataType::INT64: {
char buf[111];
- sprintf(buf,"%lld",fields[i]->longV);
+ sprintf(buf,"%lld",fields[i].longV);
ret.append(buf);
break;
}
case TSDataType::FLOAT:{
char buf[111];
- sprintf(buf,"%f",fields[i]->floatV);
+ sprintf(buf,"%f",fields[i].floatV);
ret.append(buf);
break;
}
case TSDataType::DOUBLE:{
char buf[111];
- sprintf(buf,"%lf",fields[i]->doubleV);
+ sprintf(buf,"%lf",fields[i].doubleV);
ret.append(buf);
break;
}
case TSDataType::TEXT: {
- ret.append(fields[i]->stringV);
+ ret.append(fields[i].stringV);
break;
}
case TSDataType::NULLTYPE:{
@@ -659,6 +664,6 @@ class Session
void createMultiTimeseries(std::vector<std::string> paths,
std::vector<TSDataType::TSDataType> dataTypes,
std::vector<TSEncoding::TSEncoding> encodings,
std::vector<CompressionType::CompressionType> compressors,
std::vector<std::map<std::string, std::string>>* propsList,
std::vector<std::map<std::string, std::string>>* tagsList,
std::vector<std::map<std::string, std::string>>* attributesList,
std::vector<std::string>* measurementAliasList);
bool checkTimeseriesExists(std::string path);
- SessionDataSet* executeQueryStatement(std::string sql);
+ std::unique_ptr<SessionDataSet> executeQueryStatement(std::string sql);
void executeNonQueryStatement(std::string sql);
-};
\ No newline at end of file
+};
diff --git a/example/client-cpp-example/src/SessionExample.cpp
b/example/client-cpp-example/src/SessionExample.cpp
index e39e937..f0c5453 100644
--- a/example/client-cpp-example/src/SessionExample.cpp
+++ b/example/client-cpp-example/src/SessionExample.cpp
@@ -39,203 +39,202 @@ void createTimeseries() {
// create timeseries with tags and attributes
if (!session->checkTimeseriesExists("root.sg1.d1.s4")) {
- map<string, string> tags;
- tags["tag1"] = "v1";
- map<string, string> attributes;
- attributes["description"] = "v1";
- session->createTimeseries("root.sg1.d1.s4", TSDataType::INT64,
TSEncoding::RLE,
- CompressionType::SNAPPY, NULL, &tags, &attributes, "temperature");
+ map<string, string> tags;
+ tags["tag1"] = "v1";
+ map<string, string> attributes;
+ attributes["description"] = "v1";
+ session->createTimeseries("root.sg1.d1.s4", TSDataType::INT64,
TSEncoding::RLE,
+ CompressionType::SNAPPY, NULL, &tags, &attributes, "temperature");
}
}
void createMultiTimeseries() {
- if (!session->checkTimeseriesExists("root.sg1.d2.s1") &&
!session->checkTimeseriesExists("root.sg1.d2.s1")) {
- vector<string> paths;
- paths.push_back("root.sg1.d2.s1");
- paths.push_back("root.sg1.d2.s2");
- vector<TSDataType::TSDataType> tsDataTypes;
- tsDataTypes.push_back(TSDataType::INT64);
- tsDataTypes.push_back(TSDataType::INT64);
- vector<TSEncoding::TSEncoding> tsEncodings;
- tsEncodings.push_back(TSEncoding::RLE);
- tsEncodings.push_back(TSEncoding::RLE);
- vector<CompressionType::CompressionType> compressionTypes;
- compressionTypes.push_back(CompressionType::SNAPPY);
- compressionTypes.push_back(CompressionType::SNAPPY);
-
- vector<map<string,string>> tagsList;
- map<string,string> tags;
- tags["unit"] = "kg";
- tagsList.push_back(tags);
- tagsList.push_back(tags);
-
- vector<map<string,string>> attributesList;
- map<string,string> attributes;
- attributes["minValue"] = "1";
- attributes["maxValue"] = "100";
- attributesList.push_back(attributes);
- attributesList.push_back(attributes);
-
- vector<string> alias;
- alias.push_back("weight1");
- alias.push_back("weight2");
-
- session->createMultiTimeseries(paths, tsDataTypes, tsEncodings,
compressionTypes, NULL, &tagsList, &attributesList, &alias);
- }
+ if (!session->checkTimeseriesExists("root.sg1.d2.s1") &&
!session->checkTimeseriesExists("root.sg1.d2.s1")) {
+ vector<string> paths;
+ paths.push_back("root.sg1.d2.s1");
+ paths.push_back("root.sg1.d2.s2");
+ vector<TSDataType::TSDataType> tsDataTypes;
+ tsDataTypes.push_back(TSDataType::INT64);
+ tsDataTypes.push_back(TSDataType::INT64);
+ vector<TSEncoding::TSEncoding> tsEncodings;
+ tsEncodings.push_back(TSEncoding::RLE);
+ tsEncodings.push_back(TSEncoding::RLE);
+ vector<CompressionType::CompressionType> compressionTypes;
+ compressionTypes.push_back(CompressionType::SNAPPY);
+ compressionTypes.push_back(CompressionType::SNAPPY);
+
+ vector<map<string,string>> tagsList;
+ map<string,string> tags;
+ tags["unit"] = "kg";
+ tagsList.push_back(tags);
+ tagsList.push_back(tags);
+
+ vector<map<string,string>> attributesList;
+ map<string,string> attributes;
+ attributes["minValue"] = "1";
+ attributes["maxValue"] = "100";
+ attributesList.push_back(attributes);
+ attributesList.push_back(attributes);
+
+ vector<string> alias;
+ alias.push_back("weight1");
+ alias.push_back("weight2");
+
+ session->createMultiTimeseries(paths, tsDataTypes, tsEncodings,
compressionTypes, NULL, &tagsList, &attributesList, &alias);
+ }
}
void insertRecord() {
- string deviceId = "root.sg1.d1";
- vector<string> measurements;
- measurements.push_back("s1");
- measurements.push_back("s2");
- measurements.push_back("s3");
- for (int64_t time = 0; time < 100; time++) {
- vector<string> values;
- values.push_back("11");
- values.push_back("22");
- values.push_back("33");
- session->insertRecord(deviceId, time, measurements, values);
- }
+ string deviceId = "root.sg1.d1";
+ vector<string> measurements;
+ measurements.push_back("s1");
+ measurements.push_back("s2");
+ measurements.push_back("s3");
+ for (int64_t time = 0; time < 100; time++) {
+ vector<string> values;
+ values.push_back("11");
+ values.push_back("22");
+ values.push_back("33");
+ session->insertRecord(deviceId, time, measurements, values);
+ }
}
void insertTablet() {
- pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
- pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
- pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
- vector<pair<string, TSDataType::TSDataType>> schemas;
- schemas.push_back(pairA);
- schemas.push_back(pairB);
- schemas.push_back(pairC);
-
- Tablet tablet("root.sg1.d1", schemas, 100);
-
- for (int64_t time = 0; time < 100; time++) {
- int row = tablet.rowSize++;
- tablet.timestamps[row] = time;
- for (int i = 0; i < 3; i++) {
- tablet.values[i][row] = to_string(i);
+ pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
+ pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
+ pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
+ vector<pair<string, TSDataType::TSDataType>> schemas;
+ schemas.push_back(pairA);
+ schemas.push_back(pairB);
+ schemas.push_back(pairC);
+
+ Tablet tablet("root.sg1.d1", schemas, 100);
+
+ for (int64_t time = 0; time < 100; time++) {
+ int row = tablet.rowSize++;
+ tablet.timestamps[row] = time;
+ for (int i = 0; i < 3; i++) {
+ tablet.values[i][row] = to_string(i);
+ }
+ if (tablet.rowSize == tablet.maxRowNumber) {
+ session->insertTablet(tablet, true);
+ tablet.reset();
+ }
}
- if (tablet.rowSize == tablet.maxRowNumber) {
- session->insertTablet(tablet, true);
- tablet.reset();
- }
- }
- if (tablet.rowSize != 0) {
- session->insertTablet(tablet);
- tablet.reset();
- }
+ if (tablet.rowSize != 0) {
+ session->insertTablet(tablet);
+ tablet.reset();
+ }
}
void insertTablets() {
- pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
- pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
- pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
- vector<pair<string, TSDataType::TSDataType>> schemas;
- schemas.push_back(pairA);
- schemas.push_back(pairB);
- schemas.push_back(pairC);
-
- Tablet tablet1("root.sg1.d1", schemas, 100);
- Tablet tablet2("root.sg1.d2", schemas, 100);
- Tablet tablet3("root.sg1.d3", schemas, 100);
-
- map<string, Tablet*> tabletMap;
- tabletMap["root.sg1.d1"] = &tablet1;
- tabletMap["root.sg1.d2"] = &tablet2;
- tabletMap["root.sg1.d3"] = &tablet3;
-
- for (int64_t time = 0; time < 100; time++) {
- int row1 = tablet1.rowSize++;
- int row2 = tablet2.rowSize++;
- int row3 = tablet3.rowSize++;
- tablet1.timestamps[row1] = time;
- tablet2.timestamps[row2] = time;
- tablet3.timestamps[row3] = time;
-
- for (int i = 0; i < 3; i++) {
- tablet1.values[i][row1] = to_string(i);
- tablet2.values[i][row1] = to_string(i);
- tablet3.values[i][row1] = to_string(i);
+ pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
+ pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
+ pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
+ vector<pair<string, TSDataType::TSDataType>> schemas;
+ schemas.push_back(pairA);
+ schemas.push_back(pairB);
+ schemas.push_back(pairC);
+
+ Tablet tablet1("root.sg1.d1", schemas, 100);
+ Tablet tablet2("root.sg1.d2", schemas, 100);
+ Tablet tablet3("root.sg1.d3", schemas, 100);
+
+ map<string, Tablet*> tabletMap;
+ tabletMap["root.sg1.d1"] = &tablet1;
+ tabletMap["root.sg1.d2"] = &tablet2;
+ tabletMap["root.sg1.d3"] = &tablet3;
+
+ for (int64_t time = 0; time < 100; time++) {
+ int row1 = tablet1.rowSize++;
+ int row2 = tablet2.rowSize++;
+ int row3 = tablet3.rowSize++;
+ tablet1.timestamps[row1] = time;
+ tablet2.timestamps[row2] = time;
+ tablet3.timestamps[row3] = time;
+
+ for (int i = 0; i < 3; i++) {
+ tablet1.values[i][row1] = to_string(i);
+ tablet2.values[i][row1] = to_string(i);
+ tablet3.values[i][row1] = to_string(i);
+ }
+ if (tablet1.rowSize == tablet1.maxRowNumber) {
+ session->insertTablets(tabletMap, true);
+
+ tablet1.reset();
+ tablet2.reset();
+ tablet3.reset();
+ }
}
- if (tablet1.rowSize == tablet1.maxRowNumber) {
- session->insertTablets(tabletMap, true);
- tablet1.reset();
- tablet2.reset();
- tablet3.reset();
+ if (tablet1.rowSize != 0) {
+ session->insertTablets(tabletMap, true);
+ tablet1.reset();
+ tablet2.reset();
+ tablet3.reset();
}
- }
-
- if (tablet1.rowSize != 0) {
- session->insertTablets(tabletMap, true);
- tablet1.reset();
- tablet2.reset();
- tablet3.reset();
- }
}
void insertRecords() {
- string deviceId = "root.sg1.d1";
- vector<string> measurements;
- measurements.push_back("s1");
- measurements.push_back("s2");
- measurements.push_back("s3");
-
- vector<string> deviceIds;
- vector<vector<string>> measurementsList;
- vector<vector<string>> valuesList;
- vector<int64_t> timestamps;
- vector<string>* values;
-
- for (int64_t time = 0; time < 500; time++) {
- values = new vector<string>();
- values->push_back("1");
- values->push_back("2");
- values->push_back("3");
-
- deviceIds.push_back(deviceId);
- measurementsList.push_back(measurements);
- valuesList.push_back(*values);
- timestamps.push_back(time);
- if (time != 0 && time % 100 == 0) {
- session->insertRecords(deviceIds, timestamps, measurementsList,
valuesList);
- deviceIds.clear();
- measurementsList.clear();
- valuesList.clear();
- timestamps.clear();
- }
+ string deviceId = "root.sg1.d1";
+ vector<string> measurements;
+ measurements.push_back("s1");
+ measurements.push_back("s2");
+ measurements.push_back("s3");
+
+ vector<string> deviceIds;
+ vector<vector<string>> measurementsList;
+ vector<vector<string>> valuesList;
+ vector<int64_t> timestamps;
+ vector<string>* values;
+
+ for (int64_t time = 0; time < 500; time++) {
+ values = new vector<string>();
+ values->push_back("1");
+ values->push_back("2");
+ values->push_back("3");
+
+ deviceIds.push_back(deviceId);
+ measurementsList.push_back(measurements);
+ valuesList.push_back(*values);
+ timestamps.push_back(time);
+ if (time != 0 && time % 100 == 0) {
+ session->insertRecords(deviceIds, timestamps, measurementsList,
valuesList);
+ deviceIds.clear();
+ measurementsList.clear();
+ valuesList.clear();
+ timestamps.clear();
+ }
}
session->insertRecords(deviceIds, timestamps, measurementsList,
valuesList);
}
void nonQuery() {
- session->executeNonQueryStatement("insert into root.sg1.d1(timestamp,s1)
values(200, 1);");
+ session->executeNonQueryStatement("insert into root.sg1.d1(timestamp,s1)
values(200, 1);");
}
void query() {
- SessionDataSet* dataSet;
- dataSet = session->executeQueryStatement("select * from root.sg1.d1");
- cout << "timestamp" << " ";
- for (string name : dataSet->getColumnNames()) {
- cout << name << " ";
- }
- cout << endl;
- dataSet->setBatchSize(1024);
- while (dataSet->hasNext())
- {
- cout << dataSet->next()->toString();
- }
-
- dataSet->closeOperationHandle();
+ unique_ptr<SessionDataSet> dataSet =
session->executeQueryStatement("select * from root.sg1.d1");
+ cout << "timestamp" << " ";
+ for (string name : dataSet->getColumnNames()) {
+ cout << name << " ";
+ }
+ cout << endl;
+ dataSet->setBatchSize(1024);
+ while (dataSet->hasNext())
+ {
+ cout << dataSet->next()->toString();
+ }
+
+ dataSet->closeOperationHandle();
}
void deleteData() {
- string path = "root.sg1.d1.s1";
- int64_t deleteTime = 99;
- session->deleteData(path, deleteTime);
+ string path = "root.sg1.d1.s1";
+ int64_t deleteTime = 99;
+ session->deleteData(path, deleteTime);
}
void deleteTimeseries() {
@@ -256,7 +255,7 @@ void deleteTimeseries() {
}
void queryLast() {
- SessionDataSet *dataSet = session->executeQueryStatement("select last
s1,s2,s3 from root.sg1.d1");
+ unique_ptr<SessionDataSet> dataSet =
session->executeQueryStatement("select last s1,s2,s3 from root.sg1.d1");
for (string name: dataSet->getColumnNames()) {
cout << name << " ";
}