Example #1
0
void CheckpointDaemon::run() {

  std::cout << "CheckpointDaemon started..." << std::endl;

  // bind to numa node
  bindCurrentThreadToNumaNode(0);

  struct timeval time_start, time_cur;
  unsigned long long elapsed_usec;
  gettimeofday(&time_start, NULL);
  std::chrono::milliseconds check_interval(500);

  while (_running) {

    std::this_thread::sleep_for(check_interval);

    gettimeofday(&time_cur, NULL);
    elapsed_usec = (time_cur.tv_sec * 1000000 + time_cur.tv_usec) - (time_start.tv_sec * 1000000 + time_start.tv_usec);

    if (elapsed_usec > _checkpointing_interval_in_ms * 1000) {
      doCheckpoint();
      time_start = time_cur;
    }
  }
}
/****************************************************************************
Desc:	Set the RFL keep files flag.
****************************************************************************/
RCODE XFLAPI F_Db::setRflKeepFilesFlag(
	FLMBOOL	bKeepFiles)
{
	RCODE		rc = NE_XFLM_OK;
	FLMBOOL	bDbLocked = FALSE;

	// See if the database is being forced to close

	if (RC_BAD( rc = checkState( __FILE__, __LINE__)))
	{
		goto Exit;
	}

	// Make sure we don't have a transaction going

	if (m_eTransType != XFLM_NO_TRANS)
	{
		rc = RC_SET( NE_XFLM_TRANS_ACTIVE);
		goto Exit;
	}

	// Make sure there is no active backup running

	m_pDatabase->lockMutex();
	if (m_pDatabase->m_bBackupActive)
	{
		m_pDatabase->unlockMutex();
		rc = RC_SET( NE_XFLM_BACKUP_ACTIVE);
		goto Exit;
	}
	m_pDatabase->unlockMutex();

	// Need to lock the database but not start a transaction yet.

	if (!(m_uiFlags & (FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_SHARED)))
	{
		if (RC_BAD( rc = dbLock( FLM_LOCK_EXCLUSIVE, 0, FLM_NO_TIMEOUT)))
		{
			goto Exit;
		}
		bDbLocked = TRUE;
	}

	// If we aren't changing the keep flag, jump to exit without doing
	// anything.

	if ((bKeepFiles &&
		  m_pDatabase->m_lastCommittedDbHdr.ui8RflKeepFiles) ||
		 (!bKeepFiles &&
		  !m_pDatabase->m_lastCommittedDbHdr.ui8RflKeepFiles))
	{
		goto Exit;	// Will return NE_XFLM_OK;
	}

	// Force a checkpoint and roll to the next RFL file numbers.
	// When changing from keep to no-keep or vice versa, we need to
	// go to a new RFL file so that the new RFL file gets new
	// serial numbers and a new keep or no-keep flag.

	if (RC_BAD( rc = doCheckpoint( FLM_NO_TIMEOUT)))
	{
		goto Exit;
	}

	f_memcpy( &m_pDatabase->m_uncommittedDbHdr,
				 &m_pDatabase->m_lastCommittedDbHdr,
				 sizeof( XFLM_DB_HDR));
	m_pDatabase->m_uncommittedDbHdr.ui8RflKeepFiles =
		(FLMUINT8)(bKeepFiles
					  ? (FLMUINT8)1
					  : (FLMUINT8)0);

	// Force a new RFL file - this will also write out the entire
	// log header - including the changes we made above.

	if (RC_BAD( rc = m_pDatabase->m_pRfl->finishCurrFile( this, TRUE)))
	{
		goto Exit;
	}

Exit:

	if (bDbLocked)
	{
		dbUnlock();
	}

	return( rc);
}
/****************************************************************************
Desc:	Set the RFL directory for a database.
****************************************************************************/
RCODE XFLAPI F_Db::setRflDir(
	const char *	pszNewRflDir)
{
	RCODE		rc = NE_XFLM_OK;
	FLMBOOL	bDbLocked = FALSE;

	// See if the database is being forced to close

	if (RC_BAD( rc = checkState( __FILE__, __LINE__)))
	{
		goto Exit;
	}

	// Make sure we don't have a transaction going

	if (m_eTransType != XFLM_NO_TRANS)
	{
		rc = RC_SET( NE_XFLM_TRANS_ACTIVE);
		goto Exit;
	}

	// Make sure there is no active backup running

	m_pDatabase->lockMutex();
	if (m_pDatabase->m_bBackupActive)
	{
		m_pDatabase->unlockMutex();
		rc = RC_SET( NE_XFLM_BACKUP_ACTIVE);
		goto Exit;
	}
	m_pDatabase->unlockMutex();

	// Make sure the path exists and that it is a directory
	// rather than a file.

	if (pszNewRflDir && *pszNewRflDir)
	{
		if (!gv_XFlmSysData.pFileSystem->isDir( pszNewRflDir))
		{
			rc = RC_SET( NE_FLM_IO_INVALID_FILENAME);
			goto Exit;
		}
	}

	// Need to lock the database because we can't change the RFL
	// directory until after the checkpoint has completed.  The
	// checkpoint code will unlock the transaction, but not the
	// file if we have an explicit lock.  We need to do this to
	// prevent another transaction from beginning before we have
	// changed the RFL directory.

	if (!(m_uiFlags & (FDB_HAS_FILE_LOCK | FDB_FILE_LOCK_SHARED)))
	{
		if( RC_BAD( rc = dbLock( FLM_LOCK_EXCLUSIVE, 0, FLM_NO_TIMEOUT)))
		{
			goto Exit;
		}
		bDbLocked = TRUE;
	}

	// Force a checkpoint and roll to the next RFL file numbers.  Both
	// of these steps are necessary to ensure that we won't have to do
	// any recovery using the current RFL file - because we do not
	// move the current RFL file to the new directory.  Forcing the
	// checkpoint ensures that we have no transactions that will need
	// to be recovered if we were to crash.  Rolling the RFL file number
	// ensures that no more transactions will be logged to the current
	// RFL file.

	if (RC_BAD( rc = doCheckpoint( FLM_NO_TIMEOUT)))
	{
		goto Exit;
	}

	// Force a new RFL file.

	if (RC_BAD( rc = m_pDatabase->m_pRfl->finishCurrFile( this, FALSE)))
	{
		goto Exit;
	}

	// Set the RFL directory to the new value now that we have
	// finished the checkpoint and rolled to the next RFL file.

	m_pDatabase->lockMutex();
	rc = m_pDatabase->m_pRfl->setRflDir( pszNewRflDir);
	m_pDatabase->unlockMutex();

Exit:

	if (bDbLocked)
	{
		dbUnlock();
	}

	return( rc);
}
Example #4
0
/****************************************************************************
Desc: Try to perform a checkpoint on the database.  Returns TRUE if we need
		to terminate.
****************************************************************************/
FLMBOOL F_Database::tryCheckpoint(
	IF_Thread *			pThread,
	CP_INFO *			pCPInfo)
{
	RCODE					rc = NE_XFLM_OK;
	FLMBOOL				bTerminate = FALSE;
	FLMBOOL				bForceCheckpoint;
	FLMINT				iForceReason;
	FLMUINT				uiCurrTime;
	XFLM_DB_STATS *	pDbStats;

	// See if we should terminate the thread.

	if (pThread->getShutdownFlag())
	{
		// Set terminate flag to TRUE and then see if
		// we have been set up to do one final checkpoint
		// to flush dirty buffers to disk.

		bTerminate = TRUE;
	}

	// Determine if we need to force a checkpoint.

	bForceCheckpoint = FALSE;
	iForceReason = 0;
	uiCurrTime = (FLMUINT)FLM_GET_TIMER();
	
	if (bTerminate)
	{
		bForceCheckpoint = TRUE;
		iForceReason = XFLM_CP_SHUTTING_DOWN_REASON;
	}
	else if (!m_pRfl->seeIfRflVolumeOk() || RC_BAD( m_CheckpointRc))
	{
		bForceCheckpoint = TRUE;
		iForceReason = XFLM_CP_RFL_VOLUME_PROBLEM;
	}
	else if ((FLM_ELAPSED_TIME( uiCurrTime, m_uiLastCheckpointTime) >=
				 gv_XFlmSysData.uiMaxCPInterval) ||
				(!gv_XFlmSysData.uiMaxCPInterval))
	{
		bForceCheckpoint = TRUE;
		iForceReason = XFLM_CP_TIME_INTERVAL_REASON;
	}

	if (gv_XFlmSysData.Stats.bCollectingStats)
	{

		// Statistics are being collected for the system.  Therefore,
		// if we are not currently collecting statistics in the
		// start.  If we were collecting statistics, but the
		// start time was earlier than the start time in the system
		// statistics structure, reset the statistics.

		if (!pCPInfo->Stats.bCollectingStats)
		{
			flmStatStart( &pCPInfo->Stats);
		}
		else if (pCPInfo->Stats.uiStartTime <
					gv_XFlmSysData.Stats.uiStartTime)
		{
			flmStatReset( &pCPInfo->Stats, FALSE);
		}
		(void)flmStatGetDb( &pCPInfo->Stats, this,
						0, &pDbStats, NULL, NULL);
	}
	else
	{
		pDbStats = NULL;
	}

	// Lock write object - If we are forcing a checkpoint
	// wait until we get the lock.  Otherwise, if we can't get
	// the lock without waiting, don't do anything.

	if (bForceCheckpoint ||
		 (gv_XFlmSysData.pBlockCacheMgr->m_uiMaxDirtyCache &&
		  (m_uiDirtyCacheCount + m_uiLogCacheCount) * m_uiBlockSize >
			gv_XFlmSysData.pBlockCacheMgr->m_uiMaxDirtyCache))
	{
		if (RC_BAD( rc = dbWriteLock( pCPInfo->hWaitSem, pDbStats)))
		{

			// THIS SHOULD NEVER HAPPEN BECAUSE dbWriteLock will
			// wait forever for the lock!

			RC_UNEXPECTED_ASSERT( rc);
			goto Exit;
		}
		pThread->setThreadStatusStr( "Forcing checkpoint");

		// Must wait for any RFL writes to complete.

		(void)m_pRfl->seeIfRflWritesDone( pCPInfo->hWaitSem, TRUE);
	}
	else
	{
		if (RC_BAD( dbWriteLock( pCPInfo->hWaitSem, pDbStats, 0)))
		{
			goto Exit;
		}

		pThread->setThreadStatus( FLM_THREAD_STATUS_RUNNING);

		// See if we actually need to do the checkpoint.  If the
		// current transaction ID and the last checkpoint transaction
		// ID are the same, no updates have occurred that would require
		// a checkpoint to take place.

		if (m_lastCommittedDbHdr.ui64RflLastCPTransID ==
			 m_lastCommittedDbHdr.ui64CurrTransID ||
			 !m_pRfl->seeIfRflWritesDone( pCPInfo->hWaitSem, FALSE))
		{
			dbWriteUnlock();
			goto Exit;
		}
	}

	// Do the checkpoint.

	(void)doCheckpoint( pCPInfo->hWaitSem, pDbStats, pCPInfo->pSFileHdl, FALSE,
						bForceCheckpoint, iForceReason, 0, 0);
	if (pDbStats)
	{
		(void)flmStatUpdate( &pCPInfo->Stats);
	}

	dbWriteUnlock();

	// Set the thread's status

	pThread->setThreadStatus( FLM_THREAD_STATUS_SLEEPING);

Exit:

	return( bTerminate);
}