Skip to content

Commit b830dd6

Browse files
Copilotbbockelm
andcommitted
Address PR feedback: conditional locking, buffer filling, and merge PR #61 logic
Co-authored-by: bbockelm <1093447+bbockelm@users.noreply.github.com>
1 parent 421bbee commit b830dd6

1 file changed

Lines changed: 48 additions & 9 deletions

File tree

src/multiuser.cpp

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,11 @@ int MultiuserFile::Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv
176176

177177
ssize_t MultiuserFile::Write(const void *buffer, off_t offset, size_t size)
178178
{
179-
// Lock protects buffer state and sequential write tracking.
180-
// While this serializes writes to the same file, it ensures correctness
181-
// and is consistent with the sequential write assumption.
182-
std::lock_guard<std::mutex> lock(m_buffer_mutex);
179+
// Only take the lock if buffering is configured (m_write_buffer_size > 0)
180+
std::unique_lock<std::mutex> lock(m_buffer_mutex, std::defer_lock);
181+
if (m_write_buffer_size > 0) {
182+
lock.lock();
183+
}
183184

184185
// Check for out-of-order writes if checksumming or buffering
185186
if ((offset != m_nextoff) && (m_state || m_buffering_enabled))
@@ -196,9 +197,10 @@ ssize_t MultiuserFile::Write(const void *buffer, off_t offset, size_t size)
196197

197198
if (m_state) {
198199
std::stringstream ss;
199-
ss << "Out-of-order writes not supported while running checksum. " << m_fname;
200+
ss << "Non-sequential write detected; disabling checksum calculation for " << m_fname;
200201
m_log.Emsg("Write", ss.str().c_str());
201-
return -ENOTSUP;
202+
delete m_state;
203+
m_state = NULL;
202204
}
203205
}
204206

@@ -234,12 +236,45 @@ ssize_t MultiuserFile::Write(const void *buffer, off_t offset, size_t size)
234236
m_nextoff = offset + size;
235237
return size;
236238
} else {
237-
// Buffer would exceed limit - flush and write directly
239+
// Buffer would exceed limit - fill buffer to maximum, flush, then continue
240+
size_t space_in_buffer = m_write_buffer_size - m_write_buffer.size();
241+
if (space_in_buffer > 0) {
242+
// Fill the buffer completely
243+
if (m_write_buffer.capacity() < m_write_buffer_size) {
244+
m_write_buffer.reserve(m_write_buffer_size);
245+
}
246+
m_write_buffer.insert(m_write_buffer.end(),
247+
static_cast<const unsigned char*>(buffer),
248+
static_cast<const unsigned char*>(buffer) + space_in_buffer);
249+
}
250+
251+
// Flush the full buffer
238252
int flush_result = FlushWriteBuffer();
239253
if (flush_result < 0) {
240254
return flush_result;
241255
}
242-
// Fall through to direct write
256+
257+
// Now handle the remaining data
258+
const unsigned char* remaining_data = static_cast<const unsigned char*>(buffer) + space_in_buffer;
259+
size_t remaining_size = size - space_in_buffer;
260+
261+
// If remaining data fits in buffer, buffer it; otherwise write directly
262+
if (remaining_size <= m_write_buffer_size) {
263+
m_buffer_offset = offset + space_in_buffer;
264+
if (m_write_buffer.capacity() < remaining_size) {
265+
m_write_buffer.reserve(remaining_size);
266+
}
267+
m_write_buffer.insert(m_write_buffer.end(),
268+
remaining_data,
269+
remaining_data + remaining_size);
270+
m_nextoff = offset + size;
271+
return size;
272+
} else {
273+
// Remaining data is too large for buffer - fall through to direct write
274+
buffer = remaining_data;
275+
offset = offset + space_in_buffer;
276+
size = remaining_size;
277+
}
243278
}
244279
}
245280
}
@@ -302,7 +337,11 @@ int MultiuserFile::FlushWriteBuffer()
302337

303338
int MultiuserFile::Close(long long *retsz)
304339
{
305-
std::lock_guard<std::mutex> lock(m_buffer_mutex);
340+
// Only take the lock if buffering is configured (m_write_buffer_size > 0)
341+
std::unique_lock<std::mutex> lock(m_buffer_mutex, std::defer_lock);
342+
if (m_write_buffer_size > 0) {
343+
lock.lock();
344+
}
306345

307346
// Flush any remaining buffered data
308347
if (!m_write_buffer.empty()) {

0 commit comments

Comments
 (0)