mirror of https://github.com/OpenTTD/OpenTTD
(svn r8647) -Codechange: add a general way to handle platforms who can only have a limited amount of file-descripters open at any given time.
The Fios keeps track how many times a file is opened, and tries to close up files which aren't used often. The first platform using this is PSP. Patch based on the work of Turulo.release/0.6
parent
424001168d
commit
7cd68b5a07
|
@ -7,19 +7,26 @@
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
/* FILE IO ROUTINES ******************************/
|
/* FILE IO ROUTINES ******************************/
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
|
|
||||||
#define FIO_BUFFER_SIZE 512
|
#define FIO_BUFFER_SIZE 512
|
||||||
|
#define MAX_HANDLES 64
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer
|
byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer
|
||||||
uint32 pos; ///< current (system) position in file
|
uint32 pos; ///< current (system) position in file
|
||||||
FILE *cur_fh; ///< current file handle
|
FILE *cur_fh; ///< current file handle
|
||||||
FILE *handles[64]; ///< array of file handles we can have open
|
FILE *handles[MAX_HANDLES]; ///< array of file handles we can have open
|
||||||
byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file
|
byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file
|
||||||
|
#if defined(LIMITED_FDS)
|
||||||
|
uint open_handles; ///< current amount of open handles
|
||||||
|
const char *filename[MAX_HANDLES]; ///< array of filenames we (should) have open
|
||||||
|
uint usage_count[MAX_HANDLES]; ///< count how many times this file has been opened
|
||||||
|
#endif /* LIMITED_FDS */
|
||||||
} Fio;
|
} Fio;
|
||||||
|
|
||||||
static Fio _fio;
|
static Fio _fio;
|
||||||
|
@ -38,10 +45,27 @@ void FioSeekTo(uint32 pos, int mode)
|
||||||
fseek(_fio.cur_fh, _fio.pos, SEEK_SET);
|
fseek(_fio.cur_fh, _fio.pos, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(LIMITED_FDS)
|
||||||
|
static void FioRestoreFile(int slot)
|
||||||
|
{
|
||||||
|
/* Do we still have the file open, or should we reopen it? */
|
||||||
|
if (_fio.handles[slot] == NULL) {
|
||||||
|
DEBUG(misc, 6, "Restoring file '%s' in slot '%d' from disk", _fio.filename[slot], slot);
|
||||||
|
FioOpenFile(slot, _fio.filename[slot]);
|
||||||
|
}
|
||||||
|
_fio.usage_count[slot]++;
|
||||||
|
}
|
||||||
|
#endif /* LIMITED_FDS */
|
||||||
|
|
||||||
// Seek to a file and a position
|
// Seek to a file and a position
|
||||||
void FioSeekToFile(uint32 pos)
|
void FioSeekToFile(uint32 pos)
|
||||||
{
|
{
|
||||||
FILE *f = _fio.handles[pos >> 24];
|
FILE *f;
|
||||||
|
#if defined(LIMITED_FDS)
|
||||||
|
/* Make sure we have this file open */
|
||||||
|
FioRestoreFile(pos >> 24);
|
||||||
|
#endif /* LIMITED_FDS */
|
||||||
|
f = _fio.handles[pos >> 24];
|
||||||
assert(f != NULL);
|
assert(f != NULL);
|
||||||
_fio.cur_fh = f;
|
_fio.cur_fh = f;
|
||||||
FioSeekTo(GB(pos, 0, 24), SEEK_SET);
|
FioSeekTo(GB(pos, 0, 24), SEEK_SET);
|
||||||
|
@ -92,6 +116,9 @@ static inline void FioCloseFile(int slot)
|
||||||
if (_fio.handles[slot] != NULL) {
|
if (_fio.handles[slot] != NULL) {
|
||||||
fclose(_fio.handles[slot]);
|
fclose(_fio.handles[slot]);
|
||||||
_fio.handles[slot] = NULL;
|
_fio.handles[slot] = NULL;
|
||||||
|
#if defined(LIMITED_FDS)
|
||||||
|
_fio.open_handles--;
|
||||||
|
#endif /* LIMITED_FDS */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +139,30 @@ bool FioCheckFileExists(const char *filename)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(LIMITED_FDS)
|
||||||
|
static void FioFreeHandle()
|
||||||
|
{
|
||||||
|
/* If we are about to open a file that will exceed the limit, close a file */
|
||||||
|
if (_fio.open_handles + 1 == LIMITED_FDS) {
|
||||||
|
uint i, count;
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
count = UINT_MAX;
|
||||||
|
slot = -1;
|
||||||
|
/* Find the file that is used the least */
|
||||||
|
for (i = 0; i < lengthof(_fio.handles); i++) {
|
||||||
|
if (_fio.handles[i] != NULL && _fio.usage_count[i] < count) {
|
||||||
|
count = _fio.usage_count[i];
|
||||||
|
slot = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(slot != -1);
|
||||||
|
DEBUG(misc, 6, "Closing filehandler '%s' in slot '%d' because of fd-limit", _fio.filename[slot], slot);
|
||||||
|
FioCloseFile(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* LIMITED_FDS */
|
||||||
|
|
||||||
FILE *FioFOpenFile(const char *filename)
|
FILE *FioFOpenFile(const char *filename)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
@ -141,11 +192,20 @@ FILE *FioFOpenFile(const char *filename)
|
||||||
|
|
||||||
void FioOpenFile(int slot, const char *filename)
|
void FioOpenFile(int slot, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *f = FioFOpenFile(filename);
|
FILE *f;
|
||||||
|
|
||||||
|
#if defined(LIMITED_FDS)
|
||||||
|
FioFreeHandle();
|
||||||
|
#endif /* LIMITED_FDS */
|
||||||
|
f = FioFOpenFile(filename);
|
||||||
if (f == NULL) error("Cannot open file '%s%s'", _paths.data_dir, filename);
|
if (f == NULL) error("Cannot open file '%s%s'", _paths.data_dir, filename);
|
||||||
|
|
||||||
FioCloseFile(slot); // if file was opened before, close it
|
FioCloseFile(slot); // if file was opened before, close it
|
||||||
_fio.handles[slot] = f;
|
_fio.handles[slot] = f;
|
||||||
|
#if defined(LIMITED_FDS)
|
||||||
|
_fio.filename[slot] = filename;
|
||||||
|
_fio.usage_count[slot] = 0;
|
||||||
|
_fio.open_handles++;
|
||||||
|
#endif /* LIMITED_FDS */
|
||||||
FioSeekToFile(slot << 24);
|
FioSeekToFile(slot << 24);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,13 @@
|
||||||
# define BSWAP16(x) ((x) >> 8 | (x) << 8)
|
# define BSWAP16(x) ((x) >> 8 | (x) << 8)
|
||||||
#endif /* __APPLE__ */
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
|
#if defined(PSP)
|
||||||
|
/* PSP can only have 10 file-descriptors open at any given time, but this
|
||||||
|
* switch only limits reads via the Fio system. So keep 2 fds free for things
|
||||||
|
* like saving a game. */
|
||||||
|
#define LIMITED_FDS 8
|
||||||
|
#endif /* PSP */
|
||||||
|
|
||||||
/* by default we use [] var arrays */
|
/* by default we use [] var arrays */
|
||||||
#define VARARRAY_SIZE
|
#define VARARRAY_SIZE
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue