#ifndef SYSCALL_HEADER
#define SYSCALL_HEADER
/***************************************************************************
* syscall_file.h
*
* Sat Aug 24 23:55:08 2002
* Copyright 2002 Roman Dementiev
* dementiev@mpi-sb.mpg.de
****************************************************************************/
#include "ufs_file.h"
#include "../common/debug.h"
__STXXL_BEGIN_NAMESPACE
//! \addtogroup fileimpl
//! \{
//! \brief Implementation of file based on UNIX syscalls
class syscall_file:public ufs_file_base
{
protected:
public:
//! \brief constructs file object
//! \param filename path of file
//! \attention filename must be resided at memory disk partition
//! \param mode open mode, see \c stxxl::file::open_modes
//! \param disk disk(file) identifier
syscall_file(
const std::string & filename,
int mode,
int disk = -1): ufs_file_base (filename, mode, disk)
{
};
request_ptr aread(
void *buffer,
stxxl::int64 pos,
size_t bytes,
completion_handler on_cmpl);
request_ptr awrite(
void *buffer,
stxxl::int64 pos,
size_t bytes,
completion_handler on_cmpl);
};
//! \brief Implementation of request based on UNIX syscalls
class syscall_request: public ufs_request_base
{
friend class syscall_file;
protected:
syscall_request(
syscall_file * f,
void *buf,
stxxl::int64 off,
size_t b,
request_type t,
completion_handler on_cmpl):
ufs_request_base(f,buf,off,b,t,on_cmpl)
{
};
void serve ();
public:
const char *io_type ()
{
return "syscall";
};
private:
// Following methods are declared but not implemented
// intentionnaly to forbid their usage
syscall_request(const syscall_request &);
syscall_request & operator=(const syscall_request &);
syscall_request();
};
void syscall_request::serve ()
{
stats * iostats = stats::get_instance();
if(nref() < 2)
{
STXXL_ERRMSG("WARNING: serious error, reference to the request is lost before serve (nref="
<<nref()<<") "<<
" this="<<long(this)<<
" File descriptor="<<
static_cast<syscall_file*>(file_)->get_file_des()<< " offset="<<offset<<" buffer="<<buffer<<" bytes="<<bytes
<< " type=" <<((type == READ)?"READ":"WRITE") )
}
STXXL_VERBOSE2("syscall_request::serve(): Buffer at "<<((void*)buffer)
<<" offset: "<<offset<<" bytes: "<<bytes<<((type== READ)?" READ":" WRITE")
<<" file: "<<static_cast<syscall_file*>(file_)->get_file_des());
stxxl_ifcheck_i(::lseek (static_cast<syscall_file*>(file_)->get_file_des (), offset, SEEK_SET),
" this="<<long(this)<<" File descriptor="<<
static_cast<syscall_file*>(file_)->get_file_des()<< " offset="<<offset<<" buffer="<<
buffer<<" bytes="<<bytes
<< " type=" <<((type == READ)?"READ":"WRITE") )
else
{
if (type == READ)
{
#ifdef STXXL_IO_STATS
iostats->read_started (size());
#endif
debugmon::get_instance()->io_started((char*)buffer);
stxxl_ifcheck_i(::read (static_cast<syscall_file*>(file_)->get_file_des(), buffer, bytes),
" this="<<long(this)<<" File descriptor="<<
static_cast<syscall_file*>(file_)->get_file_des()<< " offset="<<offset<<
" buffer="<<buffer<<" bytes="<<bytes<< " type=" <<
((type == READ)?"READ":"WRITE")<<" nref= "<<nref())
debugmon::get_instance()->io_finished((char*)buffer);
#ifdef STXXL_IO_STATS
iostats->read_finished ();
#endif
}
else
{
#ifdef STXXL_IO_STATS
iostats->write_started (size());
#endif
debugmon::get_instance()->io_started((char*)buffer);
stxxl_ifcheck_i(::write (static_cast<syscall_file*>(file_)->get_file_des (), buffer, bytes),
" this="<<long(this)<<" File descriptor="<<
static_cast<syscall_file*>(file_)->get_file_des()<< " offset="<<offset<<" buffer="<<
buffer<<" bytes="<<bytes<< " type=" <<
((type == READ)?"READ":"WRITE")<<" nref= "<<nref());
debugmon::get_instance()->io_finished((char*)buffer);
#ifdef STXXL_IO_STATS
iostats->write_finished ();
#endif
}
}
if(nref() < 2)
{
STXXL_ERRMSG("WARNING: reference to the request is lost after serve (nref="<<nref()<<") "<<
" this="<<long(this)<<" File descriptor="<<static_cast<syscall_file*>(file_)->get_file_des()<<
" offset="<<offset<<" buffer="<<buffer<<" bytes="<<bytes <<
" type=" <<((type == READ)?"READ":"WRITE"))
}
_state.set_to (DONE);
#ifdef STXXL_BOOST_THREADS
boost::mutex::scoped_lock Lock(waiters_mutex);
#else
waiters_mutex.lock ();
#endif
// << notification >>
std::for_each(
waiters.begin(),
waiters.end(),
std::mem_fun(&onoff_switch::on) );
#ifdef STXXL_BOOST_THREADS
Lock.unlock();
#else
waiters_mutex.unlock ();
#endif
completed ();
_state.set_to (READY2DIE);
}
request_ptr syscall_file::aread (
void *buffer,
stxxl::int64 pos,
size_t bytes,
completion_handler on_cmpl)
{
request_ptr req = new syscall_request(this,
buffer, pos, bytes,
request::READ, on_cmpl);
if(!req.get())
stxxl_function_error;
#ifndef NO_OVERLAPPING
disk_queues::get_instance ()->add_readreq(req,get_id());
#endif
return req;
};
request_ptr syscall_file::awrite (
void *buffer,
stxxl::int64 pos,
size_t bytes,
completion_handler on_cmpl)
{
request_ptr req = new syscall_request(this, buffer, pos, bytes,
request::WRITE, on_cmpl);
if(!req.get())
stxxl_function_error;
#ifndef NO_OVERLAPPING
disk_queues::get_instance ()->add_writereq(req,get_id());
#endif
return req;
};
//! \}
__STXXL_END_NAMESPACE
#endif