1
0
forked from 0ad/0ad
0ad/source/lib/res/file/file_io.h
janwas b755ddefda remove all author/modified by tags.
make include guards consistent.

This was SVN commit r5040.
2007-05-07 16:33:24 +00:00

150 lines
5.1 KiB
C++

/**
* =========================================================================
* File : file_io.h
* Project : 0 A.D.
* Description : provide fast I/O via POSIX aio and splitting into blocks.
* =========================================================================
*/
// license: GPL; see lib/license.txt
#ifndef INCLUDED_FILE_IO
#define INCLUDED_FILE_IO
struct FileProvider_VTbl;
struct File;
namespace ERR
{
const LibError IO = -110100;
const LibError IO_EOF = -110101;
}
extern void file_io_init();
extern void file_io_shutdown();
//
// asynchronous IO
//
// this is a thin wrapper on top of the system AIO calls.
// IOs are carried out exactly as requested - there is no caching or
// alignment done here. rationale: see source.
// again chosen for nice alignment; each user checks if big enough.
const size_t FILE_IO_OPAQUE_SIZE = 28;
struct FileIo
{
const FileProvider_VTbl* type;
u8 opaque[FILE_IO_OPAQUE_SIZE];
};
// queue the IO; it begins after the previous ones (if any) complete.
//
// rationale: this interface is more convenient than implicitly advancing a
// file pointer because archive.cpp often accesses random offsets.
extern LibError file_io_issue(File* f, off_t ofs, size_t size, void* buf, FileIo* io);
// indicates if the given IO has completed.
// return value: 0 if pending, 1 if complete, < 0 on error.
extern int file_io_has_completed(FileIo* io);
// wait for the given IO to complete. passes back its buffer and size.
extern LibError file_io_wait(FileIo* io, void*& p, size_t& size);
// indicates the IO's buffer is no longer needed and frees that memory.
extern LibError file_io_discard(FileIo* io);
extern LibError file_io_validate(const FileIo* io);
//
// synchronous IO
//
extern size_t file_sector_size;
// called by file_io after a block IO has completed.
// *bytes_processed must be set; file_io will return the sum of these values.
// example: when reading compressed data and decompressing in the callback,
// indicate #bytes decompressed.
// return value: INFO::CB_CONTINUE to continue calling; anything else:
// abort immediately and return that.
// note: in situations where the entire IO is not split into blocks
// (e.g. when reading from cache or not using AIO), this is still called but
// for the entire IO. we do not split into fake blocks because it is
// advantageous (e.g. for decompressors) to have all data at once, if available
// anyway.
typedef LibError (*FileIOCB)(uintptr_t ctx, const void* block, size_t size, size_t* bytes_processed);
typedef const u8* FileIOBuf;
FileIOBuf* const FILE_BUF_TEMP = (FileIOBuf*)1;
const FileIOBuf FILE_BUF_ALLOC = (FileIOBuf)2;
enum FileBufFlags
{
// indicates the buffer will not be freed immediately
// (i.e. before the next buffer alloc) as it normally should.
// this flag serves to suppress a warning and better avoid fragmentation.
// caller sets this when FILE_LONG_LIVED is specified.
//
// also used by file_cache_retrieve because it may have to
// 'reactivate' the buffer (transfer from cache to extant list),
// which requires knowing whether the buffer is long-lived or not.
FB_LONG_LIVED = 1,
// statistics (e.g. # buffer allocs) should not be updated.
// (useful for simulation, e.g. trace_entry_causes_io)
FB_NO_STATS = 2,
// file_cache_retrieve should not update item credit.
// (useful when just looking up buffer given atom_fn)
FB_NO_ACCOUNTING = 4,
// memory will be allocated from the heap, not the (limited) file cache.
// this makes sense for write buffers that are never used again,
// because we avoid having to displace some other cached items.
FB_FROM_HEAP = 8
};
// allocate a new buffer of <size> bytes (possibly more due to internal
// fragmentation). never returns 0.
// <atom_fn>: owner filename (buffer is intended to be used for data from
// this file).
extern FileIOBuf file_buf_alloc(size_t size, const char* atom_fn, uint fb_flags = 0);
// mark <buf> as no longer needed. if its reference count drops to 0,
// it will be removed from the extant list. if it had been added to the
// cache, it remains there until evicted in favor of another buffer.
extern LibError file_buf_free(FileIOBuf buf, uint fb_flags = 0);
// transfer <size> bytes, starting at <ofs>, to/from the given file.
// (read or write access was chosen at file-open time).
//
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
// it returns how much data was actually transferred, or a negative error
// code (in which case we abort the transfer and return that value).
// the callback mechanism is useful for user progress notification or
// processing data while waiting for the next I/O to complete
// (quasi-parallel, without the complexity of threads).
//
// return number of bytes transferred (see above), or a negative error code.
extern ssize_t file_io(File* f, off_t ofs, size_t size, FileIOBuf* pbuf, FileIOCB cb = 0, uintptr_t ctx = 0);
extern ssize_t file_read_from_cache(const char* atom_fn, off_t ofs, size_t size,
FileIOBuf* pbuf, FileIOCB cb, uintptr_t ctx);
extern LibError file_io_get_buf(FileIOBuf* pbuf, size_t size,
const char* atom_fn, uint file_flags, FileIOCB cb);
#endif // #ifndef INCLUDED_FILE_IO