diff --git a/receiver/src/data_cache.cpp b/receiver/src/data_cache.cpp index d0b6b32a847cfd8b48346505b56a27b0108995e9..1ad50f54008be00942f522d0a6951ea69833f94c 100644 --- a/receiver/src/data_cache.cpp +++ b/receiver/src/data_cache.cpp @@ -4,6 +4,7 @@ #include <chrono> #include <algorithm> +#include "receiver_error.h" namespace asapo { @@ -20,7 +21,7 @@ DataCache::DataCache(uint64_t cache_size, float keepunlocked_ratio) : cache_size counter_ = static_cast<uint32_t>(rand() % 100 + 1); } -void* DataCache::AllocateSlot(uint64_t size) { +void* DataCache::AllocateSlot(uint64_t size,CacheMeta** blocking_meta) { auto tmp = cur_pointer_; if (cur_pointer_ + size > cache_size_) { @@ -29,22 +30,29 @@ void* DataCache::AllocateSlot(uint64_t size) { auto addr = cache_.get() + cur_pointer_; cur_pointer_ += size; - if (!CleanOldSlots(size)) { + if (!CleanOldSlots(size,blocking_meta)) { cur_pointer_ = tmp; return nullptr; } return addr; } - -void* DataCache::GetFreeSlotAndLock(uint64_t size, CacheMeta** meta) { +void* DataCache::GetFreeSlotAndLock(uint64_t size, CacheMeta** meta, Error* err) { std::lock_guard<std::mutex> lock{mutex_}; *meta = nullptr; if (!CheckAllocationSize(size)) { + *err = ReceiverErrorTemplates::kCacheAllocationError.Generate("size too large"); return nullptr; } - - auto addr = AllocateSlot(size); + CacheMeta* blocking_meta; + auto addr = AllocateSlot(size,&blocking_meta); if (!addr) { + *err = ReceiverErrorTemplates::kCacheAllocationError.Generate("no slot available"); + (*err)->AddDetails("curPointer",cur_pointer_)->AddDetails("cacheSize",cache_size_); + if (blocking_meta) { + (*err)->AddDetails("blockingMetaId",blocking_meta->id)->AddDetails("blockingMetaSize",blocking_meta->size); + uint64_t start_position = static_cast<uint64_t>((uint8_t*) blocking_meta->addr - cache_.get()); + (*err)->AddDetails("starPosition",start_position); + } return nullptr; } @@ -53,6 +61,7 @@ void* DataCache::GetFreeSlotAndLock(uint64_t size, CacheMeta** meta) { *meta = new CacheMeta{id, addr, size, 1}; meta_.emplace_back(std::unique_ptr<CacheMeta> {*meta}); + *err = nullptr; return addr; } @@ -96,7 +105,8 @@ bool Intersects(uint64_t left1, uint64_t right1, uint64_t left2, uint64_t right2 return (left1 >= left2 && left1 < right2) || (right1 <= right2 && right1 > left2); } -bool DataCache::CleanOldSlots(uint64_t size) { +bool DataCache::CleanOldSlots(uint64_t size,CacheMeta** blocking_meta) { + *blocking_meta = nullptr; int64_t last_del = -1; bool was_intersecting = false; for (uint64_t i = 0; i < meta_.size(); i++) { @@ -112,7 +122,10 @@ bool DataCache::CleanOldSlots(uint64_t size) { } for (int i = 0; i <= last_del; i++) { - if (meta_[static_cast<unsigned long>(i)]->lock > 0) return false; + if (meta_[static_cast<unsigned long>(i)]->lock > 0) { + *blocking_meta = meta_[static_cast<unsigned long>(i)].get(); + return false; + } } if (last_del >= 0) { diff --git a/receiver/src/data_cache.h b/receiver/src/data_cache.h index 78264e62285a0abffe98fd1e06114400628ef513..6015439bf876975295974ffa1127a539520ec004 100644 --- a/receiver/src/data_cache.h +++ b/receiver/src/data_cache.h @@ -7,7 +7,7 @@ #include <deque> #include "asapo/preprocessor/definitions.h" - +#include "asapo/common/error.h" namespace asapo { @@ -21,7 +21,7 @@ struct CacheMeta { class DataCache { public: explicit DataCache(uint64_t cache_size_gb, float keepunlocked_ratio); - ASAPO_VIRTUAL void* GetFreeSlotAndLock(uint64_t size, CacheMeta** meta); + ASAPO_VIRTUAL void* GetFreeSlotAndLock(uint64_t size, CacheMeta** meta, Error* err); ASAPO_VIRTUAL void* GetSlotToReadAndLock(uint64_t id, uint64_t data_size, CacheMeta** meta); ASAPO_VIRTUAL bool UnlockSlot(CacheMeta* meta); ASAPO_VIRTUAL ~DataCache() = default; @@ -34,8 +34,8 @@ class DataCache { std::mutex mutex_; std::deque<std::unique_ptr<CacheMeta>> meta_; bool SlotTooCloseToCurrentPointer(const CacheMeta* meta); - bool CleanOldSlots(uint64_t size); - void* AllocateSlot(uint64_t size); + bool CleanOldSlots(uint64_t size,CacheMeta** blocking_meta); + void* AllocateSlot(uint64_t size,CacheMeta** blocking_meta); bool CheckAllocationSize(uint64_t size); uint64_t GetNextId(); }; diff --git a/receiver/src/receiver_error.h b/receiver/src/receiver_error.h index dff04fc0655265a5de163b14ae28f1e532548998..eb08f560461d39ae08c364ddcaa6c6256340a49f 100644 --- a/receiver/src/receiver_error.h +++ b/receiver/src/receiver_error.h @@ -13,7 +13,8 @@ enum class ReceiverErrorType { kReAuthorizationFailure, kWarningDuplicatedRequest, kUnsupportedClient, - kProcessingError + kProcessingError, + kCacheAllocationError }; using ReceiverErrorTemplate = ServiceErrorTemplate<ReceiverErrorType>; @@ -38,6 +39,9 @@ auto const kProcessingError = ReceiverErrorTemplate { "processing error", ReceiverErrorType::kProcessingError }; +auto const kCacheAllocationError = ReceiverErrorTemplate { + "cache allocation error", ReceiverErrorType::kCacheAllocationError +}; auto const kBadRequest = ReceiverErrorTemplate { "Bad request", ReceiverErrorType::kBadRequest diff --git a/receiver/src/request.cpp b/receiver/src/request.cpp index 25172a9abf261044f31f6fc272b5d9ea23aedb3f..fc43846aad597f95f93ddf8c39de796dc1ffba8d 100644 --- a/receiver/src/request.cpp +++ b/receiver/src/request.cpp @@ -1,53 +1,70 @@ #include "request.h" #include "asapo/io/io_factory.h" #include "request_handler/request_handler_db_check_request.h" +#include "receiver_logger.h" namespace asapo { Request::Request(const GenericRequestHeader& header, SocketDescriptor socket_fd, std::string origin_uri, DataCache* cache, const RequestHandlerDbCheckRequest* db_check_handler) : io__{GenerateDefaultIO()}, - cache__{cache}, request_header_(header), + cache__{cache}, log__{GetDefaultReceiverLogger()},request_header_(header), socket_fd_{socket_fd}, origin_uri_{std::move(origin_uri)}, check_duplicate_request_handler_{db_check_handler} { origin_host_ = HostFromUri(origin_uri_); } +Error Request::PrepareDataBufferFromMemory() { + try { + data_buffer_.reset(new uint8_t[(size_t)request_header_.data_size]); + } catch(std::exception& e) { + auto err = GeneralErrorTemplates::kMemoryAllocationError.Generate( + std::string("cannot allocate memory for request")); + err->AddDetails("reason", e.what())->AddDetails("size", std::to_string(request_header_.data_size)); + return err; + } + return nullptr; +} + +Error Request::PrepareDataBufferFromCache() { + Error err; + CacheMeta* slot; + data_ptr = cache__->GetFreeSlotAndLock(request_header_.data_size, &slot, &err); + if (err == nullptr) { + slot_meta_ = slot; + } else { + err->AddDetails("size", std::to_string(request_header_.data_size)); + return err; + } + return nullptr; +} + + Error Request::PrepareDataBufferAndLockIfNeeded() { if (cache__ == nullptr) { - try { - data_buffer_.reset(new uint8_t[(size_t)request_header_.data_size]); - } catch(std::exception& e) { - auto err = GeneralErrorTemplates::kMemoryAllocationError.Generate( - std::string("cannot allocate memory for request")); - err->AddDetails("reason", e.what())->AddDetails("size", std::to_string(request_header_.data_size)); - return err; - } - } else { - CacheMeta* slot; - data_ptr = cache__->GetFreeSlotAndLock(request_header_.data_size, &slot); - if (data_ptr) { - slot_meta_ = slot; - } else { - auto err = GeneralErrorTemplates::kMemoryAllocationError.Generate("cannot allocate slot in cache"); - err->AddDetails("size", std::to_string(request_header_.data_size)); - return err; - } + return PrepareDataBufferFromMemory(); + } + auto err = PrepareDataBufferFromCache(); + if (err) { + log__->Warning(LogMessageWithFields(err).Append(RequestLog("", this))); + return PrepareDataBufferFromMemory(); } return nullptr; } Error Request::Handle(ReceiverStatistics* statistics) { + Error err; for (auto handler : handlers_) { statistics->StartTimer(handler->GetStatisticEntity()); - auto err = handler->ProcessRequest(this); + err = handler->ProcessRequest(this); if (err) { - return err; + break; } statistics->StopTimer(); } - return nullptr; + UnlockDataBufferIfNeeded(); + return err; } const RequestHandlerList& Request::GetListHandlers() const { diff --git a/receiver/src/request.h b/receiver/src/request.h index a7d8402e8df7a694fdf263e57b8d5493675932a1..ba5bb3e17c77e4324d2d2c31ebdc7d8ea92784e6 100644 --- a/receiver/src/request.h +++ b/receiver/src/request.h @@ -12,6 +12,7 @@ #include "data_cache.h" #include "asapo/preprocessor/definitions.h" +#include "asapo/logger/logger.h" namespace asapo { @@ -76,7 +77,10 @@ class Request { ASAPO_VIRTUAL ResponseMessageType GetResponseMessageType() const; ASAPO_VIRTUAL const std::string& GetResponseMessage() const; ASAPO_VIRTUAL Error CheckForDuplicates(); - private: + const AbstractLogger* log__; + private: + Error PrepareDataBufferFromMemory(); + Error PrepareDataBufferFromCache(); const GenericRequestHeader request_header_; const SocketDescriptor socket_fd_; MessageData data_buffer_; diff --git a/receiver/src/request_handler/request_handler_receive_data.cpp b/receiver/src/request_handler/request_handler_receive_data.cpp index e81a5e30402ef70c533930b0b4b662ad42933146..ebd6706dcfea49d8a1ea5debf3bf98c3e914eb6e 100644 --- a/receiver/src/request_handler/request_handler_receive_data.cpp +++ b/receiver/src/request_handler/request_handler_receive_data.cpp @@ -23,7 +23,6 @@ Error RequestHandlerReceiveData::ProcessRequest(Request* request) const { if (io_err) { err = ReceiverErrorTemplates::kProcessingError.Generate("cannot receive data",std::move(io_err)); } - request->UnlockDataBufferIfNeeded(); if (err == nullptr) { log__->Debug(RequestLog("received request data", request).Append("size",request->GetDataSize())); } diff --git a/receiver/unittests/receiver_mocking.h b/receiver/unittests/receiver_mocking.h index eb587199f7ba24f3e85143431d98df407b147ce6..dd2b21353bc7ff09b1a066aa167b2c44a3ae917b 100644 --- a/receiver/unittests/receiver_mocking.h +++ b/receiver/unittests/receiver_mocking.h @@ -121,10 +121,17 @@ class MockRequest: public Request { class MockDataCache: public DataCache { public: MockDataCache(): DataCache(0, 0) {}; - MOCK_METHOD(void*, GetFreeSlotAndLock, (uint64_t size, CacheMeta** meta), (override)); + + void* GetFreeSlotAndLock(uint64_t size, CacheMeta** meta, Error* err) override{ + ErrorInterface* error = nullptr; + auto data = GetFreeSlotAndLock_t(size, meta, &error); + err->reset(error); + return data; + } + + MOCK_METHOD(void*, GetFreeSlotAndLock_t, (uint64_t size, CacheMeta** meta,ErrorInterface** err)); MOCK_METHOD(bool, UnlockSlot, (CacheMeta* meta), (override)); MOCK_METHOD(void*, GetSlotToReadAndLock, (uint64_t id, uint64_t data_size, CacheMeta** meta), (override)); - }; diff --git a/receiver/unittests/request_handler/test_request_handler_receive_data.cpp b/receiver/unittests/request_handler/test_request_handler_receive_data.cpp index 8d734e18cad50406bf4e1b06dad2acb6da103e30..9cf3f34b5e2f3f9a1b85e3188a7f83ebde228192 100644 --- a/receiver/unittests/request_handler/test_request_handler_receive_data.cpp +++ b/receiver/unittests/request_handler/test_request_handler_receive_data.cpp @@ -122,13 +122,12 @@ TEST_F(ReceiveDataHandlerTests, HandleGetsMemoryFromCache) { request->cache__ = &mock_cache; asapo::CacheMeta meta; meta.id = expected_slot_id; - EXPECT_CALL(mock_cache, GetFreeSlotAndLock(data_size_, _)).WillOnce( + EXPECT_CALL(mock_cache, GetFreeSlotAndLock_t(data_size_, _, _)).WillOnce( DoAll(SetArgPointee<1>(&meta), + SetArgPointee<2>(nullptr), Return(&mock_cache) )); - EXPECT_CALL(mock_cache, UnlockSlot(&meta)); - auto err = handler.ProcessRequest(request.get()); ASSERT_THAT(request->GetSlotId(), Eq(expected_slot_id)); @@ -138,17 +137,15 @@ TEST_F(ReceiveDataHandlerTests, HandleGetsMemoryFromCache) { TEST_F(ReceiveDataHandlerTests, ErrorGetMemoryFromCache) { request->cache__ = &mock_cache; - EXPECT_CALL(mock_cache, GetFreeSlotAndLock(data_size_, _)).WillOnce( - Return(nullptr) - ); - - EXPECT_CALL(mock_cache, UnlockSlot(_)).Times(0); - + EXPECT_CALL(mock_cache, GetFreeSlotAndLock_t(data_size_, _,_)).WillOnce( + DoAll(SetArgPointee<2>(asapo::ReceiverErrorTemplates::kProcessingError.Generate().release()), + Return(nullptr) + )); auto err = handler.ProcessRequest(request.get()); ASSERT_THAT(request->GetSlotId(), Eq(0)); - ASSERT_THAT(err, Eq(asapo::GeneralErrorTemplates::kMemoryAllocationError)); + ASSERT_THAT(err, Eq(nullptr)); } diff --git a/receiver/unittests/test_datacache.cpp b/receiver/unittests/test_datacache.cpp index ead69885bdbad0ae6a4f880f6b45898eb403412c..f0e1e2d81f1d2f6bf30e85217f5538f5e6cb17fc 100644 --- a/receiver/unittests/test_datacache.cpp +++ b/receiver/unittests/test_datacache.cpp @@ -30,8 +30,10 @@ class DataCacheTests : public Test { }; TEST_F(DataCacheTests, GetFreeSlotFailsDueToSize) { - auto addr = cache.GetFreeSlotAndLock(expected_cache_size + 1, &meta1); + asapo::Error err; + auto addr = cache.GetFreeSlotAndLock(expected_cache_size + 1, &meta1,&err); ASSERT_THAT(addr, Eq(nullptr)); + ASSERT_THAT(err, Ne(nullptr)); } void set_array(uint8_t* addr, uint64_t size, uint8_t val) { @@ -41,16 +43,18 @@ void set_array(uint8_t* addr, uint64_t size, uint8_t val) { } TEST_F(DataCacheTests, GetFreeSlotOK) { - uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1); + asapo::Error err; + uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1,&err); set_array(addr, 1, 2); ASSERT_THAT(addr[0], Eq(2)); ASSERT_THAT(meta1->id, Gt(0)); } TEST_F(DataCacheTests, GetFreeSlotStartsFromLastPointer) { - uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1); + asapo::Error err; + uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1,&err); set_array(ini_addr, 1, 2); - uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta2); + uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta2,&err); set_array(addr, 1, 1); ASSERT_THAT(ini_addr[0], Eq(2)); ASSERT_THAT(ini_addr[1], Eq(1)); @@ -58,8 +62,9 @@ TEST_F(DataCacheTests, GetFreeSlotStartsFromLastPointer) { } TEST_F(DataCacheTests, GetFreeSlotLocks) { - uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1); - uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2); + asapo::Error err; + uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1,&err); + uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2,&err); ASSERT_THAT(ini_addr, Ne(nullptr)); ASSERT_THAT(addr, Eq(nullptr)); ASSERT_THAT(meta1, Ne(nullptr)); @@ -68,19 +73,21 @@ TEST_F(DataCacheTests, GetFreeSlotLocks) { TEST_F(DataCacheTests, GetFreeSlotStartsFromBeginIfNotFit) { - uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1); + asapo::Error err; + uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(1, &meta1,&err); auto id = meta1->id; set_array(ini_addr, 1, 2); cache.UnlockSlot(meta1); - uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2); + uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2,&err); set_array(addr, expected_cache_size, 1); ASSERT_THAT(ini_addr[0], Eq(1)); ASSERT_THAT(id, Ne(meta2->id)); } TEST_F(DataCacheTests, GetFreeSlotCannotWriteIfAlreadyWriting) { - cache.GetFreeSlotAndLock(1, &meta1); - uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2); + asapo::Error err; + cache.GetFreeSlotAndLock(1, &meta1,&err); + uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2,&err); ASSERT_THAT(addr, Eq(nullptr)); ASSERT_THAT(meta2, Eq(nullptr)); @@ -95,8 +102,9 @@ TEST_F(DataCacheTests, PrepareToReadIdNotFound) { } TEST_F(DataCacheTests, PrepareToReadOk) { + asapo::Error err; auto data_size = static_cast<uint64_t>(static_cast<double>(expected_cache_size) * 0.7); - uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(data_size, &meta1); + uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(data_size, &meta1,&err); uint8_t* addr = (uint8_t*) cache.GetSlotToReadAndLock(meta1->id, data_size, &meta2); ASSERT_THAT(addr, Eq(ini_addr)); @@ -106,8 +114,9 @@ TEST_F(DataCacheTests, PrepareToReadOk) { TEST_F(DataCacheTests, PrepareToReadFailsIfTooCloseToCurrentPointer) { + asapo::Error err; auto data_size = static_cast<uint64_t>(static_cast<double>(expected_cache_size) * 0.9); - cache.GetFreeSlotAndLock(data_size, &meta1); + cache.GetFreeSlotAndLock(data_size, &meta1,&err); uint8_t* addr = (uint8_t*) cache.GetSlotToReadAndLock(meta1->id, data_size, &meta2); ASSERT_THAT(addr, Eq(nullptr)); @@ -118,9 +127,10 @@ TEST_F(DataCacheTests, GetFreeSlotRemovesOldMetadataRecords) { DataCache cache{expected_cache_size, 0}; CacheMeta* meta3, *meta4, *meta5; CacheMeta* meta; - cache.GetFreeSlotAndLock(10, &meta1); - cache.GetFreeSlotAndLock(10, &meta2); - cache.GetFreeSlotAndLock(expected_cache_size - 30, &meta3); + asapo::Error err; + cache.GetFreeSlotAndLock(10, &meta1,&err); + cache.GetFreeSlotAndLock(10, &meta2,&err); + cache.GetFreeSlotAndLock(expected_cache_size - 30, &meta3,&err); auto id1 = meta1->id; auto id2 = meta2->id; auto id3 = meta3->id; @@ -129,11 +139,11 @@ TEST_F(DataCacheTests, GetFreeSlotRemovesOldMetadataRecords) { cache.UnlockSlot(meta2); cache.UnlockSlot(meta3); - cache.GetFreeSlotAndLock(10, &meta4); + cache.GetFreeSlotAndLock(10, &meta4,&err); auto id4 = meta4->id; cache.UnlockSlot(meta4); - cache.GetFreeSlotAndLock(30, &meta5); + cache.GetFreeSlotAndLock(30, &meta5,&err); uint8_t* addr1 = (uint8_t*) cache.GetSlotToReadAndLock(id1, 10, &meta); uint8_t* addr2 = (uint8_t*) cache.GetSlotToReadAndLock(id2, 10, &meta); uint8_t* addr3 = (uint8_t*) cache.GetSlotToReadAndLock(id3, expected_cache_size - 30, &meta); @@ -147,22 +157,23 @@ TEST_F(DataCacheTests, GetFreeSlotRemovesOldMetadataRecords) { } TEST_F(DataCacheTests, GetFreeSlotRemovesOldWhenCrossTheBoundary) { + asapo::Error err; DataCache cache{expected_cache_size, 0}; CacheMeta* meta1, *meta2, *meta3; CacheMeta* meta4, *meta5, *meta; - auto addr1_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 3 - 1, &meta1); - auto addr2_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 3 - 1, &meta2); - auto addr3_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 3 - 1, &meta3); + auto addr1_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 3 - 1, &meta1,&err); + auto addr2_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 3 - 1, &meta2,&err); + auto addr3_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 3 - 1, &meta3,&err); auto id1 = meta1->id; auto id2 = meta2->id; auto id3 = meta3->id; cache.UnlockSlot(meta1); cache.UnlockSlot(meta2); cache.UnlockSlot(meta3); - auto addr4_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 2 + 5, &meta4); + auto addr4_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 2 + 5, &meta4,&err); auto id4 = meta4->id; cache.UnlockSlot(meta4); - auto addr5_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 2 + 5, &meta5); + auto addr5_alloc = cache.GetFreeSlotAndLock(expected_cache_size / 2 + 5, &meta5,&err); auto id5 = meta5->id; uint8_t* addr1 = (uint8_t*) cache.GetSlotToReadAndLock(id1, expected_cache_size / 3 - 1, &meta); @@ -190,8 +201,9 @@ TEST_F(DataCacheTests, GetFreeSlotRemovesOldWhenCrossTheBoundary) { TEST_F(DataCacheTests, GetSlotToReadSizeOk) { + asapo::Error err; CacheMeta* meta; - cache.GetFreeSlotAndLock(expected_size, &meta1); + cache.GetFreeSlotAndLock(expected_size, &meta1,&err); uint8_t* addr1 = (uint8_t*) cache.GetSlotToReadAndLock(meta1->id, expected_size, &meta); @@ -201,7 +213,8 @@ TEST_F(DataCacheTests, GetSlotToReadSizeOk) { TEST_F(DataCacheTests, GetSlotToReadWrongSize) { CacheMeta* meta; - cache.GetFreeSlotAndLock(expected_size, &meta1); + asapo::Error err; + cache.GetFreeSlotAndLock(expected_size, &meta1,&err); uint8_t* addr1 = (uint8_t*) cache.GetSlotToReadAndLock(meta1->id, expected_size + 1, &meta); @@ -212,10 +225,12 @@ TEST_F(DataCacheTests, GetSlotToReadWrongSize) { TEST_F(DataCacheTests, CannotGetFreeSlotIfNeedCleanOnebeingReaded) { CacheMeta* meta; + asapo::Error err; - uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(10, &meta1); + + uint8_t* ini_addr = (uint8_t*) cache.GetFreeSlotAndLock(10, &meta1,&err); auto res = cache.GetSlotToReadAndLock(meta1->id, 10, &meta); - uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2); + uint8_t* addr = (uint8_t*) cache.GetFreeSlotAndLock(expected_cache_size, &meta2,&err); ASSERT_THAT(ini_addr, Ne(nullptr)); ASSERT_THAT(res, Eq(ini_addr)); @@ -225,36 +240,40 @@ TEST_F(DataCacheTests, CannotGetFreeSlotIfNeedCleanOnebeingReaded) { TEST_F(DataCacheTests, CanGetFreeSlotIfWasUnlocked) { CacheMeta* meta; - cache.GetFreeSlotAndLock(10, &meta1); + asapo::Error err; + cache.GetFreeSlotAndLock(10, &meta1,&err); cache.UnlockSlot(meta1); cache.GetSlotToReadAndLock(meta1->id, 10, &meta); cache.UnlockSlot(meta); - auto addr = cache.GetFreeSlotAndLock(expected_cache_size, &meta2); + auto addr = cache.GetFreeSlotAndLock(expected_cache_size, &meta2,&err); ASSERT_THAT(addr, Ne(nullptr)); } TEST_F(DataCacheTests, IncreasLockForEveryRead) { CacheMeta* meta; - cache.GetFreeSlotAndLock(10, &meta1); + asapo::Error err; + cache.GetFreeSlotAndLock(10, &meta1,&err); cache.GetSlotToReadAndLock(meta1->id, 10, &meta); cache.GetSlotToReadAndLock(meta1->id, 10, &meta); cache.UnlockSlot(meta); - auto addr = cache.GetFreeSlotAndLock(expected_cache_size, &meta2); + auto addr = cache.GetFreeSlotAndLock(expected_cache_size, &meta2,&err); ASSERT_THAT(addr, Eq(nullptr)); } TEST_F(DataCacheTests, DecreasLockForEveryUnlock) { CacheMeta* meta; - cache.GetFreeSlotAndLock(10, &meta1); + asapo::Error err; + + cache.GetFreeSlotAndLock(10, &meta1,&err); cache.UnlockSlot(meta1); cache.GetSlotToReadAndLock(meta1->id, 10, &meta); cache.GetSlotToReadAndLock(meta1->id, 10, &meta); cache.UnlockSlot(meta); cache.UnlockSlot(meta); - auto addr = cache.GetFreeSlotAndLock(expected_cache_size, &meta2); + auto addr = cache.GetFreeSlotAndLock(expected_cache_size, &meta2,&err); ASSERT_THAT(addr, Ne(nullptr)); } @@ -262,13 +281,14 @@ TEST_F(DataCacheTests, DecreasLockForEveryUnlock) { TEST_F(DataCacheTests, GetFreeSlotCreatesCorrectIds) { CacheMeta* meta3, *meta4; - cache.GetFreeSlotAndLock(10, &meta1); + asapo::Error err; + cache.GetFreeSlotAndLock(10, &meta1,&err); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - cache.GetFreeSlotAndLock(10, &meta2); + cache.GetFreeSlotAndLock(10, &meta2,&err); std::this_thread::sleep_for(std::chrono::milliseconds(10)); - cache.GetFreeSlotAndLock(10, &meta3); + cache.GetFreeSlotAndLock(10, &meta3,&err); std::this_thread::sleep_for(std::chrono::milliseconds(1)); - cache.GetFreeSlotAndLock(10, &meta4); + cache.GetFreeSlotAndLock(10, &meta4,&err); auto c1 = static_cast<uint32_t>(meta1->id); auto c2 = static_cast<uint32_t>(meta2->id); diff --git a/receiver/unittests/test_request.cpp b/receiver/unittests/test_request.cpp index a8c96669096df6cd64ed805e987fb856e2696e53..4bd58d36a20ecf17e3e48536c1d1da9eec024340 100644 --- a/receiver/unittests/test_request.cpp +++ b/receiver/unittests/test_request.cpp @@ -71,6 +71,7 @@ class RequestTests : public Test { Return(0) )); } + void MockAllocateRequestSlot(); void TearDown() override { request->io__.release(); } @@ -78,8 +79,19 @@ class RequestTests : public Test { }; -TEST_F(RequestTests, HandleProcessesRequests) { +void RequestTests::MockAllocateRequestSlot() +{ + request->cache__ = &mock_cache; + asapo::CacheMeta meta; + EXPECT_CALL(mock_cache, GetFreeSlotAndLock_t(data_size_, _, _)).WillOnce( + DoAll(SetArgPointee<1>(&meta), + SetArgPointee<2>(nullptr), + Return(&mock_cache) + )); + request->PrepareDataBufferAndLockIfNeeded(); +} +TEST_F(RequestTests, HandleProcessesRequests) { MockReqestHandler mock_request_handler; EXPECT_CALL(mock_request_handler, ProcessRequest_t(_)).WillOnce( @@ -88,13 +100,13 @@ TEST_F(RequestTests, HandleProcessesRequests) { Return(new asapo::IOError("Test Send Error", "", asapo::IOErrorType::kUnknownIOError)) ); + MockAllocateRequestSlot(); request->AddHandler(&mock_request_handler); request->AddHandler(&mock_request_handler); EXPECT_CALL(mock_statistics, StartTimer_t(asapo::StatisticEntity::kDisk)).Times(2); - EXPECT_CALL(mock_statistics, StopTimer_t()).Times(1); - + EXPECT_CALL(mock_cache, UnlockSlot(_)); auto err = request->Handle(stat);