2929#include < unistd.h>
3030#include " file/file.h"
3131#include " logger/logger.h"
32- #include " trans/buffer .h"
32+ #include " trans/device .h"
3333
3434namespace UC {
3535
3636static constexpr int32_t SHARE_BUFFER_MAGIC = ((' S' << 16 ) | (' b' << 8 ) | 1 );
37+ static constexpr size_t INVALID_POSITION = size_t (-1 );
3738
3839struct ShareMutex {
3940 pthread_mutex_t mutex;
@@ -87,12 +88,24 @@ struct ShareBlockHeader {
8788 ShareBlockStatus status;
8889 size_t offset;
8990 void * Data () { return reinterpret_cast <char *>(this ) + offset; }
91+ void Refer ()
92+ {
93+ if (this ->ref == 0 && this ->status != ShareBlockStatus::LOADED) {
94+ this ->status = ShareBlockStatus::INIT;
95+ }
96+ this ->ref ++;
97+ }
98+ void Occupy (const std::string& block)
99+ {
100+ this ->id .Set (block);
101+ this ->ref = 1 ;
102+ this ->status = ShareBlockStatus::INIT;
103+ }
90104};
91105
92106struct ShareBufferHeader {
93107 ShareMutex mutex;
94108 std::atomic<int32_t > magic;
95- int32_t ref;
96109 size_t blockSize;
97110 size_t blockNumber;
98111 ShareBlockHeader headers[0 ];
@@ -128,13 +141,14 @@ void CleanUpShmFileExceptMe(const std::string& me)
128141}
129142
130143Status ShareBuffer::Setup (const size_t blockSize, const size_t blockNumber, const bool ioDirect,
131- const size_t nSharer, const std::string& uniqueId)
144+ const std::string& uniqueId)
132145{
133146 this ->blockSize_ = blockSize;
134147 this ->blockNumber_ = blockNumber;
135148 this ->ioDirect_ = ioDirect;
136- this ->nSharer_ = nSharer;
137149 this ->addr_ = nullptr ;
150+ tmpBufMaker_ = Trans::Device{}.MakeBuffer ();
151+ if (!tmpBufMaker_) { return Status::OutOfMemory (); }
138152 this ->shmName_ = ShmPrefix () + uniqueId;
139153 CleanUpShmFileExceptMe (this ->shmName_ );
140154 auto file = File::Make (this ->shmName_ );
@@ -149,31 +163,19 @@ Status ShareBuffer::Setup(const size_t blockSize, const size_t blockNumber, cons
149163ShareBuffer::~ShareBuffer ()
150164{
151165 if (!this ->addr_ ) { return ; }
152- auto bufferHeader = (ShareBufferHeader*)this ->addr_ ;
153- bufferHeader->mutex .Lock ();
154- auto ref = (--bufferHeader->ref );
155- bufferHeader->mutex .Unlock ();
156166 void * dataAddr = static_cast <char *>(this ->addr_ ) + this ->DataOffset ();
157167 Trans::Buffer::UnregisterHostBuffer (dataAddr);
158168 const auto shmSize = this ->ShmSize ();
159169 File::MUnmap (this ->addr_ , shmSize);
160- if (ref == 0 ) { File::ShmUnlink (this ->shmName_ ); }
170+ File::ShmUnlink (this ->shmName_ );
161171}
162172
163173std::shared_ptr<ShareBuffer::Reader> ShareBuffer::MakeReader (const std::string& block,
164174 const std::string& path)
165175{
166- auto index = this ->AcquireBlock (block);
167- try {
168- void * addr = this ->BlockAt (index);
169- return std::shared_ptr<Reader>(
170- new Reader{block, path, blockSize_, ioDirect_, nSharer_, addr},
171- [this , index](auto ) { this ->ReleaseBlock (index); });
172- } catch (...) {
173- this ->ReleaseBlock (index);
174- UC_ERROR (" Failed to create reader." );
175- return nullptr ;
176- }
176+ auto pos = this ->AcquireBlock (block);
177+ if (pos != INVALID_POSITION) { return MakeSharedReader (block, path, pos); }
178+ return MakeLocalReader (block, path);
177179}
178180
179181size_t ShareBuffer::DataOffset () const
@@ -198,7 +200,6 @@ Status ShareBuffer::InitShmBuffer(IFile* file)
198200 auto bufferHeader = (ShareBufferHeader*)this ->addr_ ;
199201 bufferHeader->magic = 1 ;
200202 bufferHeader->mutex .Init ();
201- bufferHeader->ref = this ->nSharer_ ;
202203 bufferHeader->blockSize = this ->blockSize_ ;
203204 bufferHeader->blockNumber = this ->blockNumber_ ;
204205 const auto dataOffset = this ->DataOffset ();
@@ -215,7 +216,7 @@ Status ShareBuffer::InitShmBuffer(IFile* file)
215216 auto dataSize = shmSize - dataOffset;
216217 auto status = Trans::Buffer::RegisterHostBuffer (dataAddr, dataSize);
217218 if (status.Success ()) { return Status::OK (); }
218- UC_ERROR (" Failed({}) to regitster host buffer({})." , status.ToString (), dataSize);
219+ UC_ERROR (" Failed({}) to register host buffer({})." , status.ToString (), dataSize);
219220 return Status::Error ();
220221}
221222
@@ -246,7 +247,7 @@ Status ShareBuffer::LoadShmBuffer(IFile* file)
246247 auto dataSize = shmSize - dataOffset;
247248 auto status = Trans::Buffer::RegisterHostBuffer (dataAddr, dataSize);
248249 if (status.Success ()) { return Status::OK (); }
249- UC_ERROR (" Failed({}) to regitster host buffer({})." , status.ToString (), dataSize);
250+ UC_ERROR (" Failed({}) to register host buffer({})." , status.ToString (), dataSize);
250251 return Status::Error ();
251252}
252253
@@ -255,36 +256,39 @@ size_t ShareBuffer::AcquireBlock(const std::string& block)
255256 static std::hash<std::string> hasher{};
256257 auto pos = hasher (block) % this ->blockNumber_ ;
257258 auto bufferHeader = (ShareBufferHeader*)this ->addr_ ;
258- auto reusedIdx = this -> blockNumber_ ;
259+ auto reusedPos = INVALID_POSITION ;
259260 bufferHeader->mutex .Lock ();
260- for (size_t i = 0 ;; i++) {
261- if (! bufferHeader->headers [pos]. id . Used ()) {
262- if (reusedIdx == this -> blockNumber_ ) { reusedIdx = pos; }
263- break ;
264- }
265- if (bufferHeader-> headers [pos]. id == block) {
266- reusedIdx = pos ;
267- break ;
261+ for (size_t i = 0 ; i < this -> blockNumber_ ; i++) {
262+ auto header = bufferHeader->headers + pos;
263+ header-> mutex . Lock ();
264+ if (header-> id == block) {
265+ header-> Refer ();
266+ header-> mutex . Unlock ();
267+ bufferHeader-> mutex . Unlock () ;
268+ return pos ;
268269 }
269- if (bufferHeader->headers [pos].ref <= 0 ) {
270- if (reusedIdx == this ->blockNumber_ ) { reusedIdx = pos; }
270+ if (!header->id .Used ()) {
271+ if (reusedPos != INVALID_POSITION) {
272+ header->mutex .Unlock ();
273+ break ;
274+ }
275+ header->Occupy (block);
276+ header->mutex .Unlock ();
277+ bufferHeader->mutex .Unlock ();
278+ return pos;
271279 }
280+ if (header->ref <= 0 && reusedPos == INVALID_POSITION) { reusedPos = pos; }
281+ header->mutex .Unlock ();
272282 pos = (pos + 1 ) % this ->blockNumber_ ;
273- if (i == this ->blockNumber_ ) {
274- UC_WARN (" Buffer({}) used out." , this ->blockNumber_ );
275- i = 0 ;
276- }
277283 }
278- auto blockHeader = bufferHeader->headers + reusedIdx;
279- blockHeader->mutex .Lock ();
280- if (blockHeader->ref <= 0 ) {
281- blockHeader->id .Set (block);
282- blockHeader->ref = this ->nSharer_ ;
283- blockHeader->status = ShareBlockStatus::INIT;
284+ if (reusedPos != INVALID_POSITION) {
285+ auto header = bufferHeader->headers + reusedPos;
286+ header->mutex .Lock ();
287+ header->Occupy (block);
288+ header->mutex .Unlock ();
284289 }
285- blockHeader->mutex .Unlock ();
286290 bufferHeader->mutex .Unlock ();
287- return reusedIdx ;
291+ return reusedPos ;
288292}
289293
290294void ShareBuffer::ReleaseBlock (const size_t index)
@@ -301,7 +305,67 @@ void* ShareBuffer::BlockAt(const size_t index)
301305 return bufferHeader->headers + index;
302306}
303307
308+ std::shared_ptr<ShareBuffer::Reader> ShareBuffer::MakeLocalReader (const std::string& block,
309+ const std::string& path)
310+ {
311+ auto addr = tmpBufMaker_->MakeHostBuffer (blockSize_);
312+ if (!addr) [[unlikely]] {
313+ UC_ERROR (" Failed to make buffer({}) on host." , blockSize_);
314+ return nullptr ;
315+ }
316+ Reader* reader = nullptr ;
317+ try {
318+ reader = new Reader{block, path, blockSize_, ioDirect_, false , addr.get ()};
319+ return std::shared_ptr<Reader>(reader,
320+ [addr = std::move (addr)](Reader* reader) { delete reader; });
321+ } catch (const std::exception& e) {
322+ if (reader) { delete reader; }
323+ UC_ERROR (" Failed({}) to create reader." , e.what ());
324+ return nullptr ;
325+ }
326+ }
327+
328+ std::shared_ptr<ShareBuffer::Reader> ShareBuffer::MakeSharedReader (const std::string& block,
329+ const std::string& path,
330+ size_t position)
331+ {
332+ void * addr = this ->BlockAt (position);
333+ Reader* reader = nullptr ;
334+ try {
335+ reader = new Reader{block, path, blockSize_, ioDirect_, true , addr};
336+ return std::shared_ptr<Reader>(reader, [this , position](Reader* reader) {
337+ delete reader;
338+ this ->ReleaseBlock (position);
339+ });
340+ } catch (...) {
341+ this ->ReleaseBlock (position);
342+ if (reader) { delete reader; }
343+ UC_ERROR (" Failed to create reader." );
344+ return nullptr ;
345+ }
346+ }
347+
304348Status ShareBuffer::Reader::Ready4Read ()
349+ {
350+ if (shared_) { return Ready4ReadOnSharedBuffer (); }
351+ return Ready4ReadOnLocalBuffer ();
352+ }
353+
354+ uintptr_t ShareBuffer::Reader::GetData ()
355+ {
356+ if (shared_) {
357+ auto header = (ShareBlockHeader*)this ->addr_ ;
358+ return (uintptr_t )header->Data ();
359+ }
360+ return (uintptr_t )this ->addr_ ;
361+ }
362+
363+ Status ShareBuffer::Reader::Ready4ReadOnLocalBuffer ()
364+ {
365+ return File::Read (this ->path_ , 0 , this ->length_ , this ->GetData (), this ->ioDirect_ );
366+ }
367+
368+ Status ShareBuffer::Reader::Ready4ReadOnSharedBuffer ()
305369{
306370 auto header = (ShareBlockHeader*)this ->addr_ ;
307371 if (header->status == ShareBlockStatus::LOADED) { return Status::OK (); }
@@ -324,10 +388,4 @@ Status ShareBuffer::Reader::Ready4Read()
324388 return s;
325389}
326390
327- uintptr_t ShareBuffer::Reader::GetData ()
328- {
329- auto header = (ShareBlockHeader*)this ->addr_ ;
330- return (uintptr_t )header->Data ();
331- }
332-
333391} // namespace UC
0 commit comments