summaryrefslogtreecommitdiff
path: root/src/fileio.cpp
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2007-02-08 23:46:25 +0000
committertruelight <truelight@openttd.org>2007-02-08 23:46:25 +0000
commit7cd68b5a072ce788e3a9fad0767b2015d397ee73 (patch)
treebda0f305d17d31d1e4b13d4d3937b315b0ed0037 /src/fileio.cpp
parent424001168d89da0c58e426e808f175598bc15eb9 (diff)
downloadopenttd-7cd68b5a072ce788e3a9fad0767b2015d397ee73.tar.xz
(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.
Diffstat (limited to 'src/fileio.cpp')
-rw-r--r--src/fileio.cpp66
1 files changed, 63 insertions, 3 deletions
diff --git a/src/fileio.cpp b/src/fileio.cpp
index 2a09916ea..e7e95453f 100644
--- a/src/fileio.cpp
+++ b/src/fileio.cpp
@@ -7,19 +7,26 @@
#include "string.h"
#include "macros.h"
#include "variables.h"
+#include "debug.h"
/*************************************************/
/* FILE IO ROUTINES ******************************/
/*************************************************/
#define FIO_BUFFER_SIZE 512
+#define MAX_HANDLES 64
typedef struct {
byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer
uint32 pos; ///< current (system) position in file
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
+#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;
static Fio _fio;
@@ -38,10 +45,27 @@ void FioSeekTo(uint32 pos, int mode)
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
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);
_fio.cur_fh = f;
FioSeekTo(GB(pos, 0, 24), SEEK_SET);
@@ -92,6 +116,9 @@ static inline void FioCloseFile(int slot)
if (_fio.handles[slot] != NULL) {
fclose(_fio.handles[slot]);
_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;
}
+#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 *f;
@@ -141,11 +192,20 @@ FILE *FioFOpenFile(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);
FioCloseFile(slot); // if file was opened before, close it
_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);
}