diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index fe5dc8221dfa3..5ef35b293cd77 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -115,9 +115,13 @@ class CcdbApi //: public DatabaseInterface * @param metadata Key-values representing the metadata for this object. * @param startValidityTimestamp Start of validity. If omitted, current timestamp is used. * @param endValidityTimestamp End of validity. If omitted, current timestamp + 1 day is used. + * @return 0 -> ok, + * positive number -> curl error (https://curl.se/libcurl/c/libcurl-errors.html), + * -1 : object bigger than maxSize, + * -2 : curl initialization error */ - void storeAsTFile(const TObject* rootObject, std::string const& path, std::map const& metadata, - long startValidityTimestamp = -1, long endValidityTimestamp = -1) const; + int storeAsTFile(const TObject* rootObject, std::string const& path, std::map const& metadata, + long startValidityTimestamp = -1, long endValidityTimestamp = -1, std::vector::size_type maxSize = 0 /*bytes*/) const; /** * Store into the CCDB a TFile containing an object of type T (which needs to have a ROOT dictionary) @@ -127,19 +131,23 @@ class CcdbApi //: public DatabaseInterface * @param metadata Key-values representing the metadata for this object. * @param startValidityTimestamp Start of validity. If omitted, current timestamp is used. * @param endValidityTimestamp End of validity. If omitted, current timestamp + 1 day is used. + * @return 0 -> ok, + * positive number -> curl error (https://curl.se/libcurl/c/libcurl-errors.html), + * -1 : object bigger than maxSize, + * -2 : curl initialization error */ template - void storeAsTFileAny(const T* obj, std::string const& path, std::map const& metadata, - long startValidityTimestamp = -1, long endValidityTimestamp = -1) const + int storeAsTFileAny(const T* obj, std::string const& path, std::map const& metadata, + long startValidityTimestamp = -1, long endValidityTimestamp = -1, std::vector::size_type maxSize = 0 /*bytes*/) const { - storeAsTFile_impl(reinterpret_cast(obj), typeid(T), path, metadata, startValidityTimestamp, endValidityTimestamp); + return storeAsTFile_impl(reinterpret_cast(obj), typeid(T), path, metadata, startValidityTimestamp, endValidityTimestamp, maxSize); } // interface for storing TObject via storeAsTFileAny - void storeAsTFileAny(const TObject* rootobj, std::string const& path, std::map const& metadata, - long startValidityTimestamp = -1, long endValidityTimestamp = -1) const + int storeAsTFileAny(const TObject* rootobj, std::string const& path, std::map const& metadata, + long startValidityTimestamp = -1, long endValidityTimestamp = -1, std::vector::size_type maxSize = 0 /*bytes*/) const { - storeAsTFile(rootobj, path, metadata, startValidityTimestamp, endValidityTimestamp); + return storeAsTFile(rootobj, path, metadata, startValidityTimestamp, endValidityTimestamp, maxSize); } /** @@ -392,19 +400,31 @@ class CcdbApi //: public DatabaseInterface public: /** * A generic method to store a binary buffer (e.g. an image of the TMemFile) + * @return 0 -> ok, + * positive number -> curl error (https://curl.se/libcurl/c/libcurl-errors.html), + * -1 : object bigger than maxSize, + * -2 : curl initialization error */ - void storeAsBinaryFile(const char* buffer, size_t size, const std::string& fileName, const std::string& objectType, - const std::string& path, const std::map& metadata, - long startValidityTimestamp, long endValidityTimestamp) const; + int storeAsBinaryFile(const char* buffer, size_t size, const std::string& fileName, const std::string& objectType, + const std::string& path, const std::map& metadata, + long startValidityTimestamp, long endValidityTimestamp, std::vector::size_type maxSize = 0 /*in bytes*/) const; /** * A generic helper implementation to store an obj whose type is given by a std::type_info + * @return 0 -> ok, + * positive number -> curl error (https://curl.se/libcurl/c/libcurl-errors.html), + * -1 : object bigger than maxSize, + * -2 : curl initialization error */ - void storeAsTFile_impl(const void* obj1, std::type_info const& info, std::string const& path, std::map const& metadata, - long startValidityTimestamp = -1, long endValidityTimestamp = -1) const; + int storeAsTFile_impl(const void* obj1, std::type_info const& info, std::string const& path, std::map const& metadata, + long startValidityTimestamp = -1, long endValidityTimestamp = -1, std::vector::size_type maxSize = 0 /*in bytes*/) const; /** * A generic helper implementation to query obj whose type is given by a std::type_info + * @return 0 -> ok, + * positive number -> curl error (https://curl.se/libcurl/c/libcurl-errors.html), + * -1 : object bigger than maxSize, + * -2 : curl initialization error */ void* retrieveFromTFile(std::type_info const&, std::string const& path, std::map const& metadata, long timestamp = -1, std::map* headers = nullptr, std::string const& etag = "", diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 0ff27fe53c9ad..b2af1989b8f49 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -128,22 +128,25 @@ std::unique_ptr> CcdbApi::createObjectImage(const TObject* roo return o2::utils::MemFileHelper::createFileImage(*rootObject, tmpFileName, CCDBOBJECT_ENTRY); } -void CcdbApi::storeAsTFile_impl(const void* obj, std::type_info const& tinfo, std::string const& path, - std::map const& metadata, - long startValidityTimestamp, long endValidityTimestamp) const +int CcdbApi::storeAsTFile_impl(const void* obj, std::type_info const& tinfo, std::string const& path, + std::map const& metadata, + long startValidityTimestamp, long endValidityTimestamp, + std::vector::size_type maxSize) const { // We need the TClass for this type; will verify if dictionary exists CcdbObjectInfo info; auto img = createObjectImage(obj, tinfo, &info); - storeAsBinaryFile(img->data(), img->size(), info.getFileName(), info.getObjectType(), - path, metadata, startValidityTimestamp, endValidityTimestamp); + return storeAsBinaryFile(img->data(), img->size(), info.getFileName(), info.getObjectType(), + path, metadata, startValidityTimestamp, endValidityTimestamp, maxSize); } -void CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::string& filename, const std::string& objectType, - const std::string& path, const std::map& metadata, - long startValidityTimestamp, long endValidityTimestamp) const +int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::string& filename, const std::string& objectType, + const std::string& path, const std::map& metadata, + long startValidityTimestamp, long endValidityTimestamp, std::vector::size_type maxSize) const { - // Store a binary file + if (maxSize > 0 && size > maxSize) { + return -1; + } // Prepare URL long sanitizedStartValidityTimestamp = startValidityTimestamp; @@ -160,6 +163,7 @@ void CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::stri // Curl preparation CURL* curl = nullptr; curl = curl_easy_init(); + int returnValue = 0; if (curl != nullptr) { struct curl_httppost* formpost = nullptr; @@ -196,6 +200,7 @@ void CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::stri if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + returnValue = res; } } @@ -208,16 +213,18 @@ void CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::stri curl_slist_free_all(headerlist); } else { cerr << "curl initialization failure" << endl; + returnValue = -2; } + return returnValue; } -void CcdbApi::storeAsTFile(const TObject* rootObject, std::string const& path, std::map const& metadata, - long startValidityTimestamp, long endValidityTimestamp) const +int CcdbApi::storeAsTFile(const TObject* rootObject, std::string const& path, std::map const& metadata, + long startValidityTimestamp, long endValidityTimestamp, std::vector::size_type maxSize) const { // Prepare file CcdbObjectInfo info; auto img = createObjectImage(rootObject, &info); - storeAsBinaryFile(img->data(), img->size(), info.getFileName(), info.getObjectType(), path, metadata, startValidityTimestamp, endValidityTimestamp); + return storeAsBinaryFile(img->data(), img->size(), info.getFileName(), info.getObjectType(), path, metadata, startValidityTimestamp, endValidityTimestamp, maxSize); } string CcdbApi::getFullUrlForStorage(CURL* curl, const string& path, const string& objtype, diff --git a/CCDB/test/testCcdbApi.cxx b/CCDB/test/testCcdbApi.cxx index 2e768228b1656..cac48ecff933c 100644 --- a/CCDB/test/testCcdbApi.cxx +++ b/CCDB/test/testCcdbApi.cxx @@ -200,6 +200,21 @@ BOOST_AUTO_TEST_CASE(store_retrieve_TMemFile_templated_test, *utf::precondition( } } +BOOST_AUTO_TEST_CASE(store_max_size_test, *utf::precondition(if_reachable())) +{ + test_fixture f; + + // try to store a user defined class + // since we don't depend on anything, we are putting an object known to CCDB + o2::ccdb::IdPath path; + path.setPath("HelloWorld"); + + int result = f.api.storeAsTFileAny(&path, basePath + "CCDBPath", f.metadata); // ok + BOOST_CHECK_EQUAL(result, 0); + result = f.api.storeAsTFileAny(&path, basePath + "CCDBPath", f.metadata, -1, -1, 1 /* bytes */); // we know this will fail + BOOST_CHECK_EQUAL(result, -1); +} + /// A test verifying that the DB responds the correct result for given timestamps BOOST_AUTO_TEST_CASE(timestamptest, *utf::precondition(if_reachable())) {