1
1
/******************************************************************************
2
* $Id: fdlimit.c 3811 2007-11-12 15:22:20Z charles $
2
* $Id: fdlimit.c 4047 2007-12-03 16:53:24Z charles $
4
4
* Copyright (c) 2005-2006 Transmission authors and contributors
35
35
#include <libgen.h> /* basename, dirname */
36
36
#include <fcntl.h> /* O_LARGEFILE */
38
#include <sys/queue.h> /* libevent needs this */
39
#include <sys/types.h> /* libevent needs this */
42
39
#include <evutil.h>
44
41
#include "transmission.h"
94
TR_MAX_OPEN_FILES = 16, /* real files, not sockets */
96
TR_RESERVED_FDS = 16 /* sockets reserved for tracker connections */
91
TR_MAX_OPEN_FILES = 8, /* real files, not sockets */
93
TR_RESERVED_FDS = 16 /* sockets reserved for tracker connections */
101
98
unsigned int isCheckedOut : 1;
102
99
unsigned int isWritable : 1;
100
unsigned int closeWhenDone : 1;
103
101
char filename[MAX_PATH_LENGTH];
134
131
/* create subfolders, if any */
136
133
char * tmp = tr_strdup( filename );
137
const int val = tr_mkdirp( dirname(tmp), 0700 );
134
const int val = tr_mkdirp( dirname(tmp), 0777 );
140
137
return tr_ioErrorFromErrno( );
149
146
flags |= O_BINARY;
152
file->fd = open( filename, flags, 0600 );
149
file->fd = open( filename, flags, 0666 );
153
150
if( file->fd < 0 ) {
155
152
tr_err( "Couldn't open '%s': %s", filename, strerror(errno) );
218
214
if( fileIsCheckedOut( o ) ) {
219
215
dbgmsg( "found it! it's open, but checked out. waiting..." );
220
tr_condWait( gFd->cond, gFd->lock );
216
tr_lockUnlock( gFd->lock );
218
tr_lockLock( gFd->lock );
221
219
i = -1; /* reloop */
231
229
dbgmsg( "found it! it's ready for use!" );
237
234
dbgmsg( "it's not already open. looking for an open slot or an old file." );
240
237
uint64_t date = tr_date( ) + 1;
239
/* look for the file that's been open longest */
243
240
for( i=0; i<TR_MAX_OPEN_FILES; ++i )
245
242
o = &gFd->open[i];
259
256
if( winner >= 0 ) {
260
dbgmsg( "closing file '%s', slot #%d", gFd->open[winner].filename, winner );
261
TrCloseFile( winner );
257
if( fileIsOpen( &gFd->open[i] ) ) {
258
dbgmsg( "closing file '%s', slot #%d", gFd->open[winner].filename, winner );
259
TrCloseFile( winner );
262
dbgmsg( "everything's full! waiting for someone else to finish something" );
263
tr_lockUnlock( gFd->lock );
265
tr_lockLock( gFd->lock );
265
/* All used! Wait a bit and try again */
266
dbgmsg( "everything's full! waiting for someone else to finish something" );
267
tr_condWait( gFd->cond, gFd->lock );
269
assert( winner >= 0 );
272
270
o = &gFd->open[winner];
273
271
if( !fileIsOpen( o ) )
286
284
dbgmsg( "checking out '%s' in slot %d", filename, winner );
287
285
o->isCheckedOut = 1;
286
o->closeWhenDone = 0;
288
287
o->date = tr_date( );
289
288
tr_lockUnlock( gFd->lock );
294
tr_fdFileRelease( int file )
297
tr_lockLock( gFd->lock );
299
for( i=0; i<TR_MAX_OPEN_FILES; ++i ) {
300
struct tr_openfile * o = &gFd->open[i];
301
if( o->fd == file ) {
302
dbgmsg( "releasing file '%s' in slot #%d", o->filename, i );
303
/* fsync( o->fd ); */
293
tr_fdFileReturn( int fd )
296
tr_lockLock( gFd->lock );
298
for( i=0; i<TR_MAX_OPEN_FILES; ++i )
300
struct tr_openfile * o = &gFd->open[i];
304
dbgmsg( "releasing file '%s' in slot #%d", o->filename, i );
306
if( o->closeWhenDone )
312
tr_lockUnlock( gFd->lock );
316
tr_fdFileClose( const char * filename )
319
tr_lockLock( gFd->lock );
320
dbgmsg( "tr_fdFileClose closing '%s'", filename );
322
for( i=0; i<TR_MAX_OPEN_FILES; ++i )
324
struct tr_openfile * o = &gFd->open[i];
325
if( !fileIsOpen(o) || strcmp(filename,o->filename) )
328
if( !o->isCheckedOut ) {
329
dbgmsg( "not checked out, so closing it now... '%s'", filename );
332
dbgmsg( "flagging file '%s', slot #%d to be closed when checked in", gFd->open[i].filename, i );
333
o->closeWhenDone = 1;
309
tr_condSignal( gFd->cond );
310
337
tr_lockUnlock( gFd->lock );
434
461
gFd = tr_new0( struct tr_fd_s, 1 );
435
462
gFd->lock = tr_lockNew( );
436
gFd->cond = tr_condNew( );
438
464
/* count the max number of sockets we can use */
439
465
for( i=0; i<TR_MAX_SOCKETS; ++i )