Exemplo n.º 1
0
/****************************************************************************
Desc:	Index a set of documents or until time runs out.
****************************************************************************/
RCODE F_Db::indexSetOfRows(
	FLMUINT					uiIndexNum,
	FLMUINT64				ui64StartRowId,
	FLMUINT64				ui64EndRowId,
	IF_IxStatus *			pIxStatus,
	IF_IxClient *			pIxClient,
	SFLM_INDEX_STATUS *	pIndexStatus,
	FLMBOOL *				pbHitEnd,
	IF_Thread *				pThread)
{
	RCODE				rc = NE_SFLM_OK;
	FLMUINT64		ui64RowId;
	FLMUINT64		ui64LastRowId = 0;
	F_INDEX *		pIndex = NULL;
	F_TABLE *		pTable;
	IF_LockObject *
						pDatabaseLockObj = m_pDatabase->m_pDatabaseLockObj;
	FLMBOOL			bHitEnd = FALSE;
	FLMUINT			uiCurrTime;
	FLMUINT			uiLastStatusTime = 0;
	FLMUINT			uiStartTime;
	FLMUINT			uiMinTU;
	FLMUINT			uiStatusIntervalTU;
	FLMUINT64		ui64RowsProcessed = 0;
	FLMBOOL			bRelinquish = FALSE;
	FLMBYTE			ucKey[ FLM_MAX_NUM_BUF_SIZE];
	FLMUINT			uiKeyLen;
	void *			pvTmpPoolMark = m_tempPool.poolMark();
	F_Btree *		pbtree = NULL;
	FLMBOOL			bNeg;
	FLMUINT			uiBytesProcessed;
	F_Row *			pRow = NULL;

	uiMinTU = FLM_MILLI_TO_TIMER_UNITS( 500);
	uiStatusIntervalTU = FLM_SECS_TO_TIMER_UNITS( 10);
	uiStartTime = FLM_GET_TIMER();

	if (RC_BAD( rc = krefCntrlCheck()))
	{
		goto Exit;
	}

	pIndex = m_pDict->getIndex( uiIndexNum);
	flmAssert( pIndex);
	
	flmAssert( !(pIndex->uiFlags & IXD_SUSPENDED));

	// Get a btree

	if (RC_BAD( rc = gv_SFlmSysData.pBtPool->btpReserveBtree( &pbtree)))
	{
		goto Exit;
	}

	pTable = m_pDict->getTable( pIndex->uiTableNum);
	flmAssert( pTable);

	if (RC_BAD( rc = pbtree->btOpen( this, &pTable->lfInfo,
								FALSE, TRUE)))
	{
		goto Exit;
	}

	uiKeyLen = sizeof( ucKey);
	if (RC_BAD( rc = flmNumber64ToStorage( ui64StartRowId, &uiKeyLen,
									ucKey, FALSE, TRUE)))
	{
		goto Exit;
	}
	if( RC_BAD( rc = pbtree->btLocateEntry(
								ucKey, sizeof( ucKey), &uiKeyLen, FLM_INCL)))
	{
		if (rc == NE_SFLM_EOF_HIT || rc == NE_SFLM_NOT_FOUND)
		{
			rc = NE_SFLM_OK;
			bHitEnd = TRUE;
			goto Commit_Keys;
		}

		goto Exit;
	}
	
	for (;;)
	{
		
		// See what row we're on
	
		if (RC_BAD( rc = flmCollation2Number( uiKeyLen, ucKey,
									&ui64RowId, &bNeg, &uiBytesProcessed)))
		{
			goto Exit;
		}

		if (ui64RowId > ui64EndRowId)
		{
			break;
		}
		
		if( RC_BAD( rc = gv_SFlmSysData.pRowCacheMgr->retrieveRow( this,
									pIndex->uiTableNum, ui64RowId, &pRow)))
		{
			goto Exit;
		}

		if (RC_BAD( rc = buildKeys( pIndex, pTable, pRow, TRUE, NULL)))
		{
			goto Exit;
		}

		// See if there is an indexing callback

		if (pIxClient)
		{
			if (RC_BAD( rc = pIxClient->doIndexing( this, uiIndexNum,
								pIndex->uiTableNum, pRow)))
			{
				goto Exit;
			}
		}

		ui64LastRowId = ui64RowId;
		ui64RowsProcessed++;

		if (pIndexStatus)
		{
			pIndexStatus->ui64RowsProcessed++;
			pIndexStatus->ui64LastRowIndexed = ui64LastRowId;
		}

		// Get the current time

		uiCurrTime = FLM_GET_TIMER();

		// Break out if someone is waiting for an update transaction.

		if (pThread)
		{
			if (pThread->getShutdownFlag())
			{
				bRelinquish = TRUE;
				break;
			}

			if (pDatabaseLockObj->getWaiterCount())
			{
				// See if our minimum run time has elapsed

				if (FLM_ELAPSED_TIME( uiCurrTime, uiStartTime) >= uiMinTU)
				{
					if (ui64RowsProcessed < 50)
					{
						// If there are higher priority waiters in the lock queue,
						// we want to relinquish.

						if (pDatabaseLockObj->haveHigherPriorityWaiter(
							FLM_BACKGROUND_LOCK_PRIORITY))
						{
							bRelinquish = TRUE;
							break;
						}
					}
					else
					{
						bRelinquish = TRUE;
						break;
					}
				}
			}
			else
			{

				// Even if no one has requested a lock for a long time, we
				// still want to periodically commit our transaction so
				// we won't lose more than uiMaxCPInterval timer units worth
				// of work if we crash.  We will run until we exceed the checkpoint
				// interval and we see that someone (the checkpoint thread) is
				// waiting for the write lock.

				if (FLM_ELAPSED_TIME( uiCurrTime, uiStartTime) >
					gv_SFlmSysData.uiMaxCPInterval &&
					m_pDatabase->m_pWriteLockObj->getWaiterCount())
				{
					bRelinquish = TRUE;
					break;
				}
			}
		}

		if (FLM_ELAPSED_TIME( uiCurrTime, uiLastStatusTime) >=
					uiStatusIntervalTU)
		{
			uiLastStatusTime = uiCurrTime;
			if( pIxStatus)
			{
				if( RC_BAD( rc = pIxStatus->reportIndex( ui64LastRowId)))
				{
					goto Exit;
				}
			}

			// Send indexing completed event notification

			if( gv_SFlmSysData.EventHdrs[ SFLM_EVENT_UPDATES].pEventCBList)
			{
				flmDoEventCallback( SFLM_EVENT_UPDATES,
						SFLM_EVENT_INDEXING_PROGRESS, this, f_threadId(),
						0, uiIndexNum, ui64LastRowId,
						NE_SFLM_OK);
			}

			// Log a progress message

			flmLogIndexingProgress( uiIndexNum, ui64LastRowId);
		}

		// Need to go to the next row.

		if( RC_BAD( rc = pbtree->btNextEntry(
									ucKey, sizeof( ucKey), &uiKeyLen)))
		{
			if (rc == NE_SFLM_EOF_HIT)
			{
				rc = NE_SFLM_OK;
				bHitEnd = TRUE;
				break;
			}
			goto Exit;
		}
	}

Commit_Keys:

	if (RC_BAD( rc = keysCommit( TRUE)))
	{
		goto Exit;
	}

	// If at the end, change index state.

	if (bHitEnd)
	{
		if (RC_BAD( rc = setIxStateInfo( uiIndexNum, 0, 0)))
		{
			goto Exit;
		}

		// setIxStateInfo may have changed to a new dictionary, so pIxd is no
		// good after this point

		pIndex = NULL;
	}
	else if (ui64RowsProcessed)
	{
		if (RC_BAD( rc = setIxStateInfo( uiIndexNum, ui64LastRowId,
										IXD_OFFLINE)))
		{
			goto Exit;
		}

		// setIxStateInfo may have changed to a new dictionary, so pIndex is no
		// good after this point

		pIndex = NULL;
	}
	
	// Log the rows that were indexed, if any
	
	if (ui64LastRowId)
	{
		if (RC_BAD( rc = m_pDatabase->m_pRfl->logIndexSet( this, uiIndexNum,
									ui64StartRowId, ui64LastRowId)))
		{
			goto Exit;
		}
	}

Exit:

	// We want to make one last call if we are in the foreground or if
	// we actually did some indexing.

	if (gv_SFlmSysData.EventHdrs[ SFLM_EVENT_UPDATES].pEventCBList)
	{
		flmDoEventCallback( SFLM_EVENT_UPDATES,
				SFLM_EVENT_INDEXING_PROGRESS, this, f_threadId(),
				0, uiIndexNum,
				(FLMUINT64)(bHitEnd ? (FLMUINT64)0 : ui64LastRowId),
				NE_SFLM_OK);
	}

	flmLogIndexingProgress( uiIndexNum,
		(FLMUINT64)(bHitEnd ? (FLMUINT64)0 : ui64LastRowId));

	if (pIxStatus)
	{
		(void) pIxStatus->reportIndex( ui64LastRowId);
	}

	if (pbHitEnd)
	{
		*pbHitEnd = bHitEnd;
	}

	krefCntrlFree();
	m_tempPool.poolReset( pvTmpPoolMark);

	if (pbtree)
	{
		gv_SFlmSysData.pBtPool->btpReturnBtree( &pbtree);
	}

	if (pRow)
	{
		pRow->ReleaseRow();
	}

	return( rc);
}
Exemplo n.º 2
0
		void setUp() {
			buildDimensions();
			buildElements();
			buildKeys();
		}