@@ -176,10 +176,11 @@ int MultiuserFile::Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv
176176
177177ssize_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
303338int 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