Пример #1
0
// . get the fd of this file
// . if it was closed by us we reopen it
// . may re-open a virtual fd whose real fd was closed
// . if we hit our max # of real fds allowed we'll have to close 
//   the least used of those so we can open this one
// . return -2 if never been opened
// . return -1 on other errors
// . otherwise, return the file descriptor
int File::getfd () {
	// if m_vfd is -1 it's never been opened
	if ( m_vfd < 0 ) {
		g_errno = EBADENGINEER;
		log(LOG_LOGIC,"disk: getfd: Must call open() first.");
		char *xx=NULL; *xx=0; 
		return -2;
	}
	// . sanity check
	// . no caller should call open/getfd after unlink was queued for thred
	//if ( m_gone ) { char *xx = NULL; *xx = 0; }
	// get the real fd from the virtual fd
	int fd = s_fds [ m_vfd ];
	// return true if it's already opened
	if ( fd >=  0 ) { 
		// debug msg
		log(LOG_DEBUG,"disk: Opened vfd #%li of %li.",
		    (long)m_vfd,(long)s_fds[m_vfd]);
		// but update the timestamp to reduce chance it closes on us
		//s_timestamps [ m_vfd ] = getTime();
		s_timestamps [ m_vfd ] = gettimeofdayInMillisecondsLocal();
		return fd;
	}
	// if fd is -2 it's marked as available
	if ( fd != -1 ) {
		g_errno = EBADENGINEER;
		log (LOG_LOGIC, "disk: getfd: fd is available?!?!" );
		return -2;
	}
	// . a real fd of -1 means it's been closed and we gotta reopen it
	// . we have to close someone if we don't have enough room
	while ( s_numOpenFiles >= s_maxNumOpenFiles ) 
		if ( ! closeLeastUsed() ) return -1;
	// what was the filename/mode of this timed-out fd?
	//char *filename    = s_filenames   [ m_vfd ];
	// time the calls to open just in case they are hurting us
	long long t1 = -1LL;
	// . re-open the sleeping file descriptor
	// . if a rename thread was queued or spawned, try old guy first
	//if ( m_oldFilename[0] ) {
	//	t1 = gettimeofdayInMilliseconds();
	//	fd = ::open ( m_oldFilename , m_flags , m_permissions );
	//}
	// then try to open the new name
	if ( fd == -1 ) {
		t1 = gettimeofdayInMilliseconds();
 retry7:
		fd = ::open ( m_filename , m_flags , m_permissions );
		// valgrind
		if ( fd == -1 && errno == EINTR ) goto retry7;
		// 0 means stdout, right? why am i seeing it get assigned???
		if ( fd == 0 ) 
			log("disk: Got fd of 0 when opening %s.",m_filename);
		if ( fd == 0 )
			fd = ::open ( m_filename , m_flags , m_permissions );
		if ( fd == 0 ) 
			log("disk: Got fd of 0 when opening2 %s.",m_filename);
		// . now inc that count in case there was someone reading on
		//   that fd right before it was closed and we got it
		// . ::close() call can now happen in a thread, so we
		//   need to inc this guy here now, too
		// . so when that read returns it will know to re-do
		// . this should really be named s_openCounts!!
		if ( fd >= 0 ) s_closeCounts [ fd ]++;
		// . we now record this
		// . that way if our fd gets closed in closeLeastUsed() or
		//   in close1_r() due to a rename/unlink then we know it!
		// . this fixes a race condition of closeCounts in Threads.cpp
		//   where we did not know that the fd had been stolen from
		//   us and assigned to another file because our close1_r()
		//   had called ::close() on our fd and our closeCount algo
		//   failed us. see the top of this file for more description
		//   into this bug fix.
		m_closeCount = s_closeCounts[fd];
	}
	if ( t1 >= 0 ) {
		long long dt = gettimeofdayInMilliseconds() - t1 ;
		if ( dt > 1 ) log(LOG_INFO,
				  "disk: call to open(%s) blocked for "
				  "%lli ms.",m_filename,dt);
	}
	// copy errno to g_errno
	if ( fd == -1 ) {
		g_errno = errno;
		log("disk: error open(%s) : %s",m_filename,strerror(g_errno));
		return -1;
	}
	// we're another open file
	s_numOpenFiles++;
	// set this file descriptor, the other stuff remains the same
	s_fds [ m_vfd ] = fd;
	// 0 means stdout, right? why am i seeing it get assigned???
	if ( fd == 0 ) 
		log("disk: Found fd of 0 when opening %s.",m_filename);
	// reset
	s_writing   [ m_vfd ] = 0;
	s_unlinking [ m_vfd ] = 0;
	// update the time stamp
	s_timestamps [ m_vfd ] = gettimeofdayInMillisecondsLocal();
	return fd;
}
Пример #2
0
// . get the fd of this file
// . if it was closed by us we reopen it
// . may re-open a virtual fd whose real fd was closed
// . if we hit our max # of real fds allowed we'll have to close 
//   the least used of those so we can open this one
// . return -2 if never been opened
// . return -1 on other errors
// . otherwise, return the file descriptor
int File::getfd () {
	// if m_vfd is -1 it's never been opened
	if ( ! m_calledOpen ) { // m_vfd < 0 ) {
		g_errno = EBADENGINEER;
		log(LOG_LOGIC,"disk: getfd: Must call open() first.");
		char *xx=NULL; *xx=0; 
		return -2;
	}

	// if someone closed our fd, why didn't our m_fd get set to -1 ??!?!?!!
	if ( m_fd >= 0 && m_closeCount != s_closeCounts[m_fd] ) {
		log(LOG_DEBUG,"disk: invalidating existing fd %i "
		    "for %s this=0x%"PTRFMT" ccSaved=%i ccNow=%i", 
		    (int)m_fd,getFilename(),(PTRTYPE)this,
		    (int)m_closeCount,
		    (int)s_closeCounts[m_fd]);
		m_fd = -1;
	}

	// . sanity check
	// . no caller should call open/getfd after unlink was queued for thred
	//if ( m_gone ) { char *xx = NULL; *xx = 0; }
	// get the real fd from the virtual fd
	//int fd = s_fds [ m_vfd ];
	// return true if it's already opened
	if ( m_fd >=  0 ) { 
		// debug msg
		if ( g_conf.m_logDebugDisk )
			log(LOG_DEBUG,"disk: returning existing fd %i for %s "
			    "this=0x%"PTRFMT" ccSaved=%i ccNow=%i", 
			    (int)m_fd,getFilename(),(PTRTYPE)this,
			    (int)m_closeCount,
			    (int)s_closeCounts[m_fd]);
		if ( m_fd >= MAX_NUM_FDS ) { char *xx=NULL;*xx=0; }
		// but update the timestamp to reduce chance it closes on us
		//s_timestamps [ m_vfd ] = getTime();
		s_timestamps [ m_fd ] = gettimeofdayInMillisecondsLocal();
		return m_fd;
	}
	// if fd is -2 it's marked as available
	// if ( fd != -1 ) {
	// 	g_errno = EBADENGINEER;
	// 	log (LOG_LOGIC, "disk: getfd: fd is available?!?!" );
	// 	return -2;
	// }
	// . a real fd of -1 means it's been closed and we gotta reopen it
	// . we have to close someone if we don't have enough room
	while ( s_numOpenFiles >= s_maxNumOpenFiles )  {
		if ( g_conf.m_logDebugDisk ) sanityCheck();
		if ( ! closeLeastUsed() ) return -1;
		if ( g_conf.m_logDebugDisk ) sanityCheck();
	}
	// what was the filename/mode of this timed-out fd?
	//char *filename    = s_filenames   [ m_vfd ];
	// time the calls to open just in case they are hurting us
	int64_t t1 = -1LL;
	// . re-open the sleeping file descriptor
	// . if a rename thread was queued or spawned, try old guy first
	//if ( m_oldFilename[0] ) {
	//	t1 = gettimeofdayInMilliseconds();
	//	fd = ::open ( m_oldFilename , m_flags , m_permissions );
	//}
	int fd = -1;
	// then try to open the new name
	if ( fd == -1 ) {
		t1 = gettimeofdayInMilliseconds();
 retry7:
		fd = ::open ( getFilename() , m_flags,getFileCreationFlags());
		// valgrind
		if ( fd == -1 && errno == EINTR ) goto retry7;
		// 0 means stdout, right? why am i seeing it get assigned???
		if ( fd == 0 ) 
			log("disk: Got fd of 0 when opening %s.",
			    getFilename());
		if ( fd == 0 )
		       fd=::open(getFilename(),m_flags,getFileCreationFlags());
		if ( fd == 0 ) 
			log("disk: Got fd of 0 when opening2 %s.",
			    getFilename());
		if ( fd >= MAX_NUM_FDS )
			log("disk: got fd of %i out of bounds 1 of %i",
			    (int)fd,(int)MAX_NUM_FDS);

		// if we got someone else's fd that called close1_r() in a
		// thread but did not have time to call close2() to fix
		// up these member vars, then do it here. close2() will 
		// see that s_filePtrs[fd] does not equal the file ptr any more
		// and it will not update s_numOpenFiles in that case.
		if ( fd >= 0 && s_open [ fd ] ) {
			File *f = s_filePtrs [ fd ];
			if ( g_conf.m_logDebugDisk )
				log("disk: swiping fd %i from %s before "
				    "his close thread returned "
				    "this=0x%"PTRFMT,
				    fd,
				    f->getFilename(),
				    (PTRTYPE)f);
			// he only incs/decs his counters if he owns it so in
			// close2() so dec this global counter here
			s_numOpenFiles--;
			s_open[fd] = 0;
			s_filePtrs[fd] = NULL;
			if ( g_conf.m_logDebugDisk ) sanityCheck();
		}

		// sanity. how can we get an fd already opened?
		// because it was closed in a thread in close1_r()
		if ( fd >= 0 && s_open[fd] ) { char *xx=NULL;*xx=0; }
		// . now inc that count in case there was someone reading on
		//   that fd right before it was closed and we got it
		// . ::close() call can now happen in a thread, so we
		//   need to inc this guy here now, too
		// . so when that read returns it will know to re-do
		// . this should really be named s_openCounts!!
		if ( fd >= 0 ) s_closeCounts [ fd ]++;
		// . we now record this
		// . that way if our fd gets closed in closeLeastUsed() or
		//   in close1_r() due to a rename/unlink then we know it!
		// . this fixes a race condition of closeCounts in Threads.cpp
		//   where we did not know that the fd had been stolen from
		//   us and assigned to another file because our close1_r()
		//   had called ::close() on our fd and our closeCount algo
		//   failed us. see the top of this file for more description
		//   into this bug fix.
		m_closeCount = s_closeCounts[fd];
	}
	if ( t1 >= 0 ) {
		int64_t dt = gettimeofdayInMilliseconds() - t1 ;
		if ( dt > 1 ) log(LOG_INFO,
				  "disk: call to open(%s) blocked for "
				  "%"INT64" ms.",getFilename(),dt);
	}
	// copy errno to g_errno
	if ( fd <= -1 ) {
		g_errno = errno;
		log("disk: error open(%s) : %s fd %i",
		    getFilename(),strerror(g_errno),(int)fd);
		return -1;
	}

	if ( g_conf.m_logDebugDisk ) sanityCheck();

	// we're another open file
	s_numOpenFiles++;

	// debug log
	if ( g_conf.m_logDebugDisk )
		log("disk: opened1 fd %i for %s #openfiles=%i this=0x%"PTRFMT,
		    (int)fd,getFilename(),(int)s_numOpenFiles,(PTRTYPE)this);

	// set this file descriptor, the other stuff remains the same
	//s_fds [ m_vfd ] = fd;
	m_fd = fd;
	// 0 means stdout, right? why am i seeing it get assigned???
	if ( fd == 0 ) 
		log("disk: Found fd of 0 when opening %s.",getFilename());
	// reset
	s_writing   [ fd ] = 0;
	s_unlinking [ fd ] = 0;
	// update the time stamp
	s_timestamps [ fd ] = gettimeofdayInMillisecondsLocal();
	s_open       [ fd ] = true;
	s_filePtrs   [ fd ] = this;

	if ( g_conf.m_logDebugDisk ) sanityCheck();
	// add file to linked list of active files
	//addFileToLinkedList ( this );
	return fd;
}