src/fileio.cpp
changeset 6218 89dc931b8d78
parent 5835 e0ff603ae0b7
child 6285 187e3ef04cc9
child 6505 abcb0580d976
equal deleted inserted replaced
6217:4766eafe7e6d 6218:89dc931b8d78
     5 #include "fileio.h"
     5 #include "fileio.h"
     6 #include "functions.h"
     6 #include "functions.h"
     7 #include "string.h"
     7 #include "string.h"
     8 #include "macros.h"
     8 #include "macros.h"
     9 #include "variables.h"
     9 #include "variables.h"
       
    10 #include "debug.h"
    10 
    11 
    11 /*************************************************/
    12 /*************************************************/
    12 /* FILE IO ROUTINES ******************************/
    13 /* FILE IO ROUTINES ******************************/
    13 /*************************************************/
    14 /*************************************************/
    14 
    15 
    15 #define FIO_BUFFER_SIZE 512
    16 #define FIO_BUFFER_SIZE 512
       
    17 #define MAX_HANDLES 64
    16 
    18 
    17 typedef struct {
    19 typedef struct {
    18 	byte *buffer, *buffer_end;          ///< position pointer in local buffer and last valid byte of buffer
    20 	byte *buffer, *buffer_end;          ///< position pointer in local buffer and last valid byte of buffer
    19 	uint32 pos;                         ///< current (system) position in file
    21 	uint32 pos;                         ///< current (system) position in file
    20 	FILE *cur_fh;                       ///< current file handle
    22 	FILE *cur_fh;                       ///< current file handle
    21 	FILE *handles[64];                  ///< array of file handles we can have open
    23 	FILE *handles[MAX_HANDLES];         ///< array of file handles we can have open
    22 	byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file
    24 	byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file
       
    25 #if defined(LIMITED_FDS)
       
    26 	uint open_handles;                  ///< current amount of open handles
       
    27 	const char *filename[MAX_HANDLES];  ///< array of filenames we (should) have open
       
    28 	uint usage_count[MAX_HANDLES];      ///< count how many times this file has been opened
       
    29 #endif /* LIMITED_FDS */
    23 } Fio;
    30 } Fio;
    24 
    31 
    25 static Fio _fio;
    32 static Fio _fio;
    26 
    33 
    27 // Get current position in file
    34 // Get current position in file
    36 	_fio.buffer = _fio.buffer_end = _fio.buffer_start + FIO_BUFFER_SIZE;
    43 	_fio.buffer = _fio.buffer_end = _fio.buffer_start + FIO_BUFFER_SIZE;
    37 	_fio.pos = pos;
    44 	_fio.pos = pos;
    38 	fseek(_fio.cur_fh, _fio.pos, SEEK_SET);
    45 	fseek(_fio.cur_fh, _fio.pos, SEEK_SET);
    39 }
    46 }
    40 
    47 
       
    48 #if defined(LIMITED_FDS)
       
    49 static void FioRestoreFile(int slot)
       
    50 {
       
    51 	/* Do we still have the file open, or should we reopen it? */
       
    52 	if (_fio.handles[slot] == NULL) {
       
    53 		DEBUG(misc, 6, "Restoring file '%s' in slot '%d' from disk", _fio.filename[slot], slot);
       
    54 		FioOpenFile(slot, _fio.filename[slot]);
       
    55 	}
       
    56 	_fio.usage_count[slot]++;
       
    57 }
       
    58 #endif /* LIMITED_FDS */
       
    59 
    41 // Seek to a file and a position
    60 // Seek to a file and a position
    42 void FioSeekToFile(uint32 pos)
    61 void FioSeekToFile(uint32 pos)
    43 {
    62 {
    44 	FILE *f = _fio.handles[pos >> 24];
    63 	FILE *f;
       
    64 #if defined(LIMITED_FDS)
       
    65 	/* Make sure we have this file open */
       
    66 	FioRestoreFile(pos >> 24);
       
    67 #endif /* LIMITED_FDS */
       
    68 	f = _fio.handles[pos >> 24];
    45 	assert(f != NULL);
    69 	assert(f != NULL);
    46 	_fio.cur_fh = f;
    70 	_fio.cur_fh = f;
    47 	FioSeekTo(GB(pos, 0, 24), SEEK_SET);
    71 	FioSeekTo(GB(pos, 0, 24), SEEK_SET);
    48 }
    72 }
    49 
    73 
    90 static inline void FioCloseFile(int slot)
   114 static inline void FioCloseFile(int slot)
    91 {
   115 {
    92 	if (_fio.handles[slot] != NULL) {
   116 	if (_fio.handles[slot] != NULL) {
    93 		fclose(_fio.handles[slot]);
   117 		fclose(_fio.handles[slot]);
    94 		_fio.handles[slot] = NULL;
   118 		_fio.handles[slot] = NULL;
       
   119 #if defined(LIMITED_FDS)
       
   120 		_fio.open_handles--;
       
   121 #endif /* LIMITED_FDS */
    95 	}
   122 	}
    96 }
   123 }
    97 
   124 
    98 void FioCloseAll(void)
   125 void FioCloseAll(void)
    99 {
   126 {
   109 	if (f == NULL) return false;
   136 	if (f == NULL) return false;
   110 
   137 
   111 	fclose(f);
   138 	fclose(f);
   112 	return true;
   139 	return true;
   113 }
   140 }
       
   141 
       
   142 #if defined(LIMITED_FDS)
       
   143 static void FioFreeHandle()
       
   144 {
       
   145 	/* If we are about to open a file that will exceed the limit, close a file */
       
   146 	if (_fio.open_handles + 1 == LIMITED_FDS) {
       
   147 		uint i, count;
       
   148 		int slot;
       
   149 
       
   150 		count = UINT_MAX;
       
   151 		slot = -1;
       
   152 		/* Find the file that is used the least */
       
   153 		for (i = 0; i < lengthof(_fio.handles); i++) {
       
   154 			if (_fio.handles[i] != NULL && _fio.usage_count[i] < count) {
       
   155 				count = _fio.usage_count[i];
       
   156 				slot  = i;
       
   157 			}
       
   158 		}
       
   159 		assert(slot != -1);
       
   160 		DEBUG(misc, 6, "Closing filehandler '%s' in slot '%d' because of fd-limit", _fio.filename[slot], slot);
       
   161 		FioCloseFile(slot);
       
   162 	}
       
   163 }
       
   164 #endif /* LIMITED_FDS */
   114 
   165 
   115 FILE *FioFOpenFile(const char *filename)
   166 FILE *FioFOpenFile(const char *filename)
   116 {
   167 {
   117 	FILE *f;
   168 	FILE *f;
   118 	char buf[MAX_PATH];
   169 	char buf[MAX_PATH];
   139 	return f;
   190 	return f;
   140 }
   191 }
   141 
   192 
   142 void FioOpenFile(int slot, const char *filename)
   193 void FioOpenFile(int slot, const char *filename)
   143 {
   194 {
   144 	FILE *f = FioFOpenFile(filename);
   195 	FILE *f;
   145 
   196 
       
   197 #if defined(LIMITED_FDS)
       
   198 	FioFreeHandle();
       
   199 #endif /* LIMITED_FDS */
       
   200 	f = FioFOpenFile(filename);
   146 	if (f == NULL) error("Cannot open file '%s%s'", _paths.data_dir, filename);
   201 	if (f == NULL) error("Cannot open file '%s%s'", _paths.data_dir, filename);
   147 
   202 
   148 	FioCloseFile(slot); // if file was opened before, close it
   203 	FioCloseFile(slot); // if file was opened before, close it
   149 	_fio.handles[slot] = f;
   204 	_fio.handles[slot] = f;
       
   205 #if defined(LIMITED_FDS)
       
   206 	_fio.filename[slot] = filename;
       
   207 	_fio.usage_count[slot] = 0;
       
   208 	_fio.open_handles++;
       
   209 #endif /* LIMITED_FDS */
   150 	FioSeekToFile(slot << 24);
   210 	FioSeekToFile(slot << 24);
   151 }
   211 }