off_t offset() const;
virtual void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) = 0;
- virtual void write(char const *buf, size_t size, off_t offset, FREE * free_func) = 0;
+ /** write the given buffer and free it when it is no longer needed
+ * \param offset zero for the very first write and -1 for all other writes
+ * \retval false if write failed (callback has been or will be called)
+ */
+ virtual bool write(char const *buf, size_t size, off_t offset, FREE * free_func) = 0;
typedef enum {
wroteAll, ///< success: caller supplied all data it wanted to swap out
CossMemBuf *locked_membuf;
off_t st_size;
+ /* StoreIOState API */
void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data);
- void write(char const *buf, size_t size, off_t offset, FREE * free_func);
+ virtual bool write(char const *buf, size_t size, off_t offset, FREE * free_func);
virtual void close(int);
void doCallback(int errflag);
void lockMemBuf();
}
}
-void
+bool
CossState::write(char const *buf, size_t size, off_t offset, FREE * free_func)
{
char *dest;
(free_func) ((char *)buf);
++ StoreFScoss::GetInstance().stats.write.success;
+ return true;
}
off_t
* writes and just do the write directly. But for now we'll keep the
* code simpler and always go through the pending_writes queue.
*/
-void
+bool
Fs::Ufs::UFSStoreState::write(char const *buf, size_t size, off_t aOffset, FREE * free_func)
{
debugs(79, 3, "UFSStoreState::write: dirn " << swap_dirn << ", fileno "<<
debugs(79, DBG_IMPORTANT,HERE << "avoid write on theFile with error");
debugs(79, DBG_IMPORTANT,HERE << "calling free_func for " << (void*) buf);
free_func((void*)buf);
- return;
+ return false;
}
queueWrite(buf, size, aOffset, free_func);
drainWriteQueue();
+ return true;
}
/*
bool closing;
bool reading;
bool writing;
+ /* StoreIOState API */
void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data);
- void write(char const *buf, size_t size, off_t offset, FREE * free_func);
+ virtual bool write(char const *buf, size_t size, off_t offset, FREE * free_func);
protected:
virtual void doCloseCallback (int errflag);
e->swap_dirn = mem->swapout.sio->swap_dirn;
}
-static void
+static bool
doPages(StoreEntry *anEntry)
{
MemObject *mem = anEntry->mem_obj;
mem->data_hdr.getBlockContainingLocation(mem->swapout.queue_offset);
if (!page)
- return; // wait for more data to become available
+ break; // wait for more data to become available
// memNodeWriteComplete() and absence of buffer offset math below
// imply that we always write from the very beginning of the page
mem->swapout.queue_offset += swap_buf_len;
- storeIOWrite(mem->swapout.sio,
+ // Quit if write() fails. Sio is going to call our callback, and that
+ // will cleanup, but, depending on the fs, that call may be async.
+ const bool ok = mem->swapout.sio->write(
mem->data_hdr.NodeGet(page),
swap_buf_len,
-1,
memNodeWriteComplete);
- /* the storeWrite() call might generate an error */
- if (anEntry->swap_status != SWAPOUT_WRITING)
- break;
+ if (!ok || anEntry->swap_status != SWAPOUT_WRITING)
+ return false;
int64_t swapout_size = mem->endOffset() - mem->swapout.queue_offset;
break;
if (swapout_size <= 0)
- return;
+ break;
} while (true);
+
+ // either wait for more data or call swapOutFileClose()
+ return true;
}
/* This routine is called every time data is sent to the client side.
if (mem_obj->swapout.sio == NULL)
return;
- doPages(this);
-
- if (mem_obj->swapout.sio == NULL)
+ if (!doPages(this))
/* oops, we're not swapping out any more */
return;