コード例 #1
0
/****************************************************************************
Desc:	Reinsert all entries given a new root block.
		Caller will release 'this'.  Used ONLY for building the first
		ROOT and two leaves of the tree.
****************************************************************************/
RCODE F_BtreeLeaf::split(
    F_BtreeRoot *	pNewRoot)		// New Non-leaf root
{
    RCODE				rc = NE_FLM_OK;
    FLMBYTE *		pucEntry;
    FLMUINT			uiPos;
    FLMUINT			uiEntryCount = entryCount();
    FLMUINT			uiMid = (uiEntryCount + 1) >> 1;

    if (RC_BAD( rc = pNewRoot->setupTree( ENTRY_POS(uiMid),
                                          ACCESS_BTREE_LEAF, NULL, NULL)))
    {
        goto Exit;
    }

    for (uiPos = 0; uiPos < uiEntryCount; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        if ((rc = pNewRoot->search( pucEntry)) != NE_FLM_NOT_FOUND)
        {
            rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
            goto Exit;
        }

        if (RC_BAD( rc = pNewRoot->insert( pucEntry)))
        {
            goto Exit;
        }
    }

Exit:

    return( rc);
}
コード例 #2
0
ファイル: ftkmfh.cpp プロジェクト: ajumi2/libflaim
/****************************************************************************
Desc: Flushes cached data to the data file(s)
****************************************************************************/
RCODE F_MultiFileHdl::flush( void)
{
	FLMUINT		uiLoop;
	RCODE			rc = NE_FLM_OK;

	if( !m_bOpen)
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
		goto Exit;
	}

	for( uiLoop = 0; uiLoop < F_MULTI_FHDL_LIST_SIZE; uiLoop++)
	{
		if( m_pFileHdlList[ uiLoop].bDirty)
		{
			if( RC_BAD( rc = m_pFileHdlList[ uiLoop].pFileHdl->flush()))
			{
				goto Exit;
			}
			m_pFileHdlList[ uiLoop].bDirty = FALSE;
		}
	}

Exit:

	return( rc);
}
コード例 #3
0
ファイル: ftkmfh.cpp プロジェクト: ajumi2/libflaim
/****************************************************************************
Desc: Creates a new 64-bit "file"
****************************************************************************/
RCODE F_MultiFileHdl::createFile(
	const char *	pszPath)
{
	RCODE					rc = NE_FLM_OK;
	FLMBOOL				bCreatedDir = FALSE;
	IF_FileSystem *	pFileSystem = f_getFileSysPtr();

	if( m_bOpen)
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
		goto Exit;
	}

	if( RC_BAD( rc = pFileSystem->createDir( pszPath)))
	{
		goto Exit;
	}

	f_strcpy( m_szPath, pszPath);
	bCreatedDir = TRUE;

	// Create the lock file

	if( RC_BAD( rc = createLockFile( m_szPath)))
	{
		goto Exit;
	}

	// Initialize the EOF to 0 and set the state to open

	m_ui64EOF = 0;
	m_bOpen = TRUE;

Exit:

	// Release the lock file

	if( RC_BAD( rc))
	{
		(void)releaseLockFile( m_szPath, TRUE);
		if( bCreatedDir)
		{
			(void)pFileSystem->removeDir( m_szPath);
		}
	}

	return( rc);
}
コード例 #4
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FLMAPI f_rwlockPromote(
	F_RWLOCK				hReadWriteLock,
	F_SEM					hSem)
{
	RCODE					rc = NE_FLM_OK;
	F_RWLOCK_IMP *		pReadWriteLock = (F_RWLOCK_IMP *)hReadWriteLock;
	FLMBOOL				bMutexLocked = FALSE;
	
	f_mutexLock( pReadWriteLock->hMutex);
	bMutexLocked = TRUE;
	
	if( pReadWriteLock->iRefCnt <= 0)
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP);
		goto Exit;
	}
	
	pReadWriteLock->iRefCnt--;
		
	if( pReadWriteLock->iRefCnt != 0)
	{
		rc = f_notifyWait( pReadWriteLock->hMutex, hSem, (void *)TRUE, 
			&pReadWriteLock->pNotifyList); 
	}
	
	if( RC_OK( rc))
	{
		f_assert( !pReadWriteLock->iRefCnt);
		pReadWriteLock->iRefCnt = -1;
		pReadWriteLock->uiWriteThread = f_threadId();
	}

Exit:

	f_assert( RC_BAD( rc) || pReadWriteLock->iRefCnt);
	
	if( bMutexLocked)
	{
		f_mutexUnlock( pReadWriteLock->hMutex);
	}
	
	return( rc);
}
コード例 #5
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FLMAPI f_rwlockRelease(
	F_RWLOCK				hReadWriteLock)
{
	RCODE					rc = NE_FLM_OK;
	F_RWLOCK_IMP *		pReadWriteLock = (F_RWLOCK_IMP *)hReadWriteLock;
	FLMBOOL				bMutexLocked = FALSE;
	
	f_mutexLock( pReadWriteLock->hMutex);
	bMutexLocked = TRUE;
	
	if( pReadWriteLock->iRefCnt > 0)
	{
		pReadWriteLock->iRefCnt--;
	}
	else if( pReadWriteLock->iRefCnt == -1)
	{
		f_assert( pReadWriteLock->uiWriteThread == f_threadId());
		pReadWriteLock->iRefCnt = 0;
	}
	else
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP);
		goto Exit;
	}
	
	if( !pReadWriteLock->iRefCnt && pReadWriteLock->pNotifyList)
	{
		f_rwlockNotify( pReadWriteLock);
	}
	
Exit:
	
	f_assert( RC_BAD( rc) || pReadWriteLock->iRefCnt >= 0);
	
	if( bMutexLocked)
	{
		f_mutexUnlock( pReadWriteLock->hMutex);
	}

	return( rc);
}
コード例 #6
0
/****************************************************************************
Desc:	Build a text key.
****************************************************************************/
FSTATIC RCODE flmAddTextKeyPiece(
	SQL_PRED *		pPred,
	F_INDEX *		pIndex,
	FLMUINT			uiKeyComponent,
	ICD *				pIcd,
	F_DataVector *	pFromSearchKey,
	FLMBYTE *		pucFromKey,
	FLMUINT *		puiFromKeyLen,
	F_DataVector *	pUntilSearchKey,
	FLMBYTE *		pucUntilKey,
	FLMUINT *		puiUntilKeyLen,
	FLMBOOL *		pbCanCompareOnKey,
	FLMBOOL *		pbFromIncl,
	FLMBOOL *		pbUntilIncl)
{
	RCODE       			rc = NE_SFLM_OK;
	FLMBYTE *				pucFromKeyLenPos;
	FLMBYTE *				pucUntilKeyLenPos;
	FLMUINT					uiLanguage = pIndex->uiLanguage;
	FLMUINT					uiFromCollationLen = 0;
	FLMUINT					uiUntilCollationLen = 0;
	FLMUINT					uiCharCount;
	FLMUINT					uiFromCaseLen;
	FLMUINT					uiUntilCaseLen;
	FLMBOOL					bFromOriginalCharsLost = FALSE;
	FLMBOOL					bUntilOriginalCharsLost = FALSE;
	FLMBOOL					bIsDBCS = (uiLanguage >= FLM_FIRST_DBCS_LANG &&
								  uiLanguage <= FLM_LAST_DBCS_LANG)
								  ? TRUE
								  : FALSE;

	FLMBOOL					bCaseInsensitive = (FLMBOOL)((pPred->uiCompareRules &
															FLM_COMP_CASE_INSENSITIVE)
															? TRUE
															: FALSE);
	FLMBOOL					bDoFirstSubstring = (FLMBOOL)((pIcd->uiFlags & ICD_SUBSTRING)
															 ? TRUE
															 : FALSE);
	FLMBOOL					bDoMatchBegin = FALSE;
	FLMBOOL					bTrailingWildcard = FALSE;
	const FLMBYTE *		pucFromUTF8Buf = NULL;
	FLMUINT					uiFromBufLen = 0;
	const FLMBYTE *		pucUntilUTF8Buf = NULL;
	FLMUINT					uiUntilBufLen = 0;
	FLMUINT					uiWildcardPos;
	FLMBOOL					bFromDataTruncated;
	FLMBOOL					bUntilDataTruncated;
	FLMUINT					uiFromFlags = 0;
	FLMUINT					uiUntilFlags = 0;
	FLMUINT					uiCompareRules;
	FLMBOOL					bAscending = (pIcd->uiFlags & ICD_DESCENDING) ? FALSE: TRUE;
	F_BufferIStream		bufferIStream;
	FLMUINT					uiFromKeyLen = *puiFromKeyLen;
	FLMUINT					uiUntilKeyLen = *puiUntilKeyLen;
	FLMUINT					uiFromComponentLen;
	FLMUINT					uiUntilComponentLen;
	FLMUINT					uiFromSpaceLeft;
	FLMUINT					uiUntilSpaceLeft;
	
	// Leave room for the component length

	pucFromKeyLenPos = pucFromKey + uiFromKeyLen;
	pucUntilKeyLenPos = pucUntilKey + uiUntilKeyLen;
	pucFromKey = pucFromKeyLenPos + 2;
	pucUntilKey = pucUntilKeyLenPos + 2;
	uiFromSpaceLeft = SFLM_MAX_KEY_SIZE - uiFromKeyLen - 2;
	uiUntilSpaceLeft = SFLM_MAX_KEY_SIZE - uiUntilKeyLen - 2;

	switch (pPred->eOperator)
	{

		// The difference between MATCH and EQ_OP is that EQ does
		// not support wildcards embedded in the search key.

		case SQL_MATCH_OP:
			flmAssert( pPred->pFromValue->eValType == SQL_UTF8_VAL);
			pucFromUTF8Buf = pPred->pFromValue->val.str.pszStr;
			uiFromBufLen = pPred->pFromValue->val.str.uiByteLen;
			uiCompareRules = pIcd->uiCompareRules;

			if (RC_BAD( rc = flmUTF8FindWildcard( pucFromUTF8Buf, &uiWildcardPos,
										&uiCompareRules)))
			{
				goto Exit;
			}
			
			// If there is no wildcard, uiWildcardPos will be FLM_MAX_UINT
			
			if (uiWildcardPos != FLM_MAX_UINT)
			{

				// If wildcard is in position 0, it is NOT
				// a match begin.

				if (uiWildcardPos)
				{
					bDoMatchBegin = TRUE;
					uiFromBufLen = uiWildcardPos;
				}
			}
			if (!(pIcd->uiFlags & ICD_SUBSTRING))
			{

				// Index is NOT a substring index

				if (!bDoMatchBegin)
				{

					// Wildcard was at the beginning, will have
					// to search the index from first to last

					pucFromUTF8Buf = NULL;
				}
				else
				{
					bTrailingWildcard = TRUE;
				}
			}
			else
			{
				FLMBOOL	bNotUsingFirstOfString;

				// If this is a substring index look for a 
				// better 'contains' string to search for. 
				// We don't like "A*BCDEFG" searches.
				
				bTrailingWildcard = bDoMatchBegin;

				uiCompareRules = pIcd->uiCompareRules;
				if (RC_BAD( rc = flmSelectBestSubstr( &pucFromUTF8Buf,
					&uiFromBufLen, 
					&uiCompareRules, &bTrailingWildcard,
					&bNotUsingFirstOfString)))
				{
					goto Exit;
				}

				if (bNotUsingFirstOfString)
				{
					bDoMatchBegin = bTrailingWildcard;
					*pbCanCompareOnKey = FALSE;
					bDoFirstSubstring = FALSE;
				}
				else if (bTrailingWildcard)
				{
					bDoMatchBegin = TRUE;
				}

				if (RC_BAD( rc = flmCountCharacters( pucFromUTF8Buf,
									uiFromBufLen, 2,
									&uiCompareRules, &uiCharCount)))
				{
					goto Exit;
				}
				
				// Special case: Single character contains/MEnd in a substr ix.

				if (!bIsDBCS && uiCharCount < 2)
				{
					pucFromUTF8Buf = NULL;
				}
			}
			
			pucUntilUTF8Buf = pucFromUTF8Buf;
			uiUntilBufLen = uiFromBufLen;
			break;

		case SQL_RANGE_OP:
			if (bAscending)
			{
				if (pPred->pFromValue)
				{
					flmAssert( pPred->pFromValue->eValType == SQL_UTF8_VAL);
					pucFromUTF8Buf = pPred->pFromValue->val.str.pszStr;
					uiFromBufLen = pPred->pFromValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above
					
					// pucFromUTF8Buf = NULL;
					// uiFromBufLen = 0;
				}
				if (pPred->pUntilValue)
				{
					flmAssert( pPred->pUntilValue->eValType == SQL_UTF8_VAL);
					pucUntilUTF8Buf = pPred->pUntilValue->val.str.pszStr;
					uiUntilBufLen = pPred->pUntilValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above.
					
					// pucUntilUTF8Buf = NULL;
					// uiUntilBufLen = 0;
				}
				if (!pPred->bInclFrom)
				{
					uiFromFlags |= EXCLUSIVE_GT_FLAG;
				}
				if (!pPred->bInclUntil)
				{
					uiUntilFlags |= EXCLUSIVE_LT_FLAG;
				}
			}
			else
			{
				if (pPred->pUntilValue)
				{
					flmAssert( pPred->pUntilValue->eValType == SQL_UTF8_VAL);
					pucFromUTF8Buf = pPred->pUntilValue->val.str.pszStr;
					uiFromBufLen = pPred->pUntilValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above
					
					// pucFromUTF8Buf = NULL;
					// uiFromBufLen = 0;
				}
					
				if (pPred->pFromValue)
				{
					flmAssert( pPred->pFromValue->eValType == SQL_UTF8_VAL);
					pucUntilUTF8Buf = pPred->pFromValue->val.str.pszStr;
					uiUntilBufLen = pPred->pFromValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above.
					
					// pucUntilUTF8Buf = NULL;
					// uiUntilBufLen = 0;
				}
				if (!pPred->bInclUntil)
				{
					uiFromFlags |= EXCLUSIVE_GT_FLAG;
				}
				if (!pPred->bInclFrom)
				{
					uiUntilFlags |= EXCLUSIVE_LT_FLAG;
				}
			}
			break;

		case SQL_NE_OP:

			// Set up to do full index scan.
			
			// Buffers should already be NULL.

			// pucFromUTF8Buf = NULL;
			// pucUntilUTF8Buf = NULL;
			break;

		case SQL_APPROX_EQ_OP:

			// Set up to do full index scan.
			
			// Buffers should already be NULL

			// pucFromUTF8Buf = NULL;
			// pucUntilUTF8Buf = NULL;

			// Cannot compare on the key if index is upper case,
			// even if the bCaseInsensitive flag is set.

			if (pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE)
			{
				*pbCanCompareOnKey = FALSE;
			}
			break;

		default:

			// Every predicate should have been converted to one of the above
			// cases, or should be handled by another routine.

			rc = RC_SET_AND_ASSERT( NE_SFLM_QUERY_SYNTAX);
			goto Exit;
	}

	// If index is case insensitive, but search is case sensitive
	// we must NOT do a key match - we would fail things we should
	// not be failing.
	
	if ((pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) && !bCaseInsensitive)
	{
		*pbCanCompareOnKey = FALSE;
	}
	
	if (!pucFromUTF8Buf)
	{
		uiFromComponentLen = KEY_LOW_VALUE;
	}
	else
	{
		if (RC_BAD( rc = bufferIStream.openStream( 
			(const char *)pucFromUTF8Buf, uiFromBufLen)))
		{
			goto Exit;
		}

		// Add ICD_ESC_CHAR to the icd flags because
		// the search string must have BACKSLASHES and '*' escaped.

		uiFromComponentLen = uiFromSpaceLeft;
		bFromDataTruncated = FALSE;
		if (RC_BAD( rc = KYCollateValue( pucFromKey, &uiFromComponentLen,
								&bufferIStream, SFLM_STRING_TYPE,
							pIcd->uiFlags | ICD_ESC_CHAR, pIcd->uiCompareRules,
							pIcd->uiLimit,
							&uiFromCollationLen, &uiFromCaseLen,
							uiLanguage, bDoFirstSubstring,
							FALSE, &bFromDataTruncated,
							&bFromOriginalCharsLost)))
		{
			goto Exit;
		}
		
		bufferIStream.closeStream();
		
		if (bFromDataTruncated)
		{
			*pbCanCompareOnKey = FALSE;
			
			// Save the original data into pFromSearchKey so the comparison
			// routines can do a comparison on the full value if
			// necessary.

			if (RC_BAD( rc = pFromSearchKey->setUTF8( uiKeyComponent,
										pucFromUTF8Buf, uiFromBufLen)))
			{
				goto Exit;
			}
			uiFromFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
		}
		else if (bFromOriginalCharsLost)
		{
			*pbCanCompareOnKey = FALSE;
		}
		
		if (pucFromUTF8Buf != pucUntilUTF8Buf)
		{
			
			// Handle scenario of a case-sensitive index, but search is
			// case-insensitive.

			if (uiFromComponentLen &&
				 (bIsDBCS ||
				   (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
					 bCaseInsensitive)))
			{
				setFromCaseByte( pucFromKey, &uiFromComponentLen, uiFromCaseLen,
										bIsDBCS, bAscending,
										(uiFromFlags & EXCLUSIVE_GT_FLAG)
										? TRUE
										: FALSE);
			}
		}
	}

	// Do the until key now

	if (!pucUntilUTF8Buf)
	{
		uiUntilComponentLen = KEY_HIGH_VALUE;
	}
	else if (pucFromUTF8Buf == pucUntilUTF8Buf)
	{
		
		// Handle case where from and until buffers are the same.
		// This should only be possible in the equality case or match begin
		// case, in which cases neither the EXCLUSIVE_LT_FLAG or the
		// EXCLUSIVE_GT_FLAG should be set.
		
		flmAssert( uiFromBufLen == uiUntilBufLen);
		flmAssert( !(uiFromFlags & (EXCLUSIVE_GT_FLAG | EXCLUSIVE_LT_FLAG)));
		flmAssert( !(uiUntilFlags & (EXCLUSIVE_GT_FLAG | EXCLUSIVE_LT_FLAG)));
		
		// Need to collate the until key from the original data if
		// the from key was truncated or there is not enough room in
		// the until key.  Otherwise, we can simply copy
		// the from key into the until key - a little optimization.
		
		if (uiUntilSpaceLeft >= uiFromComponentLen && !bFromDataTruncated)
		{
			if ((uiUntilComponentLen = uiFromComponentLen) != 0)
			{
				f_memcpy( pucUntilKey, pucFromKey, uiFromComponentLen);
			}
			uiUntilCaseLen = uiFromCaseLen;
			uiUntilCollationLen = uiFromCollationLen;
			bUntilOriginalCharsLost = bFromOriginalCharsLost;
			bUntilDataTruncated = FALSE;
		}
		else
		{
			if (RC_BAD( rc = bufferIStream.openStream( 
				(const char *)pucUntilUTF8Buf, uiUntilBufLen)))
			{
				goto Exit;
			}
	
			// Add ICD_ESC_CHAR to the icd flags because
			// the search string must have BACKSLASHES and '*' escaped.
	
			uiUntilComponentLen = uiUntilSpaceLeft;
			bUntilDataTruncated = FALSE;
			if (RC_BAD( rc = KYCollateValue( pucUntilKey, &uiUntilComponentLen,
								&bufferIStream, SFLM_STRING_TYPE,
								pIcd->uiFlags | ICD_ESC_CHAR, pIcd->uiCompareRules,
								pIcd->uiLimit,
								&uiUntilCollationLen, &uiUntilCaseLen,
								uiLanguage, bDoFirstSubstring, 
								FALSE, &bUntilDataTruncated,
								&bUntilOriginalCharsLost)))
			{
				goto Exit;
			}
			
			bufferIStream.closeStream();
			
			if (bUntilDataTruncated)
			{
				
				// Save the original data into pUntilSearchKey so the comparison
				// routines can do a comparison on the full value if
				// necessary.
	
				if (RC_BAD( rc = pUntilSearchKey->setUTF8( uiKeyComponent,
											pucUntilUTF8Buf, uiUntilBufLen)))
				{
					goto Exit;
				}
				*pbCanCompareOnKey = FALSE;
				uiUntilFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
			}
			else if (bUntilOriginalCharsLost)
			{
				*pbCanCompareOnKey = FALSE;
			}
		}
		
		if (bDoMatchBegin)
		{
			if (bAscending)
			{
				
				// Handle scenario of a case-sensitive index, but search is
				// case-insensitive.
		
				if (uiFromComponentLen &&
					 (bIsDBCS ||
					  (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
						bCaseInsensitive)))
				{
					setFromCaseByte( pucFromKey, &uiFromComponentLen, uiFromCaseLen,
											bIsDBCS, bAscending, FALSE);
				}
	
				// Fill everything after the collation values in the until
				// key with high values (0xFF)
	
				f_memset( &pucUntilKey[ uiUntilCollationLen], 0xFF,
								uiUntilSpaceLeft - uiUntilCollationLen);
				uiUntilComponentLen = uiUntilSpaceLeft;
			}
			else
			{
				
				if (uiUntilComponentLen &&
					 (bIsDBCS ||
					  (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
						bCaseInsensitive)))
				{
					// NOTE: Always inclusive because this is a matchbegin.
				
					setUntilCaseByte( pucUntilKey, &uiUntilComponentLen, uiUntilCaseLen,
										bIsDBCS, bAscending, FALSE);
				}
									
				// Fill rest of from key with high values after collation values.
				
				f_memset( &pucFromKey[ uiFromCollationLen], 0xFF,
							uiFromSpaceLeft - uiFromCollationLen);
				uiFromComponentLen = uiFromSpaceLeft;
			}
		}
		else
		{
			if (bDoFirstSubstring)
			{
				FLMUINT	uiBytesToRemove = (bIsDBCS) ? 2 : 1;
				
				if (bAscending)
				{
					
					// Get rid of the first substring byte in the until
					// key.
					
					f_memmove( &pucUntilKey [uiUntilCollationLen],
								  &pucUntilKey [uiUntilCollationLen + uiBytesToRemove],
								  uiUntilComponentLen - uiUntilCollationLen - uiBytesToRemove);
					uiUntilComponentLen -= uiBytesToRemove;
				}
				else
				{
					
					// Descending order - put the string without the
					// first-substring-marker into the from key instead of
					// the until key.
					
					f_memmove( &pucFromKey [uiFromCollationLen],
								  &pucFromKey [uiFromCollationLen + uiBytesToRemove],
								  uiFromComponentLen - uiFromCollationLen - uiBytesToRemove);
					uiFromComponentLen -= uiBytesToRemove;
				}
			
				// Handle scenario of a case-sensitive index, but search is
				// case-insensitive.
		
				if (bIsDBCS ||
					 (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
					  bCaseInsensitive))
				{
					setFromCaseByte( pucFromKey, &uiFromComponentLen, uiFromCaseLen,
												bIsDBCS, bAscending, FALSE);
					setUntilCaseByte( pucUntilKey, &uiUntilComponentLen, uiUntilCaseLen,
												bIsDBCS, bAscending, FALSE);
				}
			}
		}
	}
	else // pucFromUTF8Buf != pucUntilUTF8Buf
	{
		if (RC_BAD( rc = bufferIStream.openStream( 
			(const char *)pucUntilUTF8Buf, uiUntilBufLen)))
		{
			goto Exit;
		}

		// Add ICD_ESC_CHAR to the icd flags because
		// the search string must have BACKSLASHES and '*' escaped.

		uiUntilComponentLen = uiUntilSpaceLeft;
		bUntilDataTruncated = FALSE;
		if (RC_BAD( rc = KYCollateValue( pucUntilKey, &uiUntilComponentLen,
							&bufferIStream, SFLM_STRING_TYPE,
							pIcd->uiFlags | ICD_ESC_CHAR, pIcd->uiCompareRules,
							pIcd->uiLimit,
							&uiUntilCollationLen, &uiUntilCaseLen,
							uiLanguage, bDoFirstSubstring, 
							FALSE, &bUntilDataTruncated,
							&bUntilOriginalCharsLost)))
		{
			goto Exit;
		}
		
		bufferIStream.closeStream();
		
		if (bUntilDataTruncated)
		{
			
			// Save the original data into pUntilSearchKey so the comparison
			// routines can do a comparison on the full value if
			// necessary.

			if (RC_BAD( rc = pUntilSearchKey->setUTF8( uiKeyComponent,
										pucUntilUTF8Buf, uiUntilBufLen)))
			{
				goto Exit;
			}
			*pbCanCompareOnKey = FALSE;
			uiUntilFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
		}
		else if (bUntilOriginalCharsLost)
		{
			*pbCanCompareOnKey = FALSE;
		}

		if (uiUntilComponentLen &&
			 (bIsDBCS ||
			  (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
			   bCaseInsensitive)))
		{
			setUntilCaseByte( pucUntilKey, &uiUntilComponentLen, uiUntilCaseLen,
									bIsDBCS, bAscending,
									(uiUntilFlags & EXCLUSIVE_LT_FLAG)
									? TRUE
									: FALSE);
		}
	}
	
	UW2FBA( (FLMUINT16)(uiFromKeyLen | uiFromFlags), pucFromKeyLenPos);
	UW2FBA( (FLMUINT16)(uiUntilKeyLen | uiUntilFlags), pucUntilKeyLenPos);
	
	// Set the FROM and UNTIL key length return values.

	uiFromKeyLen += 2;
	if (uiFromComponentLen != KEY_LOW_VALUE)
	{
		uiFromKeyLen += uiFromComponentLen;
		if (!(uiFromFlags & EXCLUSIVE_GT_FLAG))
		{
			*pbFromIncl = TRUE;
		}
	}
	uiUntilKeyLen += 2;
	if (uiUntilComponentLen != KEY_HIGH_VALUE)
	{
		uiUntilKeyLen += uiUntilComponentLen;
		if (!(uiUntilFlags & EXCLUSIVE_LT_FLAG))
		{
			*pbUntilIncl = TRUE;
		}
	}
	
Exit:

	return( rc);
}
コード例 #7
0
/****************************************************************************
Desc:	Compose a key buffer from the vector's components.
****************************************************************************/
RCODE F_DataVector::outputKey(
	IXD *				pIxd,
	FLMUINT			uiMatchFlags,
	FLMBYTE *		pucKeyBuf,
	FLMUINT			uiKeyBufSize,
	FLMUINT *		puiKeyLen,
	FLMUINT			uiSearchKeyFlag)
{
	RCODE						rc = NE_XFLM_OK;
	ICD *						pIcd;
	FLMBYTE *				pucToKey;
	FLMBYTE *				pucKeyLenPos;
	FLMUINT					uiToKeyLen;
	FLMUINT					uiKeyLen;
	FLMUINT					uiKeyComponent;
	FLMUINT					uiDataComponent;
	FLMUINT					uiContextComponent;
	FLMBOOL					bDataTruncated;
	FLMUINT					uiDataType;
	FLMUINT					uiLanguage;
	F_VECTOR_ELEMENT *	pVector = NULL;
	FLMBYTE					ucIDBuf [256];
	FLMUINT					uiIDLen = 0;
	FLMUINT64				ui64Id;
	FLMUINT					uiMaxKeySize;
	FLMUINT					uiDataLen;
	const FLMBYTE *		pucDataPtr;
	FLMBYTE					ucTmpSen [FLM_MAX_NUM_BUF_SIZE];
	FLMBYTE *				pucTmpSen;
	FLMUINT					uiSenLen;
	FLMUINT					uiIDMatchFlags = uiMatchFlags & (XFLM_MATCH_IDS | XFLM_MATCH_DOC_ID);
	IF_BufferIStream *	pBufferStream = NULL;

	if (uiIDMatchFlags)
	{
		pucToKey = &ucIDBuf [0];
		uiIDLen = 0;
		
		// Put document ID into buffer.  If there is room for at least nine
		// bytes, we can encode the ID right into the buffer safely.  Otherwise,
		// we have to use a temporary buffer and see if there is room.
		
		if (sizeof( ucIDBuf) - uiIDLen >= 9)
		{
			uiIDLen += f_encodeSEN( m_ui64DocumentID, &pucToKey);
		}
		else
		{
			pucTmpSen = &ucTmpSen [0];
			uiSenLen = f_encodeSEN( m_ui64DocumentID, &pucTmpSen);
			if (uiSenLen + uiIDLen > sizeof( ucIDBuf))
			{
				rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
				goto Exit;
			}
			f_memcpy( pucToKey, ucTmpSen, uiSenLen);
			uiIDLen += uiSenLen;
			pucToKey += uiSenLen;
		}

		if (uiIDMatchFlags & XFLM_MATCH_IDS)
		{
			// Append the Key component NODE IDs to the key
	
			for (uiKeyComponent = 0;
				  uiKeyComponent < pIxd->uiNumKeyComponents;
				  uiKeyComponent++)
			{
				ui64Id = getID( uiKeyComponent);

				// Put node ID into buffer.  If there is room for at least nine
				// bytes, we can encode the ID right into the buffer safely.  Otherwise,
				// we have to use a temporary buffer and see if there is room.
				
				if (sizeof( ucIDBuf) - uiIDLen >= 9)
				{
					uiIDLen += f_encodeSEN( ui64Id, &pucToKey);
				}
				else
				{
					pucTmpSen = &ucTmpSen [0];
					uiSenLen = f_encodeSEN( ui64Id, &pucTmpSen);
					if (uiSenLen + uiIDLen > sizeof( ucIDBuf))
					{
						rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
						goto Exit;
					}
					f_memcpy( pucToKey, ucTmpSen, uiSenLen);
					uiIDLen += uiSenLen;
					pucToKey += uiSenLen;
				}
			}
	
			// Append the Data NODE IDs to the key
	
			for (uiDataComponent = 0;
				  uiDataComponent < pIxd->uiNumDataComponents;
				  uiDataComponent++)
			{
				ui64Id = getID( uiDataComponent +
													pIxd->uiNumKeyComponents);

				// Put node ID into buffer.  If there is room for at least nine
				// bytes, we can encode the ID right into the buffer safely.  Otherwise,
				// we have to use a temporary buffer and see if there is room.
				
				if (sizeof( ucIDBuf) - uiIDLen >= 9)
				{
					uiIDLen += f_encodeSEN( ui64Id, &pucToKey);
				}
				else
				{
					pucTmpSen = &ucTmpSen [0];
					uiSenLen = f_encodeSEN( ui64Id, &pucTmpSen);
					if (uiSenLen + uiIDLen > sizeof( ucIDBuf))
					{
						rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
						goto Exit;
					}
					f_memcpy( pucToKey, ucTmpSen, uiSenLen);
					uiIDLen += uiSenLen;
					pucToKey += uiSenLen;
				}
			}
	
			// Append the Context NODE IDs to the key
	
			for (uiContextComponent = 0;
				  uiContextComponent < pIxd->uiNumContextComponents;
				  uiContextComponent++)
			{
				ui64Id = getID( uiContextComponent +
													pIxd->uiNumKeyComponents +
													pIxd->uiNumDataComponents);

				// Put node ID into buffer.  If there is room for at least nine
				// bytes, we can encode the ID right into the buffer safely.  Otherwise,
				// we have to use a temporary buffer and see if there is room.
				
				if (sizeof( ucIDBuf) - uiIDLen >= 9)
				{
					uiIDLen += f_encodeSEN( ui64Id, &pucToKey);
				}
				else
				{
					pucTmpSen = &ucTmpSen [0];
					uiSenLen = f_encodeSEN( ui64Id, &pucTmpSen);
					if (uiSenLen + uiIDLen > sizeof( ucIDBuf))
					{
						rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
						goto Exit;
					}
					f_memcpy( pucToKey, ucTmpSen, uiSenLen);
					uiIDLen += uiSenLen;
					pucToKey += uiSenLen;
				}
			}
		}
		
		if (uiIDLen >= uiKeyBufSize)
		{
			rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
			goto Exit;
		}
	}

	// Output the key components

	uiMaxKeySize = uiKeyBufSize - uiIDLen;
	uiLanguage = pIxd->uiLanguage;
	uiKeyLen = 0;
	pucToKey = pucKeyBuf;
	pIcd = pIxd->pFirstKey;
	for (uiKeyComponent = 0;;pIcd = pIcd->pNextKeyComponent, uiKeyComponent++)
	{
		pucKeyLenPos = pucToKey;
		pucToKey += 2;
		uiKeyLen += 2;
		
		uiDataType = icdGetDataType( pIcd);

		// Find matching node in the tree - if not found skip and continue.

		if ((pVector = getVector( uiKeyComponent, VECT_SLOT_HAS_DATA)) == NULL)
		{
			UW2FBA( 0, pucKeyLenPos);
		}
		else
		{
			uiToKeyLen = 0;
			bDataTruncated = FALSE;

			// Take the dictionary number and make it the key

			if (pIcd->uiFlags & ICD_PRESENCE)
			{
				FLMUINT	uiNum;

				// Component better be a number - and better match the
				// tag number of the ICD

				if (RC_BAD( rc = getUINT( uiKeyComponent, &uiNum)))
				{
					goto Exit;
				}
				
				flmAssert( uiNum == pIcd->uiDictNum || pIcd->uiDictNum == ELM_ROOT_TAG);

        		// Output the tag number

				if (uiKeyLen + 4 > uiMaxKeySize)
				{
					rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
					goto Exit;
				}
				
				f_UINT32ToBigEndian( (FLMUINT32)uiNum, pucToKey);
				uiToKeyLen = 4;
			}
			else if (pIcd->uiFlags & ICD_METAPHONE)
			{
				FLMUINT					uiMeta;
				FLMBYTE					ucStorageBuf[ FLM_MAX_NUM_BUF_SIZE];
				FLMUINT					uiStorageLen;

				if (uiDataType != XFLM_TEXT_TYPE)
				{
					rc = RC_SET_AND_ASSERT( NE_XFLM_SYNTAX);
					goto Exit;
				}
				
				if (pVector->uiDataType == XFLM_TEXT_TYPE)
				{
					if (RC_BAD( rc = getUTF8Ptr( uiKeyComponent,
											&pucDataPtr, &uiDataLen)))
					{
						goto Exit;
					}
					
					if( !pBufferStream)
					{
						if( RC_BAD( rc = FlmAllocBufferIStream( &pBufferStream)))
						{
							goto Exit;
						}
					}
	
					if (RC_BAD( rc = pBufferStream->openStream( 
						(const char *)pucDataPtr, uiDataLen)))
					{
						goto Exit;
					}
	
					if (RC_BAD( rc = f_getNextMetaphone( pBufferStream, &uiMeta)))
					{
						if( rc == NE_XFLM_EOF_HIT)
						{
							rc = RC_SET( NE_XFLM_SYNTAX);
						}
						goto Exit;
					}
	
					pBufferStream->closeStream();
				}
				else if (pVector->uiDataType == XFLM_NUMBER_TYPE)
				{
					if( RC_BAD( rc = getUINT( uiKeyComponent, &uiMeta)))
					{
						goto Exit;
					}
				}
				else
				{
					rc = RC_SET_AND_ASSERT( NE_XFLM_SYNTAX);
					goto Exit;
				}

				if ( uiMeta)
				{
					uiStorageLen = FLM_MAX_NUM_BUF_SIZE;
					if( RC_BAD( rc = flmNumber64ToStorage( uiMeta,
						&uiStorageLen, ucStorageBuf, FALSE, FALSE)))
					{
						goto Exit;
					}

					if( !pBufferStream)
					{
						if( RC_BAD( rc = FlmAllocBufferIStream( &pBufferStream)))
						{
							goto Exit;
						}
					}
					
					if (RC_BAD( rc = pBufferStream->openStream( 
						(const char *)ucStorageBuf, uiStorageLen)))
					{
						goto Exit;
					}

        			// Output the metaphone key piece

					uiToKeyLen = uiMaxKeySize - uiKeyLen;
					if( RC_BAD( rc = KYCollateValue( pucToKey, &uiToKeyLen,
						pBufferStream, XFLM_NUMBER_TYPE,
						pIcd->uiFlags, pIcd->uiCompareRules, pIcd->uiLimit,
						NULL, NULL, uiLanguage,
						FALSE, FALSE, &bDataTruncated, NULL)))
					{
						goto Exit;
					}
					
					pBufferStream->closeStream();
				}
			}
			else
			{
				if (uiDataType == XFLM_TEXT_TYPE)
				{
					if (RC_BAD( rc = getUTF8Ptr( uiKeyComponent,
											&pucDataPtr, &uiDataLen)))
					{
						goto Exit;
					}
				}
				else
				{
					pucDataPtr = (FLMBYTE *)getDataPtr( pVector);
					uiDataLen = pVector->uiDataLength;
				}
				
				if (uiDataLen)
				{
					if( !pBufferStream)
					{
						if( RC_BAD( rc = FlmAllocBufferIStream( &pBufferStream)))
						{
							goto Exit;
						}
					}
					
					if (RC_BAD( rc = pBufferStream->openStream( 
						(const char *)pucDataPtr, uiDataLen)))
					{
						goto Exit;
					}

					uiToKeyLen = uiMaxKeySize - uiKeyLen;
					if( RC_BAD( rc = KYCollateValue( pucToKey, &uiToKeyLen,
						pBufferStream, uiDataType,
						pIcd->uiFlags, pIcd->uiCompareRules, pIcd->uiLimit,
						NULL, NULL, uiLanguage,
						(FLMBOOL) ((pIcd->uiFlags & ICD_SUBSTRING)
								? (isLeftTruncated( pVector)
									? FALSE : TRUE)
								: FALSE),
						isRightTruncated( pVector),
						&bDataTruncated, NULL)))
					{
						goto Exit;
					}
					
					pBufferStream->closeStream();					
				}
			}

			if (uiToKeyLen)
			{

				//	Increment total key length

				pucToKey += uiToKeyLen;
				uiKeyLen += uiToKeyLen;
			}
			if (!bDataTruncated)
			{
				UW2FBA( (FLMUINT16)(uiToKeyLen | uiSearchKeyFlag),
									pucKeyLenPos);
			}
			else
			{
				UW2FBA( (FLMUINT16)(uiToKeyLen | TRUNCATED_FLAG |
									uiSearchKeyFlag), pucKeyLenPos); 
			}
		}

		// Check if done.

		if (!pIcd->pNextKeyComponent)
		{
   	 	break;
		}
	}
	
	// Output the node IDs, if requested.

	if (uiIDMatchFlags)
	{

		// There will always be room at this point for the
		// IDs - because it was subtracted out above.

		f_memcpy( pucToKey, ucIDBuf, uiIDLen);
	}
	*puiKeyLen = uiKeyLen + uiIDLen;

Exit:

	if( pBufferStream)
	{
		pBufferStream->Release();
		pBufferStream = NULL;
	}

	return( rc);
}
コード例 #8
0
/***************************************************************************
Desc:	Compares result set entries during the finalization stage to allow
		the result set to be sorted and to remove duplicates.
*****************************************************************************/
RCODE ixKeyCompare(
	F_Db *				pDb,
	F_INDEX *			pIndex,
	FLMBOOL				bCompareRowId,
	F_DataVector *		pSearchKey1,
	F_Row *				pRow1,
	const void *		pvKey1,
   FLMUINT           uiKeyLen1,
	F_DataVector *		pSearchKey2,
	F_Row *				pRow2,
	const void *		pvKey2,
	FLMUINT				uiKeyLen2,
	FLMINT *				piCompare)
{
	RCODE					rc = NE_SFLM_OK;
	FLMUINT				uiKeyComponent;
	ICD *					pIcd;
	FLMUINT				uiComponentLen1;
	FLMUINT				uiComponentLen2;
	FLMBOOL				bTruncated1;
	FLMBOOL				bTruncated2;
	const FLMBYTE *	pucKey1 = (const FLMBYTE *)pvKey1;
	const FLMBYTE *	pucKey2 = (const FLMBYTE *)pvKey2;
	const FLMBYTE *	pucKeyEnd1 = pucKey1 + uiKeyLen1;
	const FLMBYTE *	pucKeyEnd2 = pucKey2 + uiKeyLen2;
	FLMBOOL				bSortAscending;
	FLMBOOL				bSortMissingHigh;
	FLMUINT64			ui64RowId1;
	FLMUINT64			ui64RowId2;
	
	flmAssert( uiKeyLen1 && uiKeyLen2);
	
	// Loop for each compound piece of key

	uiKeyComponent = 0;
	pIcd = pIndex->pKeyIcds;
	for (;;)
	{
		bSortAscending = (pIcd->uiFlags & ICD_DESCENDING) ? FALSE : TRUE;
		bSortMissingHigh = (pIcd->uiFlags & ICD_MISSING_HIGH) ? TRUE : FALSE;
		uiComponentLen1 = getKeyComponentLength( pucKey1);
		uiComponentLen2 = getKeyComponentLength( pucKey2);
		
		// See if either component is a "high" key
		// NOTE: KEY_HIGH_VALUE always sorts highest, regardless of
		// ascending or descending.  It is never actually stored.  It is
		// only passed in for searching.
		
		if (uiComponentLen1 == KEY_HIGH_VALUE)
		{
			if (uiComponentLen2 == KEY_HIGH_VALUE)
			{
				uiComponentLen1 = uiComponentLen2 = 0;
				goto Test_Exclusive;
			}
			else
			{
				*piCompare = 1;
				goto Exit;
			}
		}
		else if (uiComponentLen2 == KEY_HIGH_VALUE)
		{
			*piCompare = -1;
			goto Exit;
		}
		
		// See if either component is a "low" key
		// NOTE: KEY_LOW_VALUE always sorts lowest, regardless of
		// ascending or descending.  It is never actually stored.  It is
		// only passed in for searching.
		
		if (uiComponentLen1 == KEY_LOW_VALUE)
		{
			if (uiComponentLen2 == KEY_LOW_VALUE)
			{
				uiComponentLen1 = uiComponentLen2 = 0;
				goto Test_Exclusive;
			}
			else
			{
				*piCompare = -1;
				goto Exit;
			}
		}
		else if (uiComponentLen2 == KEY_LOW_VALUE)
		{
			*piCompare = 1;
			goto Exit;
		}
		
		// See if either component is missing.  Need to apply the rules for
		// sorting missing components in that case.
	
		if (!uiComponentLen1)
		{
			if (uiComponentLen2)
			{
				if (bSortMissingHigh)
				{
					*piCompare = bSortAscending ? 1 : -1;
				}
				else
				{
					*piCompare = bSortAscending ? -1 : 1;
				}
				goto Exit;
			}
			else
			{
				goto Test_Exclusive;
			}
		}
		else if (!uiComponentLen2)
		{
			if (bSortMissingHigh)
			{
				*piCompare = bSortAscending ? -1 : 1;
			}
			else
			{
				*piCompare = bSortAscending ? 1 : -1;
			}
			goto Exit;
		}
		else
		{
		
			// Component length must not exceed remaining length of key.
			
			flmAssert( pucKey1 + 2 + uiComponentLen1 <= pucKeyEnd1 &&
						  pucKey2 + 2 + uiComponentLen2 <= pucKeyEnd2);
	
			if ((*piCompare = ixKeyCompareBinary( pucKey1 + 2, uiComponentLen1,
										pucKey2 + 2, uiComponentLen2, bSortAscending)) != 0)
			{
				goto Exit;
			}
			
			// Data is equal, see if one or the other is truncated.
			
			bTruncated1 = isKeyComponentTruncated( pucKey1);
			bTruncated2 = isKeyComponentTruncated( pucKey2);
			
			if (bTruncated1 || bTruncated2)
			{
				if (!bTruncated2)
				{
					*piCompare = bSortAscending ? 1 : -1;
					goto Exit;
				}
				else if (!bTruncated1)
				{
					*piCompare = bSortAscending ? -1 : 1;
					goto Exit;
				}
				
				// Need to get the row that holds the data for the 1st key.
				
				if (isSearchKeyComponent( pucKey1))
				{
					flmAssert( pSearchKey1);
					ui64RowId1 = pSearchKey1->getRowId();
					
					// The search key better have a row ID or the untruncated
					// value.
					
					flmAssert( ui64RowId1 ||
									!pSearchKey1->isRightTruncated( uiKeyComponent));
				}
				else
				{
					if (RC_BAD( rc = ixKeyGetRowId( pIndex, pucKey1, pucKeyEnd1,
												uiKeyComponent, &ui64RowId1)))
					{
						goto Exit;
					}
					flmAssert( ui64RowId1);
				}
				
				// Get the row that holds the data for the 2nd key.
				
				if (isSearchKeyComponent( pucKey2))
				{
					flmAssert( pSearchKey2);
					ui64RowId2 = pSearchKey2->getRowId();
					
					// The search key better have a row ID or the untruncated
					// value.
					
					flmAssert( ui64RowId2 ||
									!pSearchKey2->isRightTruncated( uiKeyComponent));
				}
				else
				{
					if (RC_BAD( rc = ixKeyGetRowId( pIndex, pucKey2, pucKeyEnd2,
												uiKeyComponent, &ui64RowId2)))
					{
						goto Exit;
					}
					flmAssert( ui64RowId2);
				}
	
				// If the row IDs are equal, we can skip fetching the data, because
				// it will be the same.
				
				if (ui64RowId1 != ui64RowId2)
				{
					FLMBYTE		ucDynaBuf1[ 64];
					FLMBYTE		ucDynaBuf2[ 64];
					F_DynaBuf	dynaBuf1( ucDynaBuf1, sizeof( ucDynaBuf1));
					F_DynaBuf	dynaBuf2( ucDynaBuf2, sizeof( ucDynaBuf2));
					F_TABLE *	pTable = pDb->getDict()->getTable( pIndex->uiTableNum);
					F_COLUMN *	pColumn = pDb->getDict()->getColumn( pTable, pIcd->uiColumnNum);
					
					// Better be binary data or text data.
					
					switch (pColumn->eDataTyp)
					{
						case SFLM_STRING_TYPE:
						{
							if (RC_BAD( rc = ixKeyGetUTF8( pDb, pIndex->uiTableNum,
													pIcd, pRow1, ui64RowId1,
													pSearchKey1, uiKeyComponent, &dynaBuf1)))
							{
								goto Exit;
							}
							if (RC_BAD( rc = ixKeyGetUTF8( pDb, pIndex->uiTableNum,
													pIcd, pRow2, ui64RowId2,
													pSearchKey2, uiKeyComponent, &dynaBuf2)))
							{
								goto Exit;
							}
							
							if (RC_BAD( rc = f_compareUTF8Strings(
														dynaBuf1.getBufferPtr(),
														dynaBuf1.getDataLength(),
														FALSE,
														dynaBuf2.getBufferPtr(),
														dynaBuf2.getDataLength(),
														FALSE, pIcd->uiCompareRules,
														pIndex->uiLanguage, piCompare)))
							{
								goto Exit;
							}
							if (*piCompare < 0)
							{
								*piCompare = bSortAscending ? -1 : 1;
								goto Exit;
							}
							else if (*piCompare > 0)
							{
								*piCompare = bSortAscending ? 1 : -1;
								goto Exit;
							}
							break;
						}
				
						case SFLM_BINARY_TYPE:
						{
							if (RC_BAD( rc = ixKeyGetBinary( pDb, pIndex->uiTableNum,
													pIcd, pRow1, ui64RowId1,
													pSearchKey1, uiKeyComponent, &dynaBuf1)))
							{
								goto Exit;
							}
							if (RC_BAD( rc = ixKeyGetBinary( pDb, pIndex->uiTableNum,
													pIcd, pRow2, ui64RowId2,
													pSearchKey2, uiKeyComponent, &dynaBuf2)))
							{
								goto Exit;
							}
							
							if ((*piCompare = ixKeyCompareBinary(
														dynaBuf1.getBufferPtr(),
														dynaBuf1.getDataLength(),
														dynaBuf2.getBufferPtr(),
														dynaBuf2.getDataLength(),
														bSortAscending)) != 0)
							{
								goto Exit;
							}
							break;
						}
	
						default:
							rc = RC_SET_AND_ASSERT( NE_SFLM_DATA_ERROR);
							goto Exit;
					}
				}
			}
		}

Test_Exclusive:
			
		// See if either component is exclusive - everything else is
		// equal up to this point.
		
		if (isKeyComponentLTExclusive( pucKey1))
		{
			if (!isKeyComponentLTExclusive( pucKey2))
			{
				*piCompare = bSortAscending ? -1 : 1;
				goto Exit;
			}
		}
		else if (isKeyComponentGTExclusive( pucKey1))
		{
			if (!isKeyComponentGTExclusive( pucKey2))
			{
				*piCompare = bSortAscending ? 1 : -1;
				goto Exit;
			}
		}
		else if (isKeyComponentLTExclusive( pucKey2))
		{
			*piCompare = bSortAscending ? 1 : -1;
			goto Exit;
		}
		else if (isKeyComponentGTExclusive( pucKey2))
		{
			*piCompare = bSortAscending ? -1 : 1;
			goto Exit;
		}
		
		// Position to the end of this component

		pucKey1 += (2 + uiComponentLen1);
		pucKey2 += (2 + uiComponentLen2);

		// If there are no more ICDs, we are done with the key
		// components.

		if (uiKeyComponent < pIndex->uiNumKeyComponents)
		{
			break;
		}
		pIcd++;
		uiKeyComponent++;

		// See if we are out of key components - this may be a search that
		// passed in only a partial key.
		
		if (pucKey1 >= pucKeyEnd1)
		{
			*piCompare = (pucKey2 >= pucKeyEnd2) ? 0 : -1;
			goto Exit;
		}
		else if (pucKey2 >= pucKeyEnd2)
		{
			*piCompare = 1;
			goto Exit;
		}
	}
	
	// Compare the row ID, if being requested to.  Includes comparing of the
	// last byte, which is the total number of bytes in the row ID.
	
	if (bCompareRowId)
	{
		
		// See if we have a row ID - this may be a search that
		// passed in only a partial key and there is now ROW id on it.
		
		if (pucKey1 >= pucKeyEnd1)
		{
			*piCompare = (pucKey2 >= pucKeyEnd2) ? 0 : -1;
			goto Exit;
		}
		else if (pucKey2 >= pucKeyEnd2)
		{
			*piCompare = 1;
			goto Exit;
		}
		
		// See if either one has an ID buffer of "high"
		
		if (*pucKey1 == 0xFF)
		{
			
			// Key1 has a "high" set of node IDs, see what key2 has.
			
			*piCompare = (*pucKey2 == 0xFF) ? 0 : 1;
			goto Exit;
		}
		else if (*pucKey2 == 0xFF)
		{
			// Key2 has a "high" set of node IDs, key1 does not.
			
			*piCompare = -1;
			goto Exit;
		}
		else
		{
			FLMUINT64	ui64RowId1;
			FLMUINT64	ui64RowId2;
			
			// Get the document ID and compare it, and only it.
			// At this point, both keys should be positioned to
			// get the document ID.
			
			if (RC_BAD( rc = f_decodeSEN64( &pucKey1, pucKeyEnd1, &ui64RowId1)))
			{
				goto Exit;
			}
			if (RC_BAD( rc = f_decodeSEN64( &pucKey2, pucKeyEnd2, &ui64RowId2)))
			{
				goto Exit;
			}
			if (ui64RowId1 == ui64RowId2)
			{
				*piCompare = 0;
			}
			else if (ui64RowId1 < ui64RowId2)
			{
				*piCompare = -1;
			}
			else
			{
				*piCompare = 1;
			}
		}
	}
	else
	{
		*piCompare = 0;
	}

Exit:

	return( rc);
}
コード例 #9
0
/****************************************************************************
Desc:	Split the root block and make two new non-leaf blocks.
		The secret here is that the root block never moves (cheers!).
		This takes a little longer but is worth the work because the
		root block never goes out to disk and is not in the cache.
****************************************************************************/
RCODE F_BtreeRoot::split(
    void *			pvCurEntry,
    FLMUINT			uiCurChildAddr)
{
    RCODE				rc = NE_FLM_OK;
    FLMBYTE *		pucEntry;
    FLMBYTE *		pucChildAddr;
    F_BtreeBlk *		pLeftBlk;
    F_BtreeBlk *		pRightBlk;
    F_BtreeBlk *		pBlk;
    FLMUINT			uiChildAddr;
    FLMUINT			uiPos;
    FLMUINT			uiEntryCount = entryCount();
    FLMUINT			uiMid = (uiEntryCount + 1) >> 1;

    if (RC_BAD( rc = setupTree( NULL, ACCESS_BTREE_NON_LEAF,
                                &pLeftBlk, &pRightBlk)))
    {
        goto Exit;
    }

    // Call search entry once just to setup for insert.

    (void) pLeftBlk->searchEntry( ENTRY_POS( 0));

    // Take the entries from the root block and move into leafs.

    for (uiPos = 0; uiPos <= uiMid; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        pucChildAddr = pucEntry + m_uiEntrySize;
        uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);

        if (RC_BAD( rc = pLeftBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            goto Exit;
        }
    }

    // Call search entry once just to setup for insert.

    (void) pRightBlk->searchEntry( ENTRY_POS( 0));

    for (uiPos = uiMid + 1; uiPos < uiEntryCount; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        pucChildAddr = pucEntry + m_uiEntrySize;
        uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);

        if ((rc = pRightBlk->searchEntry( pucEntry )) != NE_FLM_NOT_FOUND)
        {
            rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
            goto Exit;
        }

        if (RC_BAD( rc = pRightBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            goto Exit;
        }
    }

    // Reset the root block and insert new midpoint.

    entryCount( 0);
    lemBlk( pRightBlk->blkAddr());	// Duplicated just in case.
    pucEntry = ENTRY_POS( uiMid);

    if ((rc = searchEntry( pucEntry )) != NE_FLM_NOT_FOUND)
    {
        rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
        goto Exit;
    }

    if (RC_BAD( rc = insertEntry( pucEntry, pLeftBlk->blkAddr() )))
    {
        goto Exit;
    }

    // Insert the current entry (parameters) into the left or right blk.
    // This could be done a number of different ways.
    (void) searchEntry( pvCurEntry, &uiChildAddr);
    if (RC_BAD( rc = readBlk( uiChildAddr, ACCESS_BTREE_NON_LEAF, &pBlk)))
    {
        goto Exit;
    }
    (void) pBlk->searchEntry( pvCurEntry);
    if (RC_BAD( rc = pBlk->insertEntry( pvCurEntry, uiCurChildAddr)))
    {
        goto Exit;
    }

Exit:

    return( rc);
}
コード例 #10
0
/****************************************************************************
Desc:	Populate a vector's components from the key part of an index key.
****************************************************************************/
RCODE F_DataVector::inputKey(
	IXD *					pIxd,
	const FLMBYTE *	pucKey,
	FLMUINT				uiKeyLen)
{
	RCODE					rc = NE_XFLM_OK;
	const FLMBYTE *	pucKeyEnd = pucKey + uiKeyLen;
	FLMBYTE				ucDataBuf [XFLM_MAX_KEY_SIZE];
	FLMUINT				uiDataLen;
	ICD *					pIcd;
	FLMUINT				uiLanguage = pIxd->uiLanguage;
	FLMUINT				uiComponentLen;
	FLMUINT				uiDataType;
	FLMBOOL				bDataRightTruncated;
	FLMBOOL				bFirstSubstring;
	FLMBOOL				bIsText;
	FLMUINT				uiComponent;
	FLMUINT64			ui64Id;
	FLMUINT				uiDictNumber;

	flmAssert( uiKeyLen);

	// Loop for each compound piece of key

	uiComponent = 0;
	pIcd = pIxd->pFirstKey;
	while (pIcd)
	{
		if (uiKeyLen < 2)
		{
			rc = RC_SET_AND_ASSERT( NE_XFLM_BTREE_ERROR);
			goto Exit;
		}
		
		uiComponentLen = getKeyComponentLength( pucKey);
		bDataRightTruncated = isKeyComponentTruncated( pucKey);
		uiKeyLen -= 2;
		pucKey += 2;
		
		if (uiComponentLen > uiKeyLen)
		{
			rc = RC_SET_AND_ASSERT( NE_XFLM_BTREE_ERROR);
			goto Exit;
		}
		
		bFirstSubstring = FALSE;
		bIsText = (icdGetDataType( pIcd) == XFLM_TEXT_TYPE &&
					  !(pIcd->uiFlags & (ICD_PRESENCE | ICD_METAPHONE)))
					 ? TRUE
					 : FALSE;

		uiDataType = icdGetDataType( pIcd);
		uiDictNumber = pIcd->uiDictNum;
		if (uiComponentLen)
		{
			if (pIcd->uiFlags & ICD_PRESENCE)
			{
				FLMUINT	uiNum;
				
				if (uiComponentLen != 4 || bDataRightTruncated)
				{
					rc = RC_SET_AND_ASSERT( NE_XFLM_BTREE_ERROR);
					goto Exit;
				}
				
				uiNum = (FLMUINT)f_bigEndianToUINT32( pucKey);
	
				// What is stored in the key better match the dictionary
				// number of the ICD.
	
				if (pIcd->uiDictNum != ELM_ROOT_TAG)
				{
					if (uiNum != uiDictNumber)
					{
						rc = RC_SET_AND_ASSERT( NE_XFLM_BTREE_ERROR);
						goto Exit;
					}
				}
				else
				{
					uiDictNumber = uiNum;
				}
				if (RC_BAD( rc = setUINT( uiComponent, uiNum)))
				{
					goto Exit;
				}
			}
			else if (pIcd->uiFlags & ICD_METAPHONE)
			{
				uiDataLen = sizeof( ucDataBuf);
	
				if ( uiComponentLen)
				{
					if( RC_BAD( rc = flmCollationNum2StorageNum( pucKey,
						uiComponentLen, ucDataBuf, &uiDataLen)))
					{
						goto Exit;
					}
				}
				else
				{
					uiDataLen = 0;
				}
	
				if (bDataRightTruncated)
				{
					rc = RC_SET_AND_ASSERT( NE_XFLM_BTREE_ERROR);
					goto Exit;
				}
	
				// Allocate and copy value into the component.  NOTE:
				// storeValue handles zero length data.
	
				if (RC_BAD( rc = storeValue( uiComponent, XFLM_NUMBER_TYPE, 
														ucDataBuf, uiDataLen)))
				{
					goto Exit;
				}
			}
			else
			{
	
				// Grab only the Nth section of key if compound key
	
				switch (uiDataType)
				{
					case XFLM_TEXT_TYPE:
					{
						FLMBOOL bTmpTruncated = FALSE;
	
						if (uiComponentLen)
						{
							uiDataLen = sizeof( ucDataBuf);
							if (RC_BAD( rc = flmColText2StorageText( pucKey,
								uiComponentLen,
								ucDataBuf, &uiDataLen, uiLanguage,
								&bTmpTruncated, &bFirstSubstring)))
							{
								goto Exit;
							}
							
							if (bTmpTruncated != bDataRightTruncated)
							{
								rc = RC_SET_AND_ASSERT( NE_XFLM_BTREE_ERROR);
								goto Exit;
							}
						}
						else
						{
							uiDataLen = 0;
						}
						break;
					}
	
					case XFLM_NUMBER_TYPE:
					{
						if (uiComponentLen)
						{
							uiDataLen = sizeof( ucDataBuf);
							if( RC_BAD( rc = flmCollationNum2StorageNum( pucKey,
								uiComponentLen, ucDataBuf, &uiDataLen)))
							{
								goto Exit;
							}
						}
						else
						{
							uiDataLen = 0;
						}
						
						if (bDataRightTruncated)
						{
							rc = RC_SET_AND_ASSERT( NE_XFLM_BTREE_ERROR);
							goto Exit;
						}
						break;
					}
	
					case XFLM_BINARY_TYPE:
					{
						uiDataLen = uiComponentLen;
						if (uiComponentLen > sizeof( ucDataBuf))
						{
							rc = RC_SET( NE_XFLM_CONV_DEST_OVERFLOW);
							goto Exit;
						}
						if (uiComponentLen)
						{
							f_memcpy( ucDataBuf, pucKey, uiComponentLen);
						}
						break;
					}
	
					default:
						rc = RC_SET( NE_XFLM_DATA_ERROR);
						goto Exit;
				}
	
				// Allocate and copy value into the component.  NOTE:
				// storeValue handles zero length data.
	
				if (RC_BAD( rc = storeValue( uiComponent, uiDataType, ucDataBuf,
											uiDataLen)))
				{
					goto Exit;
				}
	
				// Set first sub-string and truncated flags.
	
				if ((pIcd->uiFlags & ICD_SUBSTRING) && !bFirstSubstring)
				{
					setLeftTruncated( uiComponent);
				}
				if (bDataRightTruncated)
				{
					setRightTruncated( uiComponent);
				}
			}
		}
		else
		{
			if ((pIcd->uiFlags & ICD_PRESENCE) && uiDictNumber == ELM_ROOT_TAG)
			{
				uiDictNumber = 0;
			}
		}

		// Store the name ID

		if (RC_BAD( rc = setNameId( uiComponent, uiDictNumber,
								(FLMBOOL)((pIcd->uiFlags & ICD_IS_ATTRIBUTE)
											 ? TRUE
											 : FALSE), FALSE)))
		{
			goto Exit;
		}

		// Position to the end of this component

		flmAssert( uiKeyLen >= uiComponentLen);
		pucKey += uiComponentLen;
		uiKeyLen -= uiComponentLen;
		uiComponent++;

		pIcd = pIcd->pNextKeyComponent;
	}
	
	// See if we have a document ID.
	
	if (RC_BAD( rc = f_decodeSEN64( &pucKey, pucKeyEnd, &m_ui64DocumentID)))
	{
		goto Exit;
	}
	
	// Get the node IDs for the key components, if any

	pIcd = pIxd->pFirstKey;
	uiComponent = 0;
	while (pIcd)
	{
		
		// Extract the component node ID

		if (RC_BAD( rc = f_decodeSEN64( &pucKey, pucKeyEnd, &ui64Id)))
		{
			goto Exit;
		}
		
		// No need to store if it is zero
		
		if (ui64Id)
		{
			if (RC_BAD( rc = setID( uiComponent, ui64Id)))
			{
				goto Exit;
			}
		}
		uiComponent++;
		pIcd = pIcd->pNextKeyComponent;
	}

	// Get the node IDs for the data components, if any

	pIcd = pIxd->pFirstData;
	while (pIcd)
	{

		// Extract the component node ID

		if (RC_BAD( rc = f_decodeSEN64( &pucKey, pucKeyEnd, &ui64Id)))
		{
			goto Exit;
		}
		
		// No need to store if it is zero
		
		if (ui64Id)
		{
			if (RC_BAD( rc = setID( uiComponent, ui64Id)))
			{
				goto Exit;
			}
		}
		
		// Store the name ID

		if (RC_BAD( rc = setNameId( uiComponent, pIcd->uiDictNum,
											(FLMBOOL)((pIcd->uiFlags & ICD_IS_ATTRIBUTE)
												 ? TRUE
												 : FALSE), TRUE)))
		{
			goto Exit;
		}
		uiComponent++;
		pIcd = pIcd->pNextDataComponent;
	}

	// Get the node IDs for the context components, if any

	pIcd = pIxd->pFirstContext;
	while (pIcd)
	{

		// Extract the component node ID

		if (RC_BAD( rc = f_decodeSEN64( &pucKey, pucKeyEnd, &ui64Id)))
		{
			goto Exit;
		}
		
		// No need to store if it is zero
		
		if (ui64Id)
		{
			if (RC_BAD( rc = setID( uiComponent, ui64Id)))
			{
				goto Exit;
			}
		}
		
		// Store the name ID

		if (RC_BAD( rc = setNameId( uiComponent, pIcd->uiDictNum,
											(FLMBOOL)((pIcd->uiFlags & ICD_IS_ATTRIBUTE)
												 ? TRUE
												 : FALSE), TRUE)))
		{
			goto Exit;
		}
		uiComponent++;
		pIcd = pIcd->pNextKeyComponent;
	}

Exit:

	return( rc);
}
コード例 #11
0
/****************************************************************************
Desc:		Add a key piece to the from and until key.  Text fields are not 
			handled in this routine because of their complexity.
Notes:	The goal of this code is to build a the collated compound piece
			for the 'from' and 'until' key only once instead of twice.
****************************************************************************/
FSTATIC RCODE flmAddNonTextKeyPiece(
	SQL_PRED *		pPred,
	F_INDEX *		pIndex,
	FLMUINT			uiKeyComponent,
	ICD *				pIcd,
	F_COLUMN *		pColumn,
	F_DataVector *	pFromSearchKey,
	FLMBYTE *		pucFromKey,
	FLMUINT *		puiFromKeyLen,
	F_DataVector *	pUntilSearchKey,
	FLMBYTE *		pucUntilKey,
	FLMUINT *		puiUntilKeyLen,
	FLMBOOL *		pbCanCompareOnKey,
	FLMBOOL *		pbFromIncl,
	FLMBOOL *		pbUntilIncl)
{
	RCODE						rc = NE_SFLM_OK;
	FLMBYTE *				pucFromKeyLenPos;
	FLMBYTE *				pucUntilKeyLenPos;
	FLMBOOL					bDataTruncated;
	FLMBYTE *				pucFromBuf;
	FLMUINT					uiFromBufLen;
	FLMBYTE *				pucUntilBuf;
	FLMUINT					uiUntilBufLen;
	FLMBYTE					ucFromNumberBuf [FLM_MAX_NUM_BUF_SIZE];
	FLMBYTE					ucUntilNumberBuf [FLM_MAX_NUM_BUF_SIZE];
	FLMUINT					uiValue;
	FLMINT					iValue;
	FLMBOOL					bNeg;
	FLMUINT64				ui64Value;
	FLMINT64					i64Value;
	FLMUINT					uiFromFlags = 0;
	FLMUINT					uiUntilFlags = 0;
	SQL_VALUE *				pFromValue;
	SQL_VALUE *				pUntilValue;
	FLMBOOL					bInclFrom;
	FLMBOOL					bInclUntil;
	FLMBOOL					bAscending = (pIcd->uiFlags & ICD_DESCENDING) ? FALSE: TRUE;
	F_BufferIStream		bufferIStream;
	FLMUINT					uiFromKeyLen = *puiFromKeyLen;
	FLMUINT					uiUntilKeyLen = *puiUntilKeyLen;
	FLMUINT					uiFromComponentLen;
	FLMUINT					uiUntilComponentLen;
	FLMUINT					uiFromSpaceLeft;
	FLMUINT					uiUntilSpaceLeft;
	
	// Leave room for the component length

	pucFromKeyLenPos = pucFromKey + uiFromKeyLen;
	pucUntilKeyLenPos = pucUntilKey + uiUntilKeyLen;
	pucFromKey = pucFromKeyLenPos + 2;
	pucUntilKey = pucUntilKeyLenPos + 2;
	uiFromSpaceLeft = SFLM_MAX_KEY_SIZE - uiFromKeyLen - 2;
	uiUntilSpaceLeft = SFLM_MAX_KEY_SIZE - uiUntilKeyLen - 2;

	// Handle the presence case here - this is not done in kyCollate.

	if (pIcd->uiFlags & ICD_PRESENCE)
	{
		
		// If we don't have enough space for the component in the from
		// key, just get all values.
		
		if (uiFromSpaceLeft < 4)
		{
			uiFromComponentLen = KEY_LOW_VALUE;
		}
		else
		{
			f_UINT32ToBigEndian( (FLMUINT32)pIcd->uiColumnNum, pucFromKey);
			uiFromComponentLen = 4;
		}
		
		// If we don't have enough space for the component in the until
		// key, just get all values.
		
		if (uiUntilSpaceLeft < 4)
		{
			uiUntilComponentLen = KEY_HIGH_VALUE;
		}
		else
		{
			f_UINT32ToBigEndian( (FLMUINT32)pIcd->uiColumnNum, pucUntilKey);
			uiUntilComponentLen = 4;
		}
	}
	else if (pIcd->uiFlags & ICD_METAPHONE)
	{
		if (pPred->eOperator != SQL_APPROX_EQ_OP ||
			 pPred->pFromValue->eValType != SQL_UTF8_VAL)
		{
			uiFromComponentLen = KEY_LOW_VALUE;
			uiUntilComponentLen = KEY_HIGH_VALUE;
			if (pPred->eOperator != SQL_EXISTS_OP)
			{
				*pbCanCompareOnKey = FALSE;
			}
		}
		else
		{
			*pbCanCompareOnKey = FALSE;
	
			// The value type in pPred->pFromValue is SQL_UTF8_VAL, but the
			// calling routine should have put the metaphone value into
			// pPred->pFromValue->val.uiVal.  Sort of weird, but was the
			// only way we could evaluate the cost of multiple words in
			// the string.
	
			uiFromBufLen = sizeof( ucFromNumberBuf);
			if( RC_BAD( rc = FlmUINT2Storage( pPred->pFromValue->val.uiVal,
									&uiFromBufLen, ucFromNumberBuf)))
			{
				goto Exit;
			}
			pucFromBuf = &ucFromNumberBuf [0];
			
			if (RC_BAD( rc = bufferIStream.openStream( 
				(const char *)pucFromBuf, uiFromBufLen)))
			{
				goto Exit;
			}
	
			uiFromComponentLen = uiFromSpaceLeft;
			bDataTruncated = FALSE;
			
			// Pass 0 for compare rules because it is non-text
			
			if (RC_BAD( rc = KYCollateValue( pucFromKey, &uiFromComponentLen,
									&bufferIStream, SFLM_NUMBER_TYPE,
									pIcd->uiFlags, 0,
									pIcd->uiLimit, NULL, NULL, 
									pIndex->uiLanguage, FALSE, FALSE,
									&bDataTruncated, NULL)))
			{
				goto Exit;
			}
			
			bufferIStream.closeStream();
			
			// Key component needs to fit in both the from and until
			// buffers.  If it will not, we simply set it up to search
			// from first to last - all values.
			
			if (bDataTruncated || uiUntilSpaceLeft < uiFromComponentLen)
			{
				uiFromComponentLen = KEY_LOW_VALUE;
				uiUntilComponentLen = KEY_HIGH_VALUE;
				*pbCanCompareOnKey = FALSE;
			}
			else
			{
				if ((uiUntilComponentLen = uiFromComponentLen) != 0)
				{
					f_memcpy( pucUntilKey, pucFromKey, uiFromComponentLen);
				}
			}
		}
	}
	else if (pPred->eOperator == SQL_EXISTS_OP ||
				pPred->eOperator == SQL_NE_OP ||
				pPred->eOperator == SQL_APPROX_EQ_OP)
	{
		
		// Setup a first-to-last key

		uiFromComponentLen = KEY_LOW_VALUE;
		uiUntilComponentLen = KEY_HIGH_VALUE;
	}
	else
	{

		// Only other operator possible is the range operator

		flmAssert( pPred->eOperator == SQL_RANGE_OP);
		
		if (bAscending)
		{
			pFromValue = pPred->pFromValue;
			bInclFrom = pPred->bInclFrom;
			pUntilValue = pPred->pUntilValue;
			bInclUntil = pPred->bInclUntil;
		}
		else
		{
			pFromValue = pPred->pUntilValue;
			bInclFrom = pPred->bInclUntil;
			pUntilValue = pPred->pFromValue;
			bInclUntil = pPred->bInclFrom;
		}
		
		// Set up from buffer

		if (!pFromValue)
		{
			pucFromBuf = NULL;
			uiFromBufLen = 0;
		}
		else
		{
			switch (pFromValue->eValType)
			{
				case SQL_UINT_VAL:
					uiValue = pFromValue->val.uiVal;
					if (!bInclFrom)
					{
						if (bAscending)
						{
							uiValue++;
						}
						else
						{
							uiValue--;
						}
					}
					uiFromBufLen = sizeof( ucFromNumberBuf);
					if( RC_BAD( rc = FlmUINT2Storage( uiValue, &uiFromBufLen,
											ucFromNumberBuf)))
					{
						goto Exit;
					}
					pucFromBuf = &ucFromNumberBuf [0];
					break;

				case SQL_INT_VAL:
					iValue = pFromValue->val.iVal;
					if (!bInclFrom)
					{
						if (bAscending)
						{
							iValue++;
						}
						else
						{
							iValue--;
						}
					}
					uiFromBufLen = sizeof( ucFromNumberBuf);
					if (RC_BAD( rc = FlmINT2Storage( iValue, &uiFromBufLen,
											ucFromNumberBuf)))
					{
						goto Exit;
					}
					pucFromBuf = &ucFromNumberBuf [0];
					break;

				case SQL_UINT64_VAL:
					ui64Value = pFromValue->val.ui64Val;
					if (!bInclFrom)
					{
						if (bAscending)
						{
							ui64Value++;
						}
						else
						{
							ui64Value--;
						}
					}
					uiFromBufLen = sizeof( ucFromNumberBuf);
					if (RC_BAD( rc = flmNumber64ToStorage( ui64Value, &uiFromBufLen,
						ucFromNumberBuf, FALSE, FALSE)))
					{
						goto Exit;
					}
					pucFromBuf = &ucFromNumberBuf [0];
					break;

				case SQL_INT64_VAL:
					i64Value = pFromValue->val.i64Val;
					if (!bInclFrom)
					{
						if (bAscending)
						{
							i64Value++;
						}
						else
						{
							i64Value--;
						}
					}
					if (i64Value < 0)
					{
						bNeg = TRUE;
						ui64Value = (FLMUINT64)-i64Value;
					}
					else
					{
						bNeg = FALSE;
						ui64Value = (FLMUINT64)i64Value;
					}

					uiFromBufLen = sizeof( ucFromNumberBuf);
					if (RC_BAD( rc = flmNumber64ToStorage( ui64Value, &uiFromBufLen,
						ucFromNumberBuf, bNeg, FALSE)))
					{
						goto Exit;
					}
					pucFromBuf = &ucFromNumberBuf [0];
					break;

				case SQL_BINARY_VAL:
					pucFromBuf = pFromValue->val.bin.pucValue;
					uiFromBufLen = pFromValue->val.bin.uiByteLen;
					if (!bInclFrom)
					{
						
						// Should use EXCLUSIVE_GT_FLAG even if in descending
						// order, because the comparison routines will take
						// that into account.
						
						uiFromFlags |= EXCLUSIVE_GT_FLAG;
					}
					break;

				default:

					// Text type should have been taken care of elsewhere.

					rc = RC_SET_AND_ASSERT( NE_SFLM_QUERY_SYNTAX);
					goto Exit;
			}
		}

		// Set up until buffer.

		if (!pUntilValue)
		{
			pucUntilBuf = NULL;
			uiUntilBufLen = 0;
		}
		else if (pUntilValue == pFromValue)
		{
			pucUntilBuf = pucFromBuf;
			uiUntilBufLen = uiFromBufLen;
		}
		else
		{
			switch (pUntilValue->eValType)
			{
				case SQL_UINT_VAL:
					uiValue = pUntilValue->val.uiVal;
					if (!bInclUntil)
					{
						if (bAscending)
						{
							uiValue--;
						}
						else
						{
							uiValue++;
						}
					}
					uiUntilBufLen = sizeof( ucUntilNumberBuf);
					if( RC_BAD( rc = FlmUINT2Storage( uiValue, &uiUntilBufLen,
											ucUntilNumberBuf)))
					{
						goto Exit;
					}
					pucUntilBuf = &ucUntilNumberBuf [0];
					break;

				case SQL_INT_VAL:
					iValue = pUntilValue->val.iVal;
					if (!bInclUntil)
					{
						if (bAscending)
						{
							iValue--;
						}
						else
						{
							iValue++;
						}
					}
					uiUntilBufLen = sizeof( ucUntilNumberBuf);
					if (RC_BAD( rc = FlmINT2Storage( iValue, &uiUntilBufLen,
											ucUntilNumberBuf)))
					{
						goto Exit;
					}
					pucUntilBuf = &ucUntilNumberBuf [0];
					break;

				case SQL_UINT64_VAL:
					ui64Value = pUntilValue->val.ui64Val;
					if (!bInclUntil)
					{
						if (bAscending)
						{
							ui64Value--;
						}
						else
						{
							ui64Value++;
						}
					}
					uiUntilBufLen = sizeof( ucUntilNumberBuf);
					if (RC_BAD( rc = flmNumber64ToStorage( ui64Value, &uiUntilBufLen,
						ucUntilNumberBuf, FALSE, FALSE)))
					{
						goto Exit;
					}
					pucUntilBuf = &ucUntilNumberBuf [0];
					break;

				case SQL_INT64_VAL:
					i64Value = pUntilValue->val.i64Val;
					if (!bInclUntil)
					{
						if (bAscending)
						{
							i64Value--;
						}
						else
						{
							i64Value++;
						}
					}
					if (i64Value < 0)
					{
						bNeg = TRUE;
						ui64Value = (FLMUINT64)-i64Value;
					}
					else
					{
						bNeg = FALSE;
						ui64Value = (FLMUINT64)i64Value;
					}

					uiUntilBufLen = sizeof( ucUntilNumberBuf);
					if (RC_BAD( rc = flmNumber64ToStorage( ui64Value, &uiUntilBufLen,
						ucUntilNumberBuf, bNeg, FALSE)))
					{
						goto Exit;
					}
					pucUntilBuf = &ucUntilNumberBuf [0];
					break;

				case SQL_BINARY_VAL:
					pucUntilBuf = pUntilValue->val.bin.pucValue;
					uiUntilBufLen = pUntilValue->val.bin.uiByteLen;
					if (!bInclUntil)
					{
						
						// Should use EXCLUSIVE_LT_FLAG even if in descending
						// order, because the comparison routines will take
						// that into account.
						
						uiUntilFlags |= EXCLUSIVE_LT_FLAG;
					}
					break;

				default:

					// Text type should have been taken care of elsewhere.

					rc = RC_SET_AND_ASSERT( NE_SFLM_QUERY_SYNTAX);
					goto Exit;
			}
		}

		// Generate the keys using the from and until buffers that
		// have been set up.

		// Set up the from key
		
		if (!pucFromBuf)
		{
			uiFromComponentLen = KEY_LOW_VALUE;
		}
		else
		{
			if (RC_BAD( rc = bufferIStream.openStream( 
				(const char *)pucFromBuf, uiFromBufLen)))
			{
				goto Exit;
			}

			uiFromComponentLen = uiFromSpaceLeft;
			bDataTruncated = FALSE;
			
			// Pass 0 for compare rules on non-text component.
			
			if (RC_BAD( rc = KYCollateValue( pucFromKey, &uiFromComponentLen,
									&bufferIStream, pColumn->eDataTyp,
									pIcd->uiFlags, 0,
									pIcd->uiLimit, NULL, NULL, 
									pIndex->uiLanguage, FALSE, FALSE,
									&bDataTruncated, NULL)))
			{
				goto Exit;
			}
			
			bufferIStream.closeStream();

			if (bDataTruncated)
			{
				*pbCanCompareOnKey = FALSE;
				if (pFromValue->eValType != SQL_BINARY_VAL)
				{
					
					// Couldn't fit the key into the remaining buffer space, so
					// we will just ask for all values.
					
					uiFromComponentLen = KEY_LOW_VALUE;
				}
				else
				{
				
					// Save the original data into pFromSearchKey so the comparison
					// routines can do a comparison on the full value if
					// necessary.
				
					if (RC_BAD( rc = pFromSearchKey->setBinary( uiKeyComponent,
												pucFromBuf, uiFromBufLen)))
					{
						goto Exit;
					}
					uiFromFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
				}
			}
		}

		// Set up the until key

		if (!pucUntilBuf)
		{
			uiUntilComponentLen = KEY_HIGH_VALUE;
		}
		
		// Little optimization here if both the from and until are pointing
		// to the same data - it is an EQ operator, and we don't need
		// to do the collation again if we have room in the until buffer
		// and we didn't truncate the from key.
		
		else if (pucUntilBuf == pucFromBuf &&
					uiFromComponentLen != KEY_LOW_VALUE &&
					uiUntilSpaceLeft >= uiFromComponentLen &&
					!(uiFromFlags & TRUNCATED_FLAG))
		{
			
			// If the truncated flag is not set in the from key, neither
			// should the search key flag be set.
			
			flmAssert( !(uiFromFlags & SEARCH_KEY_FLAG));
			if ((uiUntilComponentLen = uiFromComponentLen) != 0)
			{
				f_memcpy( pucUntilKey, pucFromKey, uiFromComponentLen);
			}
			
			// The "exclusive" flags better not have been set in this
			// case - because this should only be possible if the operator
			// was an EQ.
			
			flmAssert( !(uiFromFlags & EXCLUSIVE_GT_FLAG) &&
						  !(uiUntilFlags & EXCLUSIVE_LT_FLAG));
		}
		else
		{
			if (RC_BAD( rc = bufferIStream.openStream( 
				(const char *)pucUntilBuf, uiUntilBufLen)))
			{
				goto Exit;
			}
			uiUntilComponentLen = uiUntilSpaceLeft;
			bDataTruncated = FALSE;
			
			// Pass 0 for compare rule because it is a non-text piece.
			
			if (RC_BAD( rc = KYCollateValue( pucUntilKey, &uiUntilComponentLen,
									&bufferIStream, pColumn->eDataTyp,
									pIcd->uiFlags, 0,
									pIcd->uiLimit, NULL, NULL, 
									pIndex->uiLanguage, FALSE, FALSE,
									&bDataTruncated, NULL)))
			{
				goto Exit;
			}
			
			bufferIStream.closeStream();

			if (bDataTruncated)
			{
				*pbCanCompareOnKey = FALSE;
				if (pUntilValue->eValType != SQL_BINARY_VAL)
				{
					
					// Couldn't fit the key into the remaining buffer space, so
					// we will just ask for all values.
					
					uiUntilComponentLen = KEY_HIGH_VALUE;
				}
				else
				{
				
					// Save the original data into pUntilSearchKey so the comparison
					// routines can do a comparison on the full value if
					// necessary.
	
					if (RC_BAD( rc = pUntilSearchKey->setBinary( uiKeyComponent,
												pucUntilBuf, uiUntilBufLen)))
					{
						goto Exit;
					}
				}
				uiUntilFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
			}
		}
	}

	UW2FBA( (FLMUINT16)(uiFromComponentLen | uiFromFlags), pucFromKeyLenPos);
	UW2FBA( (FLMUINT16)(uiUntilComponentLen | uiUntilFlags), pucUntilKeyLenPos);
	
	// Set the FROM and UNTIL key length return values.

	uiFromKeyLen += 2;
	if (uiFromComponentLen != KEY_LOW_VALUE)
	{
		uiFromKeyLen += uiFromComponentLen;
		if (!(uiFromFlags & EXCLUSIVE_GT_FLAG))
		{
			*pbFromIncl = TRUE;
		}
	}
	uiUntilKeyLen += 2;
	if (uiUntilComponentLen != KEY_HIGH_VALUE)
	{
		uiUntilKeyLen += uiUntilComponentLen;
		if (!(uiUntilFlags & EXCLUSIVE_LT_FLAG))
		{
			*pbUntilIncl = TRUE;
		}
	}
	
Exit:

	*puiFromKeyLen = uiFromKeyLen;
	*puiUntilKeyLen = uiUntilKeyLen;

	return( rc);
}
コード例 #12
0
/****************************************************************************
Desc:	Commit (write out) all keys that have built up in the KREF table.
****************************************************************************/
RCODE F_Db::keysCommit(
	FLMBOOL			bCommittingTrans,
	FLMBOOL			bSortKeys)
{
	RCODE	rc = NE_SFLM_OK;
	
	// If the Kref has not been initialized, there is no
	// work to do.

	if (m_bKrefSetup)
	{
		F_INDEX *		pIndex = NULL;
		FLMUINT			uiTotal = m_uiKrefCount;
		KREF_ENTRY *	pKref;
		KREF_ENTRY **	pKrefTbl = m_pKrefTbl;
		FLMUINT			uiKrefNum;
		FLMUINT			uiLastIxNum;

		// We should not have reached this point if bAbortTrans is TRUE

		if( RC_BAD( m_AbortRc))
		{
			rc = RC_SET_AND_ASSERT( m_AbortRc);
			goto Exit;
		}

		// Sort the KREF table, if it contains more than one key.
		// This will sort all keys from the same index the same.

		if (uiTotal > 1 && bSortKeys)
		{
			processDupKeys( NULL);
			uiTotal = m_uiKrefCount;
		}

		// Loop through the KREF table outputting all keys

		uiLastIxNum = 0;
		for (uiKrefNum = 0; uiKrefNum < uiTotal; uiKrefNum++)
		{
			pKref = pKrefTbl [uiKrefNum];

			// See if the LFILE changed

			flmAssert( pKref->ui16IxNum);

			if (pKref->ui16IxNum != uiLastIxNum)
			{
				uiLastIxNum = pKref->ui16IxNum;
				pIndex = m_pDict->getIndex( uiLastIxNum);
			}

			// Flush the key to the index
			if (m_pKeyColl)
			{
				m_pKeyColl->addKey( this, pIndex, pKref);
			}
			else
			{
				if (RC_BAD(rc = refUpdate( pIndex, pKref, TRUE)))
				{
					if (rc != NE_SFLM_NOT_UNIQUE)
					{
						RC_UNEXPECTED_ASSERT( rc);
					}
					goto Exit;
				}
			}
		}
						
		if (bCommittingTrans)
		{
			krefCntrlFree();
		}
		else
		{
			// Empty the table out so we can add more keys in this trans.

			m_pKrefPool->poolReset( NULL, TRUE);
			m_uiKrefCount = 0;
			m_uiTotalKrefBytes = 0;
		}
	}

Exit:

	if( RC_BAD( rc))
	{
		setMustAbortTrans( rc);
	}

	return( rc);
}
コード例 #13
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE FTKAPI F_IOBufferMgr::getBuffer(
	FLMUINT				uiBufferSize,
	IF_IOBuffer **		ppIOBuffer)
{
	RCODE					rc = NE_FLM_OK;
	F_IOBuffer *		pIOBuffer = NULL;
	FLMBOOL				bMutexLocked = FALSE;
	
	f_assert( *ppIOBuffer == NULL);
	
	if( RC_BAD( m_completionRc))
	{
		rc = m_completionRc;
		goto Exit;
	}
	
	f_mutexLock( m_hMutex);
	bMutexLocked = TRUE;
	
Retry:

	if( m_pFirstAvail)
	{
		pIOBuffer = m_pFirstAvail;
		unlinkFromList( pIOBuffer);
		pIOBuffer->resetBuffer();
		f_assert( pIOBuffer->getBufferSize() == uiBufferSize);
	}
	else if( !m_uiTotalBuffers ||
		(m_uiTotalBufferBytes + uiBufferSize <= m_uiMaxBufferBytes &&
		m_uiTotalBuffers < m_uiMaxBuffers))
	{
		if( m_uiTotalBufferBytes + uiBufferSize > m_uiMaxBufferBytes)
		{
			rc = RC_SET_AND_ASSERT( NE_FLM_MEM);
			goto Exit;
		}

		if( (pIOBuffer = f_new F_IOBuffer) == NULL)
		{
			rc = RC_SET( NE_FLM_MEM);
			goto Exit;
		}
		
		if (RC_BAD( rc = pIOBuffer->setupBuffer( uiBufferSize, this)))
		{
			goto Exit;
		}
		
		m_uiTotalBufferBytes += uiBufferSize;
		m_uiTotalBuffers++;
	}
	else if( m_pFirstPending)
	{
	#if !defined( FLM_UNIX) && !defined( FLM_NLM)
		if( RC_BAD( rc = f_notifyWait( m_hMutex, m_hAvailSem, 
			NULL, &m_pAvailNotify)))
		{
			goto Exit;
		}
	#else
		F_IOBuffer *		pPending = m_pFirstPending;
		
		pPending->AddRef();
		f_mutexUnlock( m_hMutex);
		bMutexLocked = FALSE;
	
		rc = pPending->waitToComplete();
		
		f_mutexLock( m_hMutex);
		bMutexLocked = TRUE;
		
		pPending->Release( bMutexLocked);
		
		if( RC_BAD( rc))
		{
			goto Exit;
		}
	#endif
		
		goto Retry;
	}
	else
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_MEM);
		goto Exit;
	}
	
	pIOBuffer->AddRef();
	linkToList( &m_pFirstUsed, pIOBuffer);
	*ppIOBuffer = pIOBuffer;
	pIOBuffer = NULL;
	
Exit:

	if( pIOBuffer)
	{
		pIOBuffer->Release();
	}
	
	if( bMutexLocked)
	{
		f_mutexUnlock( m_hMutex);
	}
	
	return( rc);
}
コード例 #14
0
/****************************************************************************
Desc:	Thread that will delete block chains from deleted indexes and
		tables in the background.
****************************************************************************/
RCODE SQFAPI F_Database::maintenanceThread(
	IF_Thread *		pThread)
{
	RCODE					rc = NE_SFLM_OK;
	F_Database *		pDatabase = (F_Database *)pThread->getParm1();
	F_Db *				pDb;
	F_Row *				pRow;
	FLMUINT64			ui64MaintRowId;
	FLMBOOL				bStartedTrans;
	FLMBOOL				bShutdown;
	F_DbSystem *		pDbSystem;
	FSTableCursor *	pTableCursor;
	FLMUINT				uiBlkAddress;
	FLMBOOL				bIsNull;
	FLMUINT				uiBlocksToFree;
	FLMUINT				uiBlocksFreed;

Retry:
	
	rc = NE_SFLM_OK;
	pDb = NULL;
	pRow = NULL;
	bStartedTrans = FALSE;
	bShutdown = FALSE;
	pDbSystem = NULL;
	pTableCursor = NULL;

	if( (pDbSystem = f_new F_DbSystem) == NULL)
	{
		rc = RC_SET( NE_SFLM_MEM);
		goto Exit;
	}

	pThread->setThreadStatus( FLM_THREAD_STATUS_INITIALIZING);

	if( RC_BAD( rc = pDbSystem->internalDbOpen( pDatabase, &pDb)))
	{
		// If the file is being closed, this is not an error.

		if( pDatabase->getFlags() & DBF_BEING_CLOSED)
		{
			rc = NE_SFLM_OK;
			bShutdown = TRUE;
		}
		goto Exit;
	}
	pDbSystem->Release();
	pDbSystem = NULL;

	if ((pTableCursor = f_new FSTableCursor) == NULL)
	{
		rc = RC_SET( NE_SFLM_MEM);
		goto Exit;
	}

	for( ;;)
	{
		pThread->setThreadStatus( FLM_THREAD_STATUS_RUNNING);
		
		if( RC_BAD( rc = pDb->beginBackgroundTrans( pThread)))
		{
			goto Exit;
		}
		bStartedTrans = TRUE;
			
		pTableCursor->resetCursor();
		if (RC_BAD( rc = pTableCursor->setupRange( pDb, SFLM_TBLNUM_BLOCK_CHAINS,
												1, FLM_MAX_UINT64, FALSE)))
		{
			goto Exit;
		}
		
		// Free up to 25 blocks per transaction.
		
		uiBlocksToFree = 25;
		while (uiBlocksToFree)
		{

			if (RC_BAD( rc = pTableCursor->nextRow( pDb, &pRow, &ui64MaintRowId)))
			{
				if (rc != NE_SFLM_EOF_HIT)
				{
					RC_UNEXPECTED_ASSERT( rc);
					goto Exit;
				}
				rc = NE_SFLM_OK;
				break;
			}
			if (RC_BAD( rc = pRow->getUINT( pDb,
						SFLM_COLNUM_BLOCK_CHAINS_BLOCK_ADDRESS, &uiBlkAddress,
						&bIsNull)))
			{
				goto Exit;
			}
			if (bIsNull)
			{
				rc = RC_SET_AND_ASSERT( NE_SFLM_DATA_ERROR);
				goto Exit;
			}
			
			if( RC_BAD( rc = pDb->maintBlockChainFree(
				ui64MaintRowId, uiBlkAddress, uiBlocksToFree, 0, &uiBlocksFreed)))
			{
				goto Exit;
			}
			uiBlocksToFree -= uiBlocksFreed;
		}

		bStartedTrans = FALSE;
		if( RC_BAD( rc = pDb->commitTrans( 0, FALSE)))
		{
			goto Exit;
		}

		pThread->setThreadStatus( FLM_THREAD_STATUS_SLEEPING);
		f_semWait( pDatabase->m_hMaintSem, F_WAITFOREVER);
			
		if (pThread->getShutdownFlag())
		{
			bShutdown = TRUE;
			goto Exit;
		}
	}

Exit:

	pThread->setThreadStatus( FLM_THREAD_STATUS_TERMINATING);

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

	if( bStartedTrans)
	{
		pDb->abortTrans();
	}

	if (pDb)
	{
		pDb->Release();
		pDb = NULL;
	}

	if (!bShutdown)
	{
		flmAssert( RC_BAD( rc));
		f_sleep( 250);
		f_semSignal( pDatabase->m_hMaintSem);
		goto Retry;
	}

	return( rc);
}
コード例 #15
0
ファイル: ftkmfh.cpp プロジェクト: ajumi2/libflaim
/****************************************************************************
Desc: Opens an existing 64-bit file
****************************************************************************/
RCODE F_MultiFileHdl::openFile(
	const char *	pszPath)
{
	RCODE					rc = NE_FLM_OK;
	IF_FileSystem *	pFileSystem = f_getFileSysPtr();
	IF_DirHdl *			pDir = NULL;
	FLMUINT				uiTmp;
	FLMUINT				uiHighFileNum = 0;
	FLMUINT64			ui64HighOffset = 0;

	if( m_bOpen)
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
		goto Exit;
	}

	if( RC_BAD( pFileSystem->doesFileExist( pszPath)) ||
		!pFileSystem->isDir( pszPath))
	{
		rc = RC_SET( NE_FLM_IO_PATH_NOT_FOUND);
		goto Exit;
	}

	f_strcpy( m_szPath, pszPath);

	// Create the lock file

	if( RC_BAD( rc = createLockFile( m_szPath)))
	{
		goto Exit;
	}

	// Need to determine the current EOF

	if( RC_BAD( rc = pFileSystem->openDir( m_szPath, (char *)"*.64", &pDir)))
	{
		goto Exit;
	}

	// Find all data files to determine the EOF

	for( rc = pDir->next(); !RC_BAD( rc); rc = pDir->next())
	{
		if( RC_OK( getFileNum( pDir->currentItemName(), &uiTmp)))
		{
			if( uiTmp >= uiHighFileNum)
			{
				uiHighFileNum = uiTmp;
				ui64HighOffset = pDir->currentItemSize();
			}
		}
	}
	rc = NE_FLM_OK;

	m_ui64EOF = (((FLMUINT64)uiHighFileNum) * m_uiMaxFileSize) + ui64HighOffset;
	m_bOpen = TRUE;

Exit:

	if( pDir)
	{
		pDir->Release();
	}

	// Release the lock file

	if( RC_BAD( rc))
	{
		releaseLockFile( m_szPath, FALSE);
	}

	return( rc);
}
コード例 #16
0
ファイル: ftkmfh.cpp プロジェクト: ajumi2/libflaim
/****************************************************************************
Desc:	Creates a new 64-bit file with a unique, generated name
****************************************************************************/
RCODE F_MultiFileHdl::createUniqueFile(
	const char *		pszPath,					// Directory where the file is to be created
	const char *		pszFileExtension)		// Extension to be used on the new file.
{
	RCODE					rc = NE_FLM_OK;
	FLMUINT				uiCount;
	FLMBOOL				bModext = TRUE;
	FLMBOOL				bCreatedDir = FALSE;
	FLMUINT				uiBaseTime = 0;
	FLMBYTE				ucHighByte = 0;
	char					szDirName[ F_FILENAME_SIZE];
	char					szTmpPath[ F_PATH_MAX_SIZE];
	char					szBasePath[ F_PATH_MAX_SIZE];
	IF_FileSystem *	pFileSystem = f_getFileSysPtr();

	if( m_bOpen)
	{
		rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
		goto Exit;
	}

	if( !pszPath || pszPath[ 0] == '\0')
	{
#if defined( FLM_UNIX)
		f_strcpy( szBasePath, "./");
#elif defined( FLM_NLM)
		f_strcpy( szBasePath, "SYS:_NETWARE");
#else
		szBasePath[ 0] = '\0';
#endif
	}
	else
	{
		f_strcpy( szBasePath, pszPath);
	}

	if ((pszFileExtension) && (f_strlen( pszFileExtension) >= 3))
	{
		bModext = FALSE;
	}

	uiCount = 0;
	szDirName[ 0] = '\0';
	do
	{
		pFileSystem->pathCreateUniqueName( &uiBaseTime, szDirName, 
				pszFileExtension, &ucHighByte, bModext);

		f_strcpy( szTmpPath, szBasePath);
		pFileSystem->pathAppend( szTmpPath, szDirName);
		rc = pFileSystem->createDir( szTmpPath);
	} while ((rc != NE_FLM_OK) && (uiCount++ < 20));

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

	f_strcpy( m_szPath, szTmpPath);
	bCreatedDir = TRUE;

	// Create the lock file

	if( RC_BAD( rc = createLockFile( m_szPath)))
	{
		goto Exit;
	}

	// Initialize the EOF to 0 and set the state to open

	m_ui64EOF = 0;
	m_bOpen = TRUE;

Exit:

	// Release the lock file

	if( RC_BAD( rc))
	{
		releaseLockFile( m_szPath, TRUE);

		if( bCreatedDir)
		{
			(void)pFileSystem->removeDir( m_szPath);
		}
	}

	return( rc);
}
コード例 #17
0
ファイル: ftkmfh.cpp プロジェクト: ajumi2/libflaim
/****************************************************************************
Desc:	Removes a 64-bit file
****************************************************************************/
RCODE F_MultiFileHdl::deleteMultiFile(
	const char *	pszPath)
{
	RCODE					rc = NE_FLM_OK;
	IF_DirHdl *			pDir = NULL;
	char					szTmpPath[ F_PATH_MAX_SIZE];
	IF_FileSystem *	pFileSystem = f_getFileSysPtr();

	// Can't use this handle to delete something if we already
	// have a file open.

	if( m_bOpen)
	{

		// Can't jump to exit, because it calls releaseLockFile

		return( RC_SET_AND_ASSERT( NE_FLM_FAILURE));
	}

	if( RC_BAD( rc = pFileSystem->doesFileExist( pszPath)))
	{
		goto Exit;
	}

	if( !pFileSystem->isDir( pszPath))
	{
		// If the path specifies a single file rather than a
		// 64-bit directory, just go ahead and delete the file.

		rc = pFileSystem->deleteFile( pszPath);
		goto Exit;
	}

	if( RC_BAD( rc = createLockFile( pszPath)))
	{
		goto Exit;
	}

	if( RC_OK( pFileSystem->openDir( pszPath, "*.64", &pDir)))
	{
		// Remove all data files

		for( rc = pDir->next(); !RC_BAD( rc) ; rc = pDir->next())
		{
			pDir->currentItemPath( szTmpPath);
			f_assert( f_strstr( szTmpPath, ".64") != 0);
			(void)pFileSystem->deleteFile( szTmpPath);
		}

		pDir->Release();
		pDir = NULL;
		rc = NE_FLM_OK;
	}

	// Release and delete the lock file

	(void)releaseLockFile( pszPath, TRUE);

	// Remove the directory

	(void)pFileSystem->removeDir( pszPath);

Exit:

	(void)releaseLockFile( pszPath, FALSE);

	return( rc);
}
コード例 #18
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE F_Db::maintBlockChainFree(
	FLMUINT64		ui64MaintRowId,
	FLMUINT			uiStartBlkAddr,
	FLMUINT 			uiBlocksToFree,
	FLMUINT			uiExpectedEndBlkAddr,
	FLMUINT *		puiBlocksFreed)
{
	RCODE			rc = NE_SFLM_OK;
	FLMUINT		uiBlocksFreed = 0;
	FLMUINT		uiEndBlkAddr = 0;
	F_Row *		pRow = NULL;
	FLMUINT		uiRflToken = 0;

	// Make sure an update transaction is going and that a
	// non-zero number of blocks was specified

	if( getTransType() != SFLM_UPDATE_TRANS || !uiBlocksToFree)
	{
		rc = RC_SET_AND_ASSERT( NE_SFLM_ILLEGAL_OP);
		goto Exit;
	}

	m_pDatabase->m_pRfl->disableLogging( &uiRflToken);
	
	if( RC_BAD( rc = btFreeBlockChain( 
		this, NULL, uiStartBlkAddr, uiBlocksToFree, 
		&uiBlocksFreed, &uiEndBlkAddr, NULL)))
	{
		goto Exit;
	}

	flmAssert( uiBlocksFreed <= uiBlocksToFree);

	if (!uiEndBlkAddr)
	{
		if (RC_BAD( rc = deleteRow( SFLM_TBLNUM_BLOCK_CHAINS, ui64MaintRowId,
									FALSE)))
		{
			goto Exit;
		}
	}
	else
	{
		if (RC_BAD( rc = gv_SFlmSysData.pRowCacheMgr->retrieveRow( this,
										SFLM_TBLNUM_BLOCK_CHAINS, ui64MaintRowId,
										&pRow)))
		{
			goto Exit;
		}
		if (RC_BAD( rc = pRow->setUINT( this,
					SFLM_COLNUM_BLOCK_CHAINS_BLOCK_ADDRESS, uiEndBlkAddr)))
		{
			goto Exit;
		}
	}

	if (uiExpectedEndBlkAddr)
	{
		if (uiBlocksToFree != uiBlocksFreed ||
			 uiEndBlkAddr != uiExpectedEndBlkAddr)
		{
			rc = RC_SET_AND_ASSERT( NE_SFLM_DATA_ERROR);
			goto Exit;
		}
	}

	if (uiRflToken)
	{
		m_pDatabase->m_pRfl->enableLogging( &uiRflToken);
	}
	
	if( RC_BAD( rc = m_pDatabase->m_pRfl->logBlockChainFree( 
		this, ui64MaintRowId, uiStartBlkAddr, uiEndBlkAddr, uiBlocksFreed)))
	{
		goto Exit;
	}

	if (puiBlocksFreed)
	{
		*puiBlocksFreed = uiBlocksFreed;
	}

Exit:

	if (uiRflToken)
	{
		m_pDatabase->m_pRfl->enableLogging( &uiRflToken);
	}
	
	if (pRow)
	{
		pRow->ReleaseRow();
	}

	return( rc);
}
コード例 #19
0
RCODE FTKAPI f_mapPlatformError(
	FLMINT	iError,
	RCODE		defaultRc)
{
	switch (iError)
	{
		case 0:
		{
			return( NE_FLM_OK);
		}

		case ENOENT:
		{
			return( RC_SET( NE_FLM_IO_PATH_NOT_FOUND));
		}

		case EACCES:
		case EEXIST:
		{
			return( RC_SET( NE_FLM_IO_ACCESS_DENIED));
		}

		case EINVAL:
		{
			return( RC_SET_AND_ASSERT( NE_FLM_INVALID_PARM));
		}

		case EIO:
		{
			return( RC_SET( NE_FLM_IO_DISK_FULL));
		}

		case ENOTDIR:
		{
			return( RC_SET( NE_FLM_IO_DIRECTORY_ERR));
		}

#ifdef EBADFD
		case EBADFD:
		{
			return( RC_SET( NE_FLM_IO_BAD_FILE_HANDLE));
		}
#endif

#ifdef EOF
		case EOF:
		{
			return( RC_SET( NE_FLM_IO_END_OF_FILE));
		}
#endif
			
		case EMFILE:
		{
			return( RC_SET( NE_FLM_IO_NO_MORE_FILES));
		}

		default:
		{
			return( RC_SET( defaultRc));
		}
	}
}