src/fileio.cpp
changeset 5967 e8c5596608ad
parent 5584 1111b4d36e35
child 6179 d19b0137d8e4
--- a/src/fileio.cpp	Thu Feb 08 21:53:15 2007 +0000
+++ b/src/fileio.cpp	Thu Feb 08 23:46:25 2007 +0000
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 
 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);
 }