diff --git a/common/cpp/include/common/data_structs.h b/common/cpp/include/common/data_structs.h index fb6b0038b0b966260351eeedc14d65ec8d9e9cb9..9117b55162dbb05ed6107e1008d6e0170fb2cc82 100644 --- a/common/cpp/include/common/data_structs.h +++ b/common/cpp/include/common/data_structs.h @@ -16,6 +16,7 @@ class FileInfo { uint64_t size{0}; uint64_t id{0}; std::string source; + std::string metadata; uint64_t buf_id{0}; std::string Json() const; bool SetFromJson(const std::string& json_string); diff --git a/common/cpp/include/json_parser/json_parser.h b/common/cpp/include/json_parser/json_parser.h index 737814ad7b2c7dc53f77ad2ce331709419a1d711..26050696a477577b13ec4345733e7893cea3205f 100644 --- a/common/cpp/include/json_parser/json_parser.h +++ b/common/cpp/include/json_parser/json_parser.h @@ -20,6 +20,8 @@ class JsonParser { Error GetString(const std::string& name, std::string* val) const noexcept; Error GetArrayUInt64(const std::string& name, std::vector<uint64_t>* val) const noexcept; Error GetArrayString(const std::string& name, std::vector<std::string>* val) const noexcept; + Error GetRawString(std::string* val) const noexcept; + JsonParser Embedded(const std::string& name) const noexcept; ~JsonParser(); protected: diff --git a/common/cpp/src/data_structs/data_structs.cpp b/common/cpp/src/data_structs/data_structs.cpp index eb5e22a80ea53a32714617c35f6cb9db471a1615..67ab7e02901fb47da5f72c255e40251a6c6438c9 100644 --- a/common/cpp/src/data_structs/data_structs.cpp +++ b/common/cpp/src/data_structs/data_structs.cpp @@ -25,13 +25,15 @@ std::string FileInfo::Json() const { } #endif + int64_t buf_id_int = static_cast<int64_t>(buf_id); std::string s = "{\"_id\":" + std::to_string(id) + "," "\"size\":" + std::to_string(size) + "," "\"name\":\"" + x + "\"," "\"lastchange\":" + std::to_string(nanoseconds_from_epoch) + "," "\"source\":\"" + source + "\"," - "\"buf_id\":" + std::to_string(buf_id_int) + "\"buf_id\":" + std::to_string(buf_id_int) + "," + "\"meta\":" + (metadata.size() == 0 ? std::string("{}") : metadata) + "}"; return s; } @@ -61,11 +63,14 @@ bool FileInfo::SetFromJson(const std::string& json_string) { parser.GetString("name", &name) || parser.GetString("source", &source) || parser.GetUInt64("buf_id", &buf_id) || + parser.Embedded("meta").GetRawString(&metadata) || !TimeFromJson(parser, "lastchange", &modify_date)) { *this = old; return false; } +//ignore error if meta not found + return true; } diff --git a/common/cpp/src/json_parser/json_parser.cpp b/common/cpp/src/json_parser/json_parser.cpp index 41d9dee99ccf8f0fbd1c0b5fc3295e568221e5d5..1a07fc449e5fd155f026a41aebc4a7c4c3509341 100644 --- a/common/cpp/src/json_parser/json_parser.cpp +++ b/common/cpp/src/json_parser/json_parser.cpp @@ -50,6 +50,10 @@ JsonParser::JsonParser(JsonParser&& other) { rapid_json_ = std::move(other.rapid_json_); } +Error JsonParser::GetRawString(std::string* val) const noexcept { + return rapid_json_->GetRawString(val); +} + } diff --git a/common/cpp/src/json_parser/rapid_json.cpp b/common/cpp/src/json_parser/rapid_json.cpp index 3c79048900e0f00bcd4271492614be3c45b7c8f3..f8c49d42d254d26dcb22e9de5b442cfe56b89acd 100644 --- a/common/cpp/src/json_parser/rapid_json.cpp +++ b/common/cpp/src/json_parser/rapid_json.cpp @@ -1,5 +1,6 @@ #include "rapid_json.h" -#include "rapid_json.h" +#include "rapidjson/stringbuffer.h" +#include <rapidjson/writer.h> using namespace rapidjson; @@ -173,4 +174,16 @@ RapidJson::RapidJson(const RapidJson& parent, const std::string& subname) { initialized_ = true; } +Error RapidJson::GetRawString(std::string* val) const noexcept { + if (Error err = LazyInitialize()) { + return err; + } + + StringBuffer buffer; + Writer<StringBuffer> writer(buffer); + object_p_->Accept(writer); + val->assign(buffer.GetString()); + return nullptr; +} + } \ No newline at end of file diff --git a/common/cpp/src/json_parser/rapid_json.h b/common/cpp/src/json_parser/rapid_json.h index 9098f7cd5562c7b3e303194744425ebf1194da7f..4b539081157dcde4e6c44c18990b6bbd66450e52 100644 --- a/common/cpp/src/json_parser/rapid_json.h +++ b/common/cpp/src/json_parser/rapid_json.h @@ -26,6 +26,7 @@ class RapidJson { Error GetString(const std::string& name, std::string* val) const noexcept; Error GetArrayUInt64(const std::string& name, std::vector<uint64_t>* val) const noexcept; Error GetArrayString(const std::string& name, std::vector<std::string>* val) const noexcept; + Error GetRawString(std::string* val) const noexcept; private: Error GetInt64(const std::string& name, int64_t* val) const noexcept; const std::unique_ptr<IO>* io__; diff --git a/common/cpp/unittests/data_structs/test_data_structs.cpp b/common/cpp/unittests/data_structs/test_data_structs.cpp index e9fee1f8c860a18c43f3bea59a782494e12cf0bb..a756689639c8bf4476da51450ce24ae8bcfcc74b 100644 --- a/common/cpp/unittests/data_structs/test_data_structs.cpp +++ b/common/cpp/unittests/data_structs/test_data_structs.cpp @@ -30,6 +30,7 @@ FileInfo PrepareFileInfo() { finfo.source = "host:1234"; finfo.buf_id = big_uint; finfo.modify_date = std::chrono::time_point<std::chrono::system_clock>(std::chrono::milliseconds(1)); + finfo.metadata = "{\"bla\":10}"; return finfo; } @@ -47,10 +48,10 @@ TEST(FileInFo, CorrectConvertToJson) { printf("%s\n", json.c_str()); if (asapo::kPathSeparator == '/') { ASSERT_THAT(json, Eq( - R"({"_id":1,"size":100,"name":"folder/test","lastchange":1000000,"source":"host:1234","buf_id":-1})")); + R"({"_id":1,"size":100,"name":"folder/test","lastchange":1000000,"source":"host:1234","buf_id":-1,"meta":{"bla":10}})")); } else { ASSERT_THAT(json, Eq( - R"({"_id":1,"size":100,"name":"folder\\test","lastchange":1000000,"source":"host:1234","buf_id":-1})")); + R"({"_id":1,"size":100,"name":"folder\\test","lastchange":1000000,"source":"host:1234","buf_id":-1,"meta":{"bla":10}})")); } } @@ -69,6 +70,21 @@ TEST(FileInFo, CorrectConvertFromJsonReturnsError) { } +TEST(FileInFo, CorrectConvertFromJsonReturnsErrorForMetadata) { + auto finfo = PrepareFileInfo(); + + FileInfo result; + + std::string json = R"({"_id":2,"foo":"foo","bar":1,{"meta":err}})"; + + auto ok = result.SetFromJson(json); + + ASSERT_THAT(ok, Eq(false)); + +} + + + TEST(FileInFo, CorrectConvertFromJson) { auto finfo = PrepareFileInfo(); std::string json = finfo.Json(); @@ -84,6 +100,21 @@ TEST(FileInFo, CorrectConvertFromJson) { ASSERT_THAT(result.modify_date, Eq(finfo.modify_date)); ASSERT_THAT(result.buf_id, Eq(finfo.buf_id)); ASSERT_THAT(result.source, Eq(finfo.source)); + ASSERT_THAT(result.metadata, Eq(finfo.metadata)); + +} + + +TEST(FileInFo, CorrectConvertFromJsonEmptyMeta) { + auto finfo = PrepareFileInfo(); + finfo.metadata = ""; + std::string json = finfo.Json(); + + FileInfo result; + auto ok = result.SetFromJson(json); + + ASSERT_THAT(ok, Eq(true)); + ASSERT_THAT(result.metadata, Eq("{}")); } diff --git a/receiver/src/request.cpp b/receiver/src/request.cpp index cf14205950e5da00811eb0ba37056d4f0c314ce9..5f8a9bcf8c32c07879d3907759a3e409cff25376 100644 --- a/receiver/src/request.cpp +++ b/receiver/src/request.cpp @@ -42,7 +42,7 @@ Error Request::ReceiveMetaData() { if (err) { return err; } - metadata_.assign((char*)buf.get(),request_header_.meta_size); + metadata_.assign((char*)buf.get(), request_header_.meta_size); return nullptr; } diff --git a/receiver/src/request_handler_db_write.cpp b/receiver/src/request_handler_db_write.cpp index 4d6c07357a558766ce876a0e41fffaa6e73b7918..ecb9ad2069a37081aacf67e8038826e6baa7a2fb 100644 --- a/receiver/src/request_handler_db_write.cpp +++ b/receiver/src/request_handler_db_write.cpp @@ -43,6 +43,7 @@ FileInfo RequestHandlerDbWrite::PrepareFileInfo(const Request* request) const { file_info.buf_id = request->GetSlotId(); file_info.source = GetReceiverConfig()->source_host + ":" + string_format("%ld", GetReceiverConfig()->dataserver.listen_port); + file_info.metadata = request->GetMetaData(); return file_info; } RequestHandlerDbWrite::RequestHandlerDbWrite(std::string collection_name) : RequestHandlerDb(std::move( diff --git a/receiver/unittests/receiver_mocking.h b/receiver/unittests/receiver_mocking.h index 4b7673b9f4681c3545839437592f11b9cdec3953..05227a6888f12684a9bcac0aa936ff7e8791874a 100644 --- a/receiver/unittests/receiver_mocking.h +++ b/receiver/unittests/receiver_mocking.h @@ -51,6 +51,7 @@ class MockRequest: public Request { MOCK_CONST_METHOD0(GetSlotId, uint64_t()); MOCK_CONST_METHOD0(GetData, void* ()); MOCK_CONST_METHOD0(GetBeamtimeId, const std::string & ()); + MOCK_CONST_METHOD0(GetMetaData, const std::string & ()); MOCK_CONST_METHOD0(GetBeamline, const std::string & ()); MOCK_CONST_METHOD0(GetOpCode, asapo::Opcode ()); MOCK_CONST_METHOD0(GetMessage, const char* ()); diff --git a/receiver/unittests/test_request.cpp b/receiver/unittests/test_request.cpp index fc400799c98c1e684a3859997f948882f3a5dfb0..e50d658884045449e89c15e561e20c35f27fa602 100644 --- a/receiver/unittests/test_request.cpp +++ b/receiver/unittests/test_request.cpp @@ -103,27 +103,27 @@ class RequestTests : public Test { }; -ACTION_P(CopyStr,value) { - if (value.size()<=arg2 && value.size()>0) { - memcpy(static_cast<char*>(arg1), value.c_str(),value.size()); +ACTION_P(CopyStr, value) { + if (value.size() <= arg2 && value.size() > 0) { + memcpy(static_cast<char*>(arg1), value.c_str(), value.size()); } } -void RequestTests::ExpectReceive(uint64_t expected_size,bool ok) { +void RequestTests::ExpectReceive(uint64_t expected_size, bool ok) { EXPECT_CALL(mock_io, Receive_t(socket_fd_, _, expected_size, _)).WillOnce( DoAll( - CopyStr(expected_metadata), - SetArgPointee<3>(ok?nullptr:new asapo::IOError("Test Read Error", asapo::IOErrorType::kReadError)), - Return(0) + CopyStr(expected_metadata), + SetArgPointee<3>(ok ? nullptr : new asapo::IOError("Test Read Error", asapo::IOErrorType::kReadError)), + Return(0) )); } void RequestTests::ExpectReceiveData(bool ok) { - ExpectReceive(data_size_,ok); + ExpectReceive(data_size_, ok); } void RequestTests::ExpectReceiveMetaData(bool ok) { - ExpectReceive(expected_metadata_size,ok); + ExpectReceive(expected_metadata_size, ok); } void RequestTests::ExpectReceiveAllOK() { diff --git a/receiver/unittests/test_request_handler_db_writer.cpp b/receiver/unittests/test_request_handler_db_writer.cpp index ee6653f7f70ead90f91bb91e50d66cebd0e09fa7..6c04f1c0f4857a502cd3455d45e351696d2ff333 100644 --- a/receiver/unittests/test_request_handler_db_writer.cpp +++ b/receiver/unittests/test_request_handler_db_writer.cpp @@ -86,6 +86,7 @@ MATCHER_P(CompareFileInfo, file, "") { if (arg.buf_id != file.buf_id) return false; if (arg.name != file.name) return false; if (arg.id != file.id) return false; + if (arg.metadata != file.metadata) return false; return true; } @@ -111,6 +112,7 @@ TEST_F(DbWriterHandlerTests, CallsInsert) { WillOnce(testing::Return(nullptr)); std::string expected_file_name = "2"; + std::string expected_metadata = "meta"; uint64_t expected_file_size = 10; uint64_t expected_id = 15; EXPECT_CALL(*mock_request, GetDataSize()) @@ -121,6 +123,11 @@ TEST_F(DbWriterHandlerTests, CallsInsert) { .WillOnce(Return(expected_file_name)) ; + EXPECT_CALL(*mock_request, GetMetaData()) + .WillOnce(ReturnRef(expected_metadata)) + ; + + EXPECT_CALL(*mock_request, GetDataID()) .WillOnce(Return(expected_id)) ; @@ -131,7 +138,7 @@ TEST_F(DbWriterHandlerTests, CallsInsert) { file_info.id = expected_id; file_info.buf_id = expected_buf_id; file_info.source = expected_hostname + ":" + std::to_string(expected_port); - + file_info.metadata = expected_metadata; EXPECT_CALL(mock_db, Insert_t(CompareFileInfo(file_info), _)). WillOnce(testing::Return(nullptr));