diff --git a/.gitignore b/.gitignore
index 55b0d1f8..dfaf72db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
build/
db/
*.gcov
+**/__pycache__/
# VS Code Specific
.devcontainer
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b629dde3..afda38bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,10 +40,30 @@ else()
link_directories(/usr/local/lib /usr/lib/x86_64-linux-gnu/)
include_directories(/usr/include/jsoncpp utils/include/ src/pmgd/include src/pmgd/util include/ src/vcl /usr/include ${CMAKE_CURRENT_BINARY_DIR}/utils/src/protobuf)
- add_library(dms SHARED src/BoundingBoxCommand.cc src/CommunicationManager.cc src/DescriptorsCommand.cc src/DescriptorsManager.cc src/ExceptionsCommand.cc src/ImageCommand.cc src/PMGDIterators.cc src/PMGDQuery.cc src/PMGDQueryHandler.cc src/QueryHandler.cc src/QueryMessage.cc src/RSCommand.cc src/SearchExpression.cc src/Server.cc src/VDMSConfig.cc src/VideoCommand.cc src/AutoDeleteNode.cc ${PROTO_SRCS} ${PROTO_HDRS})
+ add_library(dms SHARED
+ src/BoundingBoxCommand.cc
+ src/BlobCommand.cc
+ src/CommunicationManager.cc
+ src/DescriptorsCommand.cc
+ src/DescriptorsManager.cc
+ src/ExceptionsCommand.cc
+ src/ImageCommand.cc
+ src/PMGDIterators.cc
+ src/PMGDQuery.cc
+ src/PMGDQueryHandler.cc
+ src/QueryHandler.cc
+ src/QueryMessage.cc
+ src/RSCommand.cc
+ src/SearchExpression.cc
+ src/Server.cc
+ src/VDMSConfig.cc
+ src/VideoCommand.cc
+ src/AutoDeleteNode.cc
+ ${PROTO_SRCS} ${PROTO_HDRS}
+ )
target_link_libraries(dms vcl pmgd pmgd-util protobuf vdms-utils pthread)
add_executable(vdms src/vdms.cc)
target_link_libraries(vdms dms vdms_protobuf vcl tiledb faiss flinng jsoncpp ${OpenCV_LIBS})
-endif ()
+endif ()
diff --git a/INSTALL.md b/INSTALL.md
index 6439df9d..a35b876c 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -2,126 +2,117 @@
Here is the detailed process of installation of VDMS dependencies.
## Dependencies
-Here we will install the Ubuntu 20.04 packages.
+Here we will install the Ubuntu 20.04 and Python3 packages. We assume `python`/`pip` is an alias for `python3`/`pip3`. If your system has both Python 2 and Python 3, please replace all pip and python commands with pip3 and python3, respectively.
```bash
-apt-get update
-apt-get -y install software-properties-common
-add-apt-repository "deb http://security.ubuntu.com/ubuntu focal-security main"
-apt-get -y install apt-transport-https autoconf automake bison build-essential \
- bzip2 ca-certificates curl ed flex g++ git gnupg-agent javacc libarchive-tools \
+sudo apt-get update
+sudo apt-get -y install --no-install-recommends software-properties-common
+sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu focal-security main"
+sudo apt-get -y install --no-install-recommends apt-transport-https autoconf automake bison build-essential \
+ bzip2 ca-certificates curl=7.68.0-1ubuntu2.18 ed flex g++ git gnupg-agent javacc libarchive-tools \
libatlas-base-dev libavcodec-dev libavformat-dev libboost-all-dev libbz2-dev \
libc-ares-dev libdc1394-22-dev libgflags-dev libgoogle-glog-dev libgtest-dev \
libgtk-3-dev libgtk2.0-dev libhdf5-serial-dev libjpeg-dev libjpeg8-dev libjsoncpp-dev \
libleveldb-dev liblmdb-dev liblz4-dev libopenblas-dev libopenmpi-dev \
libpng-dev librdkafka-dev libsnappy-dev libssl-dev libswscale-dev libtbb-dev \
- libtbb2 libtiff-dev libtiff5-dev libtool maven mpich openjdk-11-jdk-headless \
- pkg-config python python-dev python3-pip unzip wget
-pip3 install numpy
+ libtbb2 libtiff-dev libtiff5-dev libtool mpich openjdk-11-jdk-headless \
+ pkg-config python3-dev python3-pip unzip
+pip install --no-cache-dir "numpy>=1.23.2" "setuptools>=65.5.1"
```
### Clone/Download Dependencies
-Here we clone the repositories for grpc v1.40.0, libpng12, Swig v4.0.2, OpenCV 4.5.3, Valijson v0.6, CMake v3.21.2, Faiss v1.7.1, and FLINNG. Then download necesarry files for zlib v1.2.12, Json-simple v1.1.1, and TileDB v1.3.1.
-Here we assume `/` is the working directory. This is important when installing the dependencies.
+Here we clone the repositories for grpc v1.40.0, libpng12, Swig v4.0.2, OpenCV 4.5.3, Valijson v0.6, CMake v3.21.2, Faiss v1.7.1, and FLINNG. Then download necesarry files for zlib v1.2.13, Json-simple v1.1.1, and TileDB v1.3.1.
+Here we assume `$VDMS_DEP_DIR` is the working directory for installing dependencies and `python` is Python 3.
```bash
-git clone --branch v1.40.0 https://github.com/grpc/grpc.git && \
-git clone --branch v4.0.2 https://github.com/swig/swig.git && \
-git clone --branch 4.5.3 https://github.com/opencv/opencv.git && \
-git clone --branch v0.6 https://github.com/tristanpenman/valijson.git && \
+cd $VDMS_DEP_DIR
git clone --branch v3.21.2 https://github.com/Kitware/CMake.git && \
+git clone --branch v4.0.2 https://github.com/swig/swig.git && \
git clone --branch v1.7.1 https://github.com/facebookresearch/faiss.git && \
-git clone https://github.com/tonyzhang617/FLINNG.git
+git clone https://github.com/tonyzhang617/FLINNG.git && \
+git clone --recurse-submodules -b v1.40.0 https://github.com/grpc/grpc.git && \
+git clone --branch 4.5.3 https://github.com/opencv/opencv.git && \
+git clone --branch v0.6 https://github.com/tristanpenman/valijson.git
-curl http://zlib.net/zlib-1.2.12.tar.gz -o zlib-1.2.12.tar.gz && \
-curl https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/json-simple/json-simple-1.1.1.jar \
- -o /usr/share/java/json-simple-1.1.1.jar && \
-wget https://github.com/TileDB-Inc/TileDB/archive/1.3.1.tar.gz
+sudo curl -L -o /usr/share/java/json-simple-1.1.1.jar https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/json-simple/json-simple-1.1.1.jar && \
+sudo curl -L -o 1.3.1.tar.gz https://github.com/TileDB-Inc/TileDB/archive/refs/tags/1.3.1.tar.gz && \
+sudo curl -L -o zlib-1.2.13.tar.gz http://zlib.net/zlib-1.2.13.tar.gz
```
### Install Dependencies
These instructions assume you have full permissions to your system.
-If needed, use `sudo` where necessary.
+If running as root, remove `sudo` where necessary.
+
#### CMAKE
```bash
-cd /CMake && ./bootstrap
-make -j && make install
+cd $VDMS_DEP_DIR/CMake && ./bootstrap
+make -j && sudo make install
```
### Swig
```bash
-cd /swig
+cd $VDMS_DEP_DIR/swig
./autogen.sh && ./configure
-make -j && make install
+make -j && sudo make install
```
### Faiss
```bash
-cd /faiss
+cd $VDMS_DEP_DIR/faiss
mkdir build && cd build
cmake -DFAISS_ENABLE_GPU=OFF ..
-make -j && make install
+make -j && sudo make install
```
### FLINNG
```bash
-cd /FLINNG
+cd $VDMS_DEP_DIR/FLINNG
mkdir build && cd build
cmake ..
-make -j && make install
+make -j && sudo make install
```
### grpc
```bash
-cd /grpc && git submodule update --init --recursive
-cd third_party/protobuf/cmake && mkdir build && cd build
+cd $VDMS_DEP_DIR/grpc
+pip install --no-cache-dir -r requirements.txt
+GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install --no-cache-dir .
+
+cd tools/distrib/python/grpcio_tools
+python ../make_grpcio_tools.py
+GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install --no-cache-dir .
+
+cd $VDMS_DEP_DIR/grpc/third_party/zlib/ && mkdir build && cd build
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE ..
-make -j && make install
+make -j && sudo make install
+
+cd $VDMS_DEP_DIR/grpc/third_party/protobuf/cmake
+mkdir build && cd build
+cmake -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -Dprotobuf_BUILD_TESTS=OFF ..
+make -j && sudo make install
cd ../../../abseil-cpp && mkdir build && cd build
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE ..
-make -j && make install
+make -j && sudo make install
cd ../../re2/ && mkdir build && cd build
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE ..
-make -j && make install
+make -j && sudo make install
-cd ../../zlib/ && mkdir build && cd build
-cmake -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE ..
-make -j && make install
-
-cd /grpc/cmake && mkdir build && cd build
+cd $VDMS_DEP_DIR/grpc/cmake && mkdir build && cd build
cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DgRPC_ABSL_PROVIDER=package \
-DgRPC_CARES_PROVIDER=package -DgRPC_PROTOBUF_PROVIDER=package \
-DgRPC_RE2_PROVIDER=package -DgRPC_SSL_PROVIDER=package \
-DgRPC_ZLIB_PROVIDER=package -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE ../..
-make -j && make install
-```
-
-### Zlib
-```bash
-cd / && gunzip zlib-1.2.12.tar.gz && tar -xvf zlib-1.2.12.tar
-cd zlib-1.2.12 && ./configure
-make -j && make install
-cd / && rm -rf zlib-1.2.12.tar zlib-1.2.12
-```
-
-### gtest
-Unfortunately apt doesn't build gtest;
-you need to do the following steps to get it to work correctly:
-```bash
-cd /usr/src/gtest/
-cmake .
-make -j
-mv lib/libgtest* /usr/lib
+make -j && sudo make install
```
### [OpenCV](https://opencv.org/)
Below are instructions for installing ***OpenCV v4.5.3***. It may also work with newer versions of OpenCV.
```bash
-cd /opencv
+cd $VDMS_DEP_DIR/opencv
mkdir build && cd build
-cmake -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local ..
+cmake -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF ..
make -j
-make install
+sudo make install
```
**Note**: When using videos, and getting the following error: "Unable to stop the stream: Inappropriate ioctl for device", you may need to include more flags when compiling OpenCV. Follow these instructions ([source](https://stackoverflow.com/questions/41200201/opencv-unable-to-stop-the-stream-inappropriate-ioctl-for-device)):
@@ -137,66 +128,58 @@ make -j
make install
```
+### Zlib
+```bash
+cd $VDMS_DEP_DIR && tar -xvzf zlib-1.2.13.tar.gz
+cd zlib-1.2.13 && ./configure
+make -j && sudo make install
+```
+
### [TileDB](https://tiledb.io/)
VDMS works with ***TileDB v1.3.1.***
The directions below will help you install TileDB v1.3.1 from the source.
You can also follow the directions listed
[here](https://docs.tiledb.io/en/latest/installation.html).
```bash
-cd / && tar xf 1.3.1.tar.gz && rm 1.3.1.tar.gz
+cd $VDMS_DEP_DIR && tar -xvf 1.3.1.tar.gz
cd TileDB-1.3.1 && mkdir build && cd build
../bootstrap --prefix=/usr/local/
-make -j && make install-tiledb
-rm -rf /TileDB-1.3.1
+make -j && sudo make install-tiledb
```
-### Maven
+### gtest
+Unfortunately apt doesn't build gtest;
+you need to do the following steps to get it to work correctly:
```bash
-ln -s /grpc/third_party/protobuf/cmake/build/protoc grpc/third_party/protobuf/src/protoc
-cd /grpc/third_party/protobuf/java/core
-mvn package
-cp target/protobuf-java-3.13.0.jar /usr/share/java/protobuf.jar
-```
-
-You may need to change proxy setting for Maven if you are behind a proxy like this example.
-Add setting.xml file to ~/.m2 folder
-```
-
-
- optional
-
- https
-
- prox-address
- proxy-port
-
-
-
+cd /usr/src/gtest/
+sudo cmake .
+sudo make -j
+sudo mv lib/libgtest* /usr/lib
```
### Valijson
This is a headers-only library, no compilation/installation necessary
```bash
-cd /valijson
-cp -r include/* /usr/local/include
+cd $VDMS_DEP_DIR/valijson
+sudo cp -r include/* /usr/local/include
```
## Install VDMS
+This version of VDMS treats PMGD as a submodule so both libraries are compiled at one time. After entering the vdms directory, the command `git submodule update --init --recursive` will pull pmgd into the appropriate directory. Furthermore, Cmake is used to compile all directories.
```bash
git clone https://github.com/IntelLabs/vdms.git
cd vdms && git checkout develop
git submodule update --init --recursive
+```
+
+When compiling on a target without Optane persistent memory, use the following:
+```bash
mkdir build && cd build
cmake ..
make -j
cp ../config-vdms.json .
```
-
-### Compilation
-This version of VDMS treats PMGD as a submodule so both libraries are compiled at one time. After entering the vdms directory, the command `git submodule update --init --recursive` will pull pmgd into the appropriate directory. Furthermore, Cmake is used to compile all directories.
-
When compiling on a target with Optane persistent memory, use the command set:
```bash
mkdir build && cd build
@@ -204,9 +187,3 @@ cmake -DCMAKE_CXX_FLAGS='-DPM' ..
make -j
```
-For systems without Optane, use the command set:
-```bash
-mkdir build && cd build
-cmake ..
-make -j
-```
diff --git a/Security.md b/Security.md
new file mode 100644
index 00000000..ccbbdc59
--- /dev/null
+++ b/Security.md
@@ -0,0 +1,5 @@
+# Security Policy
+Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation.
+
+## Reporting a Vulnerability
+Please report any security vulnerabilities in this project [utilizing the guidelines here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html).
diff --git a/client/cpp/BoundingBoxQueryParser.h b/client/cpp/BoundingBoxQueryParser.h
new file mode 100644
index 00000000..63c3e7d0
--- /dev/null
+++ b/client/cpp/BoundingBoxQueryParser.h
@@ -0,0 +1,109 @@
+#include "CSVParserUtil.h"
+namespace VDMS {
+class BoundingBoxQueryParser : public CSVParserUtil{
+ private:
+ vector rectangleKeys{"x","y","w","h"};
+ void parseRectangle(string row,string queryType,Json::Value &aquery);
+ public:
+ VDMS::Response ParseAddBoundingBox(vector row, vector cols);
+ // VDMS::Response ParseUpdateBoundingBox(vector row, vector& cols);
+
+};
+};
+
+VDMS::Response VDMS::BoundingBoxQueryParser::ParseAddBoundingBox(vector row, vector columnNames){
+ if (row.empty() || row[0].empty()) {
+ throw "please provide rectangle details";
+ }
+
+ Json::Value aquery;
+ Json::Value allquery;
+ std::string command_name = "AddBoundingBox";
+
+ aquery["AddBoundingBox"]["_ref"] = 1;
+ // aquery["AddBoundingBox"]["image"] = 3;
+
+ Json::Value aqueryf;
+ // aqueryf["FindImage"]["_ref"] = 3;
+
+ parseRectangle(row[0], "AddBoundingBox", aquery);
+
+ for (int j = 1; j < columnNames.size(); j++){
+ const string& columnName = columnNames[j];
+ const string& cellValue = row[j];
+
+ if (cellValue.empty()) {
+ continue;
+ }
+
+ if (columnName.find("prop_") != string::npos){
+ parseProperty(columnName, cellValue, command_name, aquery);
+ }
+ // else if (columnName.find("cons_") != string::npos){
+ // std::string find_image = "FindImage";
+ // parseConstraints(columnName, cellValue, find_image, aqueryf);
+ // }
+ }
+
+ // allquery.append(aqueryf);
+
+ allquery.append(aquery);
+ return send_to_vdms(allquery);
+}
+
+
+void VDMS::BoundingBoxQueryParser::parseRectangle(string row, string queryType, Json::Value& aquery) {
+ Json::Value rec;
+ string::size_type start = 0;
+ for (int c = 0; c < 4; c++) {
+ string::size_type end = row.find(',', start);
+ if (end == string::npos && c < 3) {
+ throw "rectangle data should have four values";
+ }
+ string substr = row.substr(start, end - start);
+ try {
+ int intVal = stoi(substr);
+ rec[rectangleKeys[c]] = intVal;
+ } catch (const invalid_argument&) {
+ try {
+ float floatVal = stof(substr);
+ rec[rectangleKeys[c]] = floatVal;
+ } catch (const invalid_argument&) {
+ throw "invalid datatype of the rectangle data";
+ }
+ }
+
+ start = end + 1;
+ }
+ aquery[queryType]["rectangle"] = rec;
+}
+
+// VDMS::Response VDMS::BoundingBoxQueryParser::ParseUpdateBoundingBox(vector row, vector& columnNames){
+// Json::Value aquery;
+// Json::Value allquery;
+// aquery["UpdateBoundingBox"]["_ref"]=3;
+// std::string command_name="UpdateBoundingBox";
+// if(row[0]!=""){
+// parseRectangle(row[0],command_name,aquery);
+// }
+// for(int j=1;j rowvec;
+// splitRowOnComma(row[j],rowvec);
+// for(int v=0;v
+#include
+#include
+#include
+#include
+#include
+#include "rapidcsv.h"
+#include "CSVParserUtil.h"
+
+namespace VDMS {
+class CSVParser {
+public:
+ CSVParser(std::string filename, size_t num_threads, std::string server, int port) : m_filename(filename), m_num_threads(num_threads),vdms_server(server),vdms_port(port) {}
+ std::vector parse_csv_lines(const std::string& filename, int start_line, int end_line, std::mutex& mutex, std::vector& all_results, const size_t thread_id)
+ {
+ rapidcsv::Document csv(filename);
+
+ size_t rowCount = csv.GetRowCount();
+ std::vector columnNames = csv.GetColumnNames();
+ VDMS::CSVParserUtil csv_util(vdms_server, vdms_port, columnNames, static_cast(thread_id));
+ for (int i = start_line; i < end_line; ++i)
+ {
+ std::vector row = csv.GetRow(i);
+ VDMS::Response result = csv_util.parse_row(row);
+
+ std::lock_guard lock(mutex);
+ all_results.push_back(result);
+ }
+
+ return all_results;
+ }
+std::vector parse() {
+ auto start = std::chrono::high_resolution_clock::now();
+
+ std::ifstream file(m_filename);
+ if (!file) {
+ std::cerr << "Error opening file\n";
+
+ }
+
+ int num_lines = std::count(std::istreambuf_iterator(file), std::istreambuf_iterator(), '\n');
+ std::size_t lines_per_thread = num_lines / m_num_threads;
+
+ std::mutex mutex;
+ std::vector threads;
+ std::vector all_results;
+
+ for (size_t i = 0; i < m_num_threads; i++) {
+ size_t start_line = i * lines_per_thread;
+ size_t end_line = (i == m_num_threads - 1) ? num_lines-1 : (i + 1) * lines_per_thread;
+
+ threads.emplace_back(&CSVParser::parse_csv_lines, this, std::ref(m_filename), start_line, end_line, std::ref(mutex),std::ref(all_results), i);
+ }
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ auto finish = std::chrono::high_resolution_clock::now();
+ std::chrono::duration elapsed = finish - start;
+ std::cout << "Elapsed time: " << elapsed.count() << " s\n";
+ return all_results;
+ }
+
+private:
+ std::string m_filename;
+ size_t m_num_threads;
+ std::string vdms_server;
+ int vdms_port;
+
+
+ };
+};
\ No newline at end of file
diff --git a/client/cpp/CSVParserUtil.cpp b/client/cpp/CSVParserUtil.cpp
new file mode 100644
index 00000000..75041c9f
--- /dev/null
+++ b/client/cpp/CSVParserUtil.cpp
@@ -0,0 +1,635 @@
+
+#include
+#include
+#include "CSVParserUtil.h"
+#include "rapidcsv.h"
+#include "EntityQueryParser.h"
+#include "ImageQueryParser.h"
+#include "VideoQueryParser.h"
+#include "DescriptorQueryParser.h"
+#include "DescriptorSetQueryParser.h"
+#include "BoundingBoxQueryParser.h"
+#include "ConnectionQueryParser.h"
+#include
+static std::mutex barrier;
+std::mutex mtx;
+using namespace std;
+using namespace std::chrono;
+using namespace VDMS;
+
+VDMS::CSVParserUtil::CSVParserUtil() : vdms_server("localhost"), vdms_port(55558),
+ vdms_client(std::unique_ptr(new VDMS::VDMSClient(vdms_server, vdms_port)))
+{
+ initCommandsMap();
+}
+
+VDMS::CSVParserUtil::CSVParserUtil(const std::string &server, int port, const std::vector columnNames, int index) : vdms_server(server),
+ vdms_port(port),
+ _columnNames(columnNames),
+ id(index), vdms_client(std::unique_ptr(new VDMS::VDMSClient(vdms_server, vdms_port)))
+{
+ initCommandsMap();
+}
+void VDMS::CSVParserUtil::initCommandsMap()
+{
+ commands = {
+ {"EntityClass", EntityClass},
+ {"ConnectionClass", ConnectionClass},
+ {"ImagePath", ImagePath},
+ {"VideoPath", VideoPath},
+ {"DescriptorType", DescriptorType},
+ {"DescriptorClass", DescriptorClass},
+ {"RectangleBound", RectangleBound},
+ {"EntityUpdate", EntityUpdate},
+ {"ConnectionUpdate", ConnectionUpdate},
+ {"ImageUpdate", ImageUpdate},
+ {"RectangleUpdate", RectangleUpdate}};
+}
+string VDMS::CSVParserUtil::function_accessing_columnNames(int i)
+{
+ std::lock_guard lock(mtx);
+
+ return _columnNames[i];
+}
+VDMS::Response VDMS::CSVParserUtil::parse_row(std::vector &row)
+{
+ VDMS::Response result;
+
+ VDMS::CSVParserUtil::commandType queryType = get_query_type(_columnNames[0]);
+ switch (queryType)
+ {
+ case commandType::AddEntity:
+ {
+ EntityQueryParser entityquery;
+ result = entityquery.ParseAddEntity(row, _columnNames);
+ }
+
+ break;
+ case commandType::AddConnection:
+ {
+
+ ConnectionQueryParser connectionquery;
+ result = connectionquery.ParseAddConnection(row, _columnNames);
+ }
+ break;
+
+ case commandType::AddImage:
+ {
+ ImageQueryParser imagequery;
+ result = imagequery.ParseAddImage(row, _columnNames);
+ }
+ break;
+ case commandType::AddVideo:
+ {
+ VideoQueryParser videoquery;
+ result = videoquery.ParseAddVideo(row, _columnNames);
+ }
+ break;
+ case commandType::AddDescriptorSet:
+ {
+ DescriptorSetQueryParser descriptorsetquery;
+
+ result = descriptorsetquery.ParseAddDescriptorSet(row, _columnNames);
+ }
+ break;
+ case commandType::AddDescriptor:
+ {
+ DescriptorQueryParser descriptorquery;
+ result = descriptorquery.ParseAddDescriptor(row, _columnNames, id);
+ }
+ break;
+ case commandType::AddBoundingBox:
+ {
+ BoundingBoxQueryParser boundingboxquery;
+ result = boundingboxquery.ParseAddBoundingBox(row, _columnNames);
+ }
+ break;
+ // case commandType::UpdateEntity:{
+ // EntityQueryParser update_entityquery;
+ // update_entityquery.ParseUpdateEntity(row, _columnNames);
+ // }
+ // break;
+ // case commandType::UpdateConnection:{
+ // ConnectionQueryParser update_connectionquery;
+ // update_connectionquery.ParseUpdateConnection(row,allquery,i+1,_columnNames);
+ // }
+ // break;
+ // case commandType::UpdateImage:{
+ // ImageQueryParser update_image_query;
+ // update_image_query.ParseUpdateImage(row,allquery,i+1,_columnNames);
+ // }
+ // break;
+ // case commandType::UpdateBoundingBox:{
+ // BoundingBoxQueryParser update_boundingboxquery;
+ // update_boundingboxquery.ParseUpdateBoundingBox(row,allquery,i+1,_columnNames);
+ // }
+ // break;
+ case commandType::UNKNOWN:{
+ Json::Value results;
+ results["status"] = -1;
+ results["info"] = "Command does not exist";
+ result.json = results.toStyledString();
+ }
+ break;
+ }
+ return result;
+}
+
+int VDMS::CSVParserUtil::isBool(const std::string &s)
+{
+ std::string lower = s;
+ std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+ if (lower == "true")
+ return 1;
+ else if (lower == "false")
+ return 2;
+ return 0;
+}
+
+bool VDMS::CSVParserUtil::isFloat(const std::string &s)
+{
+ std::istringstream ss(s);
+ float x;
+ char c;
+ return (ss >> x) && !(ss >> c);
+}
+
+bool VDMS::CSVParserUtil::isInt(const std::string &s)
+{
+ std::istringstream ss(s);
+ int x;
+ char c;
+ return (ss >> x) && (floor(x)) && !(ss >> c);
+}
+
+VDMS::CSVParserUtil::commandType VDMS::CSVParserUtil::get_query_type(const string &str)
+{
+ CSVParserUtil::commandType querytype = commandType::UNKNOWN;
+
+ std::lock_guard lock(CSVParserUtil::querytype_mutex);
+ std::map::iterator iter;
+ iter = commands.find(str);
+ if (iter != commands.end()) {
+ switch (commands[str])
+ {
+ case EntityClass:
+ querytype = commandType::AddEntity;
+ break;
+ case ConnectionClass:
+ querytype = commandType::AddConnection;
+ break;
+ case ImagePath:
+ querytype = commandType::AddImage;
+ break;
+ case VideoPath:
+ querytype = commandType::AddVideo;
+ break;
+ case DescriptorType:
+ querytype = commandType::AddDescriptorSet;
+ break;
+ case DescriptorClass:
+ querytype = commandType::AddDescriptor;
+ break;
+ case RectangleBound:
+ querytype = commandType::AddBoundingBox;
+ break;
+ }
+ // std::cout << " I executed queryType "<< querytype << std::endl;
+ // return querytype;
+ }
+
+ return querytype;
+}
+
+VDMS::CSVParserUtil::DATATYPE VDMS::CSVParserUtil::getDataType(const string &str, const string &propname)
+{
+ if (propname.substr(0, 5) == "date:")
+ return DATATYPE::DATE;
+ else if (isInt(str))
+ return DATATYPE::INTEGER;
+ else if (isFloat(str))
+ return DATATYPE::FLOAT;
+ else if (isBool(str) == 1)
+ return DATATYPE::TRUE;
+ else if (isBool(str) == 2)
+ return DATATYPE::FALSE;
+ else
+ return DATATYPE::STRING;
+}
+
+void VDMS::CSVParserUtil::parseProperty(const string &columnNames, const string &row, const string &queryType, Json::Value &aquery)
+{
+ std::lock_guard lock(CSVParserUtil::aquery_mutex);
+ string propname = columnNames.substr(5, string::npos);
+ // std::cout << "Inside parseProp " << propname < lock(CSVParserUtil::cons_mutex);
+ vector consvals = spiltrow(row);
+ string consname = consvals[0];
+ if (consname.substr(0, 5) == "date:")
+ {
+ for (int z = 1; z < consvals.size(); z++)
+ {
+ if (z % 2 == 1)
+ {
+ aquery[queryType]["constraints"][consname.substr(5, string::npos)].append(consvals[z]);
+ }
+ else
+ {
+ Json::Value date;
+ date["_date"] = consvals[z];
+ aquery[queryType]["constraints"][consname.substr(5, string::npos)].append(date);
+ }
+ }
+ }
+ else
+ {
+ for (int z = 1; z < consvals.size(); z++)
+ {
+ CSVParserUtil::DATATYPE dtype = getDataType(consvals[z], consname);
+ if (dtype == DATATYPE::TRUE)
+ {
+ aquery[queryType]["constraints"][consname].append(true);
+ }
+ else if (dtype == DATATYPE::FALSE)
+ {
+ aquery[queryType]["constraints"][consname].append(false);
+ }
+ else if (dtype == DATATYPE::INTEGER)
+ {
+ aquery[queryType]["constraints"][consname].append(stoi(consvals[z]));
+ }
+ else if (dtype == DATATYPE::FLOAT)
+ {
+ aquery[queryType]["constraints"][consname].append(stof(consvals[z]));
+ }
+ else
+ {
+ aquery[queryType]["constraints"][consname].append(consvals[z]);
+ }
+ }
+ }
+}
+
+vector VDMS::CSVParserUtil::spiltrow(const string &str)
+{
+ string row = str;
+ vector rowv;
+ int start = 0;
+ for (int i = 0; i < row.size(); i++)
+ {
+ if ((row[i] == '<') || (row[i] == '>') || (row[i] == '='))
+ {
+ if (row[i + 1] == '=')
+ {
+ rowv.push_back(row.substr(start, i - start));
+ rowv.push_back(row.substr(i, 2));
+ i++;
+ }
+ else
+ {
+ rowv.push_back(row.substr(start, i - start));
+ rowv.push_back(row.substr(i, 1));
+ }
+ start = i + 1;
+ }
+ else if (row[i] == ',')
+ {
+ row.erase(i, 1);
+ i--;
+ }
+ }
+ rowv.push_back(row.substr(start, string::npos));
+ return rowv;
+}
+void VDMS::CSVParserUtil::parseOperations(string columnNames, string row, string queryType, Json::Value &aquery)
+{
+
+ std::lock_guard lock(CSVParserUtil::ops_mutex);
+ string type = columnNames.substr(4, string::npos);
+ Json::Value opsjson;
+ vector opsKeys;
+ if (isValidOpsType(type))
+ opsjson["type"] = type;
+ else
+ throw "invalid operation command name";
+ vector rowvec;
+ int c;
+ splitRowOnComma(row, rowvec);
+ if (type == "crop")
+ {
+ if (rowvec.size() <= 3 || rowvec.size() > 4)
+ throw "For crop data should be of size 4";
+ opsKeys = {"x", "y", "width", "height"};
+ for (c = 0; c < rowvec.size(); c++)
+ {
+ string substr = rowvec[c];
+ DATATYPE dType = isValidDataType(substr, 2);
+
+ if (dType == DATATYPE::INTEGER)
+ opsjson[opsKeys[c]] = stoi(substr);
+ else if (dType == DATATYPE::FLOAT)
+ opsjson[opsKeys[c]] = stof(substr);
+
+ else
+ {
+ throw "Numeric data is required for crop command";
+ }
+ }
+ }
+
+ else if (type == "threshold")
+ {
+ DATATYPE dType = isValidDataType(row, 2);
+ if (dType == DATATYPE::INTEGER)
+ opsjson["value"] = stoi(row);
+ else if (dType == DATATYPE::FLOAT)
+ opsjson["value"] = stof(row);
+
+ else
+ {
+ throw "Numeric data is required for resize command";
+ }
+ }
+
+ else if (type == "resize")
+ {
+ if (rowvec.size() <= 1 || rowvec.size() > 2)
+ throw "For resize data should be of size 2";
+ opsKeys = {"width", "height"};
+ for (c = 0; c < rowvec.size(); c++)
+ {
+ string substr = rowvec[c];
+ DATATYPE dType = isValidDataType(substr, 2);
+
+ if (dType == DATATYPE::INTEGER)
+ opsjson[opsKeys[c]] = stoi(substr);
+ else if (dType == DATATYPE::FLOAT)
+ opsjson[opsKeys[c]] = stof(substr);
+
+ else
+ {
+ throw "Numeric data is required for resize command";
+ }
+ }
+ }
+
+ else if (type == "flip")
+ {
+ DATATYPE dType = isValidDataType(row, 2);
+ if (dType == DATATYPE::INTEGER)
+ {
+ opsjson["code"] = stoi(row);
+ }
+ else
+ {
+ throw "Numeric data is required for flip command";
+ }
+ }
+
+ else if (type == "rotate")
+ {
+ if (rowvec.size() <= 1 || rowvec.size() > 2)
+ throw "For rotate data should be of size 2";
+ opsKeys = {"angle", "resize"};
+ for (c = 0; c < rowvec.size(); c++)
+ {
+ string substr = rowvec[c];
+ if (c == 0)
+ {
+ DATATYPE dType = isValidDataType(substr, 2);
+ if (dType == DATATYPE::INTEGER)
+ opsjson[opsKeys[c]] = stoi(substr);
+ else if (dType == DATATYPE::FLOAT)
+ opsjson[opsKeys[c]] = stof(substr);
+
+ else
+ {
+ throw "Numeric data is required for resize command";
+ }
+ }
+ else if (c == 1)
+ {
+ DATATYPE dType = isValidDataType(substr, 1);
+ if (dType == DATATYPE::TRUE)
+ opsjson[opsKeys[c]] = true;
+ else if (dType == DATATYPE::FALSE)
+ opsjson[opsKeys[c]] = false;
+
+ else
+ {
+ throw "Boolean data is required for rotate resize";
+ }
+ }
+ }
+ }
+
+ else if (type == "interval")
+ {
+ if (rowvec.size() <= 2 || rowvec.size() > 3)
+ throw "interval operation has 3 values to specify";
+ opsKeys = {"start", "stop", "step"};
+ for (c = 0; c < rowvec.size(); c++)
+ {
+ string substr = rowvec[c];
+ DATATYPE dType = isValidDataType(substr, 2);
+ if (dType == DATATYPE::INTEGER)
+ {
+ opsjson[opsKeys[c]] = stoi(substr);
+ }
+ else
+ {
+ throw "Numeric datatype is required for the interval";
+ }
+ }
+ }
+
+ aquery[queryType]["operations"].append(opsjson);
+}
+
+void VDMS::CSVParserUtil::splitRowOnComma(const std::string &row, std::vector &rowvec)
+{
+ std::string::size_type start = 0;
+ while (start != std::string::npos)
+ {
+ std::string::size_type end = row.find(',', start);
+ if (end == std::string::npos)
+ {
+ if (start < row.size())
+ {
+ rowvec.emplace_back(std::move(row.substr(start)));
+ }
+ break;
+ }
+ if (end > start)
+ {
+ rowvec.emplace_back(std::move(row.substr(start, end - start)));
+ }
+ start = end + 1;
+ }
+}
+
+VDMS::CSVParserUtil::DATATYPE VDMS::CSVParserUtil ::isValidDataType(string data, int type)
+{
+ CSVParserUtil::DATATYPE actualtype = getDataType(data, "");
+ return actualtype;
+
+ // if(type==2 && (actualt=3 || acype=tualtype==4))//2 is for num
+ // return actualtype;
+ // else if(type==1 && (actualtype==1 || actualtype==2))//1 is for bool
+ // return actualtype;
+ // else
+ // return -1;
+}
+
+bool VDMS::CSVParserUtil::isValidOpsType(string &type)
+{
+ if (type == "resize" || type == "threshold" || type == "flip" || type == "rotate" || type == "interval" || type == "crop")
+ return true;
+ return false;
+}
+
+void VDMS::CSVParserUtil::parseBlobFile(const std::string &filename, std::string **descriptor_ptr)
+{
+ std::vector v;
+
+ std::ifstream input(filename);
+ if (!input.is_open())
+ {
+ // handle error if file cannot be opened
+ std::cerr << "Error: Could not open file " << filename << std::endl;
+ *descriptor_ptr = nullptr;
+ return;
+ }
+
+ std::string str;
+ input >> str;
+
+ std::stringstream ss(str);
+ while (ss.good())
+ {
+ std::string substr;
+ getline(ss, substr, ';');
+ v.push_back(std::stof(substr));
+ }
+
+ input.close();
+
+ // Convert vector to array of bytes
+ const size_t byteSize = v.size() * sizeof(float);
+ unsigned char *bytes = new unsigned char[byteSize];
+ std::memcpy(bytes, v.data(), byteSize);
+
+ // Copy bytes to dynamically allocated string
+ *descriptor_ptr = new std::string(reinterpret_cast(bytes), byteSize);
+
+ // Clean up dynamically-allocated memory
+ delete[] bytes;
+}
+
+void VDMS::CSVParserUtil::videoToString(const std::string &filename, std::string **video_data_ptr)
+{
+ // Open the video file in binary mode
+ std::ifstream file(filename, std::ios::binary);
+
+ if (!file)
+ {
+ std::cerr << "Failed to open file: " << filename << std::endl;
+ *video_data_ptr = nullptr;
+ }
+ else
+ {
+ // Read the entire content of the file into a string
+ std::stringstream buffer;
+ buffer << file.rdbuf();
+ std::string video_data = buffer.str();
+
+ *video_data_ptr = new std::string(video_data);
+ }
+
+ // Close the file
+ file.close();
+}
+
+void VDMS::CSVParserUtil::read_blob_image(const std::string &filename, std::string **image_data_ptr)
+{
+ std::ifstream file(filename, std::ios::binary);
+
+ if (file.is_open())
+ {
+
+ // Get the size of the file
+ file.seekg(0, std::ios::end);
+ size_t size = file.tellg();
+ file.seekg(0, std::ios::beg);
+
+ // Allocate a buffer to hold the file data
+ char *buffer = new char[size];
+
+ // Read the file data into the buffer
+ file.read(buffer, size);
+
+ if (file.gcount() != size)
+ {
+ std::cerr << "Error: Failed to read entire file." << std::endl;
+ delete[] buffer;
+ *image_data_ptr = nullptr;
+ return;
+ }
+
+ // Close the file
+ file.close();
+
+ // Allocate a new std::string to hold the image data
+ std::string *image_data = new std::string;
+ image_data->assign(buffer, size);
+
+ // Free the buffer
+ delete[] buffer;
+
+ // Assign the std::string pointer to the image_data_ptr
+ *image_data_ptr = image_data;
+ }
+ else
+ {
+ std::cerr << "Error: Failed to open file." << std::endl;
+ *image_data_ptr = nullptr;
+ }
+}
+VDMS::Response VDMS::CSVParserUtil::send_to_vdms(const Json::Value &query,
+ const std::vector blobs)
+{
+ Json::StyledWriter _fastwriter;
+
+ return vdms_client->query(_fastwriter.write(query), blobs);
+}
diff --git a/client/cpp/CSVParserUtil.h b/client/cpp/CSVParserUtil.h
new file mode 100644
index 00000000..ad30bd9d
--- /dev/null
+++ b/client/cpp/CSVParserUtil.h
@@ -0,0 +1,102 @@
+#pragma once
+#include
+#include
+#include
+#include "rapidcsv.h"
+#include
+#include
+#include
+#include
+#include
+#include "VDMSClient.h"
+
+using namespace std;
+using namespace std::chrono;
+
+namespace VDMS {
+class CSVParserUtil {
+
+ enum QueryType { EntityClass,
+ ConnectionClass,
+ ImagePath,
+ VideoPath,
+ DescriptorType,
+ DescriptorClass,
+ RectangleBound,
+ EntityUpdate,
+ ConnectionUpdate,
+ ImageUpdate,
+ RectangleUpdate
+ };
+ enum class commandType {
+ AddEntity,
+ AddConnection,
+ AddImage,
+ AddVideo,
+ AddDescriptorSet,
+ AddDescriptor,
+ AddBoundingBox,
+ UpdateEntity,
+ UpdateConnection,
+ UpdateImage,
+ UpdateBoundingBox,
+ UNKNOWN
+
+ };
+ enum class DATATYPE{
+ TRUE,
+ FALSE,
+ INTEGER,
+ FLOAT,
+ STRING,
+ DATE,
+ WRONG
+
+ };
+ std::map commands;
+ std::map command_list;
+
+
+
+ public:
+ CSVParserUtil();
+ CSVParserUtil(const std::string&, int port, const std::vector, int id );
+ void initCommandsMap();
+ int isBool( const string& data);
+ bool isFloat(const string &);
+ bool isInt(const string &);
+ VDMS::Response parse_row(std::vector& fields);
+ commandType get_query_type(const string &data);
+ CSVParserUtil::DATATYPE getDataType(const string& data,const string& colname);
+ void parseProperty(const string& columnNames,const string& row,const string& queryType, Json::Value &aquery);
+ void parseConstraints(const string &columnNames,const string& row, string& queryType, Json::Value &aquery);
+ void parseOperations(const string columnNames,string row,string queryType,Json::Value &aquery);
+
+ // void parseCSVdata(int startrowcount,int endcount,rapidcsv::Document &doc, int &);
+ vector spiltrow(const string& row);
+ bool isValidOpsType(string& type);
+ void splitRowOnComma(const std::string& row, std::vector& rowvec);
+
+ string function_accessing_columnNames(int i);
+ DATATYPE isValidDataType(string data,int type);
+ void read_blob_image(const std::string& filename, std::string** image_data_ptr);
+ void videoToString(const std::string& filename, std::string** video_data);
+ void parseBlobFile(const std::string& filename, std::string** descriptor_ptr);
+
+ VDMS::Response send_to_vdms(const Json::Value &json_query, const std::vector blobs = {});
+
+ public:
+ std::string vdms_server;
+ int vdms_port;
+ std::vector _columnNames;
+ std::mutex querytype_mutex;
+ std::mutex aquery_mutex;
+ std::mutex cons_mutex;
+ std::mutex ops_mutex;
+ int id;
+ std::unique_ptr vdms_client;
+
+ };
+};
+
+
diff --git a/client/cpp/ConnectionQueryParser.h b/client/cpp/ConnectionQueryParser.h
new file mode 100644
index 00000000..afd8394d
--- /dev/null
+++ b/client/cpp/ConnectionQueryParser.h
@@ -0,0 +1,115 @@
+#include "CSVParserUtil.h"
+namespace VDMS {
+class ConnectionQueryParser : public CSVParserUtil{
+ public:
+ VDMS::Response ParseAddConnection(vector row, vector & cols);
+ // VDMS::Response ParseUpdateConnection(vector row, vector & cols);
+};
+};
+
+VDMS::Response VDMS::ConnectionQueryParser::ParseAddConnection(vector row, vector & columnNames){
+ Json::Value aquery;
+ Json::Value allquery;
+ Json::Value find_query1, find_query2,find_query;
+
+ if (row[0].empty()) {
+ std::cerr << "Error: Connection Class not provided\n";
+
+}
+
+// Set command name and connection class
+const string command_name = "AddConnection";
+const string connection_class = row[0];
+int ref1=1, ref2=3;
+aquery["AddConnection"]["class"] = connection_class;
+
+// Parse class1 and class2 columns
+for (int i = 1; i < columnNames.size(); i++) {
+ string column_name = columnNames[i];
+ string column_value = row[i];
+ string column_type = column_name.substr(0, 5);
+ string command="FindEntity";
+
+
+ if (column_value.empty()) {
+ continue;
+ }
+
+
+
+ if (column_name.find('@') != std::string::npos) {
+ std::size_t at_pos = column_name.find('@');
+
+ if (at_pos != std::string::npos) {
+ // Extract the name and id substrings.
+ std::string class1 = column_name.substr(0, at_pos);
+ std::string class_prop = column_name.substr(at_pos + 1);
+
+ find_query["FindEntity"]["class"]=class1;
+ find_query["FindEntity"]["_ref"]=ref1++;
+ find_query["FindEntity"]["constraints"][class_prop][0] = "==";
+ find_query["FindEntity"]["constraints"][class_prop][1]=column_value;
+ }
+ allquery.append(find_query);
+
+ }
+
+
+
+ // if (column_type == "cons_") {
+ // parseConstraints(column_name, column_value, command, find_query1);
+ // parseConstraints(column_name, column_value, command, find_query2);
+ // }
+ // if (column_type == "prop_") {
+ // parseProperty(column_name, column_value, command_name, aquery);
+ // }
+ find_query.clear();
+
+
+}
+
+// Set connection references
+aquery["AddConnection"]["ref1"] = allquery[0]["FindEntity"]["_ref"];
+aquery["AddConnection"]["ref2"] = allquery[1]["FindEntity"]["_ref"];
+
+
+
+allquery.append(aquery);
+
+
+return send_to_vdms(allquery);
+}
+
+// VDMS::Response VDMS::ConnectionQueryParser::ParseUpdateConnection(vector row, vector & columnNames){
+// Json::Value aquery;
+// Json::Value aqueryf;
+// Json::Value allquery;
+// if(row[0]=="")
+// throw "Connection Class not provided";
+// std::string command_name="UpdateConnection";
+// aquery["UpdateConnection"]["class"]=row[0];
+// aquery["UpdateConnection"]["_ref"]=96;
+// aqueryf["FindConnection"]["class"]=row[0];
+// aqueryf["FindConnection"]["_ref"]=96;
+// for(int j=1;j rowvec;
+// splitRowOnComma(row[j],rowvec);
+// for(int v=0;v row, vector& columnNames, int id);
+
+};
+};
+
+VDMS::Response VDMS::DescriptorQueryParser::ParseAddDescriptor(vector row, vector& columnNames, int id){
+
+ if(row[0]==""){
+ throw "Set not provided";
+ }
+ Json::Value aquery;
+ Json::Value fullquery;
+ std::vector blobs;
+ std::string* descriptor;
+ std::string command_name="AddDescriptor";
+ aquery["AddDescriptor"]["set"]=row[0];
+ aquery["AddDescriptor"]["_ref"]=id+3;
+ for(int j=1;j row, vector& columnNames);
+ bool isValidMetric(string& metric);
+ bool isValidEngine(string& engine);
+};
+};
+VDMS::Response VDMS::DescriptorSetQueryParser::ParseAddDescriptorSet(vector row, vector& columnNames){
+ if(row[0]==""){
+ throw "Descriptor Name not provided";
+ }
+ Json::Value aquery;
+ Json::Value fullquery;
+ std::string command_name="AddDescriptorSet";
+ aquery["AddDescriptorSet"]["name"]=row[0];
+
+
+ for(int j=1;j
+
+namespace VDMS
+{
+
+ class EntityQueryParser : public CSVParserUtil
+ {
+ public:
+ VDMS::Response ParseAddEntity(vector row, vector &cols);
+ // VDMS::Response ParseUpdateEntity(vector row, vector & cols);
+ };
+};
+
+VDMS::Response VDMS::EntityQueryParser::ParseAddEntity(vector row, vector &cols)
+{
+ Json::Value aquery;
+ Json::Value fullquery;
+
+ std::string command_name = "AddEntity";
+ // std::cout << command_name << columnNames.size() < row, vector & cols){
+// Json:: Value aquery;
+// Json::Value all_query;
+// Json::Value find_query;
+// std::string command_name="UpdateEntity";
+// if(row[0]==""){
+// throw "Entity Class not specified";
+// }
+// aquery["UpdateEntity"]["class"]=row[0];
+// int ref=10;
+// std::cout << _columnNames[0] < rowvec;
+// splitRowOnComma(row[j],rowvec);
+// for(int v=0;v row, vector columnNames);
+ // VDMS::Response ParseUpdateImage(vector row, vector columnNames);
+ bool ValidImageFormat(string data);
+
+
+};
+};
+
+
+
+VDMS::Response VDMS::ImageQueryParser::ParseAddImage(vector row, vector columnNames){
+ Json::Value aquery;
+ Json::Value fullquery;
+ std::vector blobs;
+ //
+ if(row[0].empty())
+ throw "Image path is not specified";
+ if (columnNames.size() == 0) {
+ throw std::invalid_argument("Error: Column names vector is empty.");
+ }
+
+ std::string command_name="AddImage";
+
+ aquery["AddImage"]["_ref"]=11;
+
+ std::string name =row[0];
+
+ std::string* image_data_ptr = nullptr;
+
+ read_blob_image(name, &image_data_ptr);
+
+ // std::cout << *image_data_ptr << std::endl;
+ if(image_data_ptr!=nullptr){
+ blobs.push_back(image_data_ptr);
+ // std::cout <<*blobs[0] < row, vector columnNames){
+// Json :: Value aquery;
+
+// Json::Value fullquery;
+
+// std::string command_name="UpdateIamge";
+// aquery["UpdateImage"]["_ref"]=12;
+// for(int j=1;j rowvec;
+// splitRowOnComma(row[j],rowvec);
+// for(int v=0;v(end - start);
+// cout << "duaration in ms is "< blobs)
{
diff --git a/client/cpp/VDMSClient.h b/client/cpp/VDMSClient.h
index 54ca8f9e..ced571d7 100644
--- a/client/cpp/VDMSClient.h
+++ b/client/cpp/VDMSClient.h
@@ -32,6 +32,7 @@
#include
#include
#include "comm/Connection.h"
+// #include "CSVParser.h"
namespace VDMS {
@@ -39,6 +40,7 @@ namespace VDMS {
std::string json;
std::vector blobs;
};
+
class VDMSClient {
static const int VDMS_PORT = 55555;
@@ -49,6 +51,7 @@ namespace VDMS {
// will leave the functioning like that. If the client has a need to
// disconnect and connect specifically, then we can add explicit calls.
comm::ConnClient _conn;
+
public:
VDMSClient(std::string addr = "localhost", int port = VDMS_PORT);
@@ -56,6 +59,7 @@ namespace VDMS {
// Blocking call
VDMS::Response query(const std::string &json_query,
const std::vector blobs = {});
-
+ // void parse_csv_file(std::string filename, std::string , int);
+
};
};
diff --git a/client/cpp/VideoQueryParser.h b/client/cpp/VideoQueryParser.h
new file mode 100644
index 00000000..3c89758b
--- /dev/null
+++ b/client/cpp/VideoQueryParser.h
@@ -0,0 +1,84 @@
+#pragma once
+#include "CSVParserUtil.h"
+namespace VDMS {
+class VideoQueryParser : public CSVParserUtil{
+ public:
+ VDMS::Response ParseAddVideo(vector row, vector& columnNames);
+ bool isValidCodec(string& row);
+ bool isValidContainer(string& row);
+
+};
+}
+VDMS::Response VDMS::VideoQueryParser::ParseAddVideo(vector row, vector& columnNames){
+ Json::Value aquery;
+ Json::Value fullquery;
+ std::vector blobs;
+ if(row[0]=="")
+ throw "Video not provided";
+ std::string command_name="AddVideo";
+
+ std::string video_name=row[0];
+ try {
+ std::string* video_data_ptr;
+ CSVParserUtil::videoToString(video_name, &video_data_ptr);
+
+ if(video_data_ptr!=nullptr){
+ blobs.push_back(video_data_ptr);
+ // std::cout <<*blobs[0] <
+#include
+#include
+#ifdef HAS_CODECVT
+#include
+#include
+#endif
+#include
+#include
+#include
+#include