Show MdMatch.c syntax highlighted
////////////////////////////////////////////////////////////////////////////
//
// CENS
//
// Copyright (c) 2003 The Regents of the University of California. All
// rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// - Neither the name of the University nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Contents: This file contains the module used to perform Tiny Diffusion's
// matching logic
//
// Purpose: The purpose of this functionality is to encapsulate the way in
// which attributes are matched for all of Tiny Diffusion in one
// module.
//
////////////////////////////////////////////////////////////////////////////
//
// $Id: MdMatch.c,v 1.3 2004/03/23 12:06:35 adparker Exp $
//
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// Commad: TdMatchI.oneWayMatch( )
//
// Purpose: This command takes 2 attribute arrays (a reference and a
// candidate) and performs one-way matching on them. In this
// process, success is acheived if the candidate attributes are
// equivalent to, or a superset of the reference attributes.
//
////////////////////////////////////////////////////////////////////////////
#include "Mdiff.h"
#include "assert.h"
result_t MdMatch_isClass(Mdiff_state_t *state,
int attr,
DiffAttr_t *p_Attr,
uint8_t num)
{
result_t tReturn = FAIL;
uint8_t i;
assert(p_Attr != NULL);
for (i = 0; i < num; ++i) {
if ((p_Attr[i].m_uiAttr == TD_ATTR_CLASS)
&& (p_Attr[i].m_iValue == attr)) {
tReturn = SUCCESS;
break;
}
}
return tReturn;
}
result_t MdMatch_oneWayMatch( Mdiff_state_t * state,
DiffAttr_t *p_pRefAttrs,
uint8_t p_uiNumRefAttrs,
DiffAttr_t *p_pCandidateAttrs,
uint8_t p_uiNumCandAttrs )
{
uint8_t uiRefIndex = 0;
uint8_t uiCandIndex = 0;
uint8_t uiSentinal = 0;
char *pRef = NULL;
char *pCand = NULL;
result_t tReturn = SUCCESS;
// Ensure that there is a reference array.
if ( NULL == p_pRefAttrs )
{
elog( LOG_NOTICE,
"%s [%d] - Unable to compare attributes with NULL reference array.\n",
__FILE__,
__LINE__ );
tReturn = FAIL;
}
// Ensure the that there is a candidate array.
else if ( NULL == p_pCandidateAttrs )
{
elog( LOG_NOTICE,
"%s [%d] - Unable to compare attributes with NULL condidate array.\n",
__FILE__,
__LINE__ );
tReturn = FAIL;
}
// If all is well...
else
{
pRef = ( char * ) p_pRefAttrs;
#ifdef _DEF_TD_DEBUG
elog( LOG_NOTICE,
"%s [%d] - Ref Attrs:\n",
__FILE__,
__LINE__ );
call TdMatchI.printAttrs( p_pRefAttrs,
p_uiNumRefAttrs );
elog( LOG_NOTICE,
"%s [%d] - Cand Attrs:\n",
__FILE__,
__LINE__ );
call TdMatchI.printAttrs( p_pCandidateAttrs,
p_uiNumCandAttrs );
#endif
// Loop over the reference array...
for ( uiRefIndex = 0;
uiRefIndex < p_uiNumRefAttrs;
uiRefIndex++ )
{
// Set our sentinal to indicate that we have not matched this attribute yet.
uiSentinal = 0;
if ( TD_ATTR_USER_BASE_BLOB <= ( ( DiffAttr_t * ) pRef )->m_uiAttr
&& TD_ATTR_USER_BASE_KEY > ( ( DiffAttr_t * ) pRef )->m_uiAttr )
{
pRef += ( ( DiffBlob_t * ) pRef )->m_uiLen;
uiSentinal = 1;
}
// Skip Classes, round, and Noop
else if ( (TD_ATTR_CLASS == ((DiffAttr_t*)pRef)->m_uiAttr)
||(TD_ATTR_OPP_ROUND == ((DiffAttr_t*)pRef)->m_uiAttr)
||(TD_ATTR_NOOP == ((DiffAttr_t*)pRef)->m_uiAttr))
{
pRef += sizeof( DiffAttr_t );
uiSentinal = 1;
}
// Skip Round
else
{
pCand = ( char * ) p_pCandidateAttrs;
// Loop over the candidate array until our sentinal is tripped, or we have
// finished the array.
for ( uiCandIndex = 0;
0 == uiSentinal
&& uiCandIndex < p_uiNumCandAttrs;
uiCandIndex++ )
{
// Skip Blobs
if ( TD_ATTR_USER_BASE_BLOB <= ( ( DiffAttr_t * ) pCand )->m_uiAttr
&& TD_ATTR_USER_BASE_KEY > ( ( DiffAttr_t * ) pCand )->m_uiAttr )
{
pCand += ( ( DiffBlob_t * ) pCand )->m_uiLen;
}
else
{
// If the reference and candidate attributes of this iteration are the same...
if ( ( ( DiffAttr_t * ) pRef )->m_uiAttr
== ( ( DiffAttr_t * ) pCand )->m_uiAttr )
{
// If the operation of the candidate defines its value (IS)...
if ( ( ( DiffAttr_t * ) pCand )->m_uiOp == TD_IS )
{
// We switch on the operation of the reference attribute so we know how
// to compare these 2 attributes.
switch( ( ( DiffAttr_t * ) pRef )->m_uiOp )
{
case TD_EQ:
// If these are equal, we are done with this iteration of the inner loop.
if ( ( ( DiffAttr_t * ) pCand )->m_iValue
== ( ( DiffAttr_t * ) pRef )->m_iValue )
{
// Set our sentinal so that the loop terminates and we know that
// we were successful.
uiSentinal = 1;
}
break;
case TD_LT:
// If the candidate is less than the reference,
// we are done with this iteration of the inner loop.
if ( ( ( DiffAttr_t * ) pCand )->m_iValue
< ( ( DiffAttr_t * ) pRef )->m_iValue )
{
// Set our sentinal so that the loop terminates and we know that
// we were successful.
uiSentinal = 1;
}
break;
case TD_GT:
// If the candidate is greater than the reference,
// we are done with this iteration of the inner loop.
if ( ( ( DiffAttr_t * ) pCand )->m_iValue
> ( ( DiffAttr_t * ) pRef )->m_iValue )
{
// Set our sentinal so that the loop terminates and we know that
// we were successful.
uiSentinal = 1;
}
break;
case TD_LE:
// If candidate is less than or equal to the reference,
// we are done with this iteration of the inner loop.
if ( ( ( DiffAttr_t * ) pCand )->m_iValue
<= ( ( DiffAttr_t * ) pRef )->m_iValue )
{
// Set our sentinal so that the loop terminates and we know that
// we were successful.
uiSentinal = 1;
}
break;
case TD_GE:
// If these are equal, we are done with this iteration of the inner loop.
if ( ( ( DiffAttr_t * ) pCand )->m_iValue
>= ( ( DiffAttr_t * ) pRef )->m_iValue )
{
// Set our sentinal so that the loop terminates and we know that
// we were successful.
uiSentinal = 1;
}
break;
case TD_NE:
// If these are unequal, we are done with this iteration of the inner loop.
if ( ( ( DiffAttr_t * ) pCand )->m_iValue
!= ( ( DiffAttr_t * ) pRef )->m_iValue )
{
// Set our sentinal so that the loop terminates and we know that
// we were successful.
uiSentinal = 1;
}
break;
case TD_ANY:
// Since there is any attribute at all, we are done with this
// iteration of the inner loop. Set our sentinal so that the
// loop terminates and we know that we were successful.
uiSentinal = 1;
break;
default:
elog( LOG_NOTICE,
"%s [%d] - Unknown matching operation: %u.\n",
__FILE__,
__LINE__,
( ( DiffAttr_t * ) pCand )->m_uiOp );
break;
}
}
else
{
uiSentinal = 1;
elog( LOG_NOTICE,
"%s [%d] - Got something that maybe a message type classifier (like INTEREST), or an invalid interest key: Ref Attr %u Candidate Attr %u.\n",
__FILE__,
__LINE__,
( ( DiffAttr_t * ) pRef )->m_uiOp,
( ( DiffAttr_t * ) pCand )->m_uiOp );
}
}
pCand += sizeof( DiffAttr_t );
}
}
if ( 1 != uiSentinal )
{
#ifdef _DEF_TD_DEBUG
elog( LOG_NOTICE,
"%s [%d] - No matching candidate attribute for ref [key : op : value]: [%u : %u : %d].\n",
__FILE__,
__LINE__,
( ( DiffAttr_t * ) pRef )->m_uiAttr,
( ( DiffAttr_t * ) pRef )->m_uiOp,
( ( DiffAttr_t * ) pRef )->m_iValue );
#endif
tReturn = FAIL;
break;
}
pRef += sizeof( DiffAttr_t );
}
}
if ( 0 == uiSentinal )
{
tReturn = FAIL;
}
}
return tReturn;
}
////////////////////////////////////////////////////////////////////////////
//
// Commad: TdMatchI.getAttrIndex( )
//
// Purpose: This command attempts to locate a specific attribute in an
// array. The command accepts a starting index so that the entire
// array need not be searched.
//
////////////////////////////////////////////////////////////////////////////
int16_t MdMatch_getAttrIndex( Mdiff_state_t * state,
uint8_t p_uiAttr,
uint16_t p_uiStartIndex,
DiffAttr_t *p_pAttrArray,
uint8_t p_uiNumAttrs )
{
uint8_t uiAttr = 0;
int16_t iReturn = -1;
int16_t iIndex = 0;
char *pAttr = NULL;
// Check to make sure we have a valid array.
if ( NULL == p_pAttrArray )
{
elog( LOG_NOTICE,
"%s [%d] - Unable to search NULL array.\n",
__FILE__,
__LINE__ );
}
// If all is well.
else
{
iIndex = 0;
// Loop over the attribute array...
for ( uiAttr = 0;
uiAttr < p_uiNumAttrs;
uiAttr++ )
{
// We traverse the array at a byte level to account for BLOBs.
pAttr = &( ( ( char * ) p_pAttrArray )[ iIndex ] );
// If we have found the target, set our return and break out
// of the loop.
if ( p_uiAttr == ( ( DiffAttr_t * ) pAttr )->m_uiAttr )
{
iReturn = iIndex;
break;
}
// Otherwise, if attribute is flagged as a BLOB...
else if ( TD_ATTR_USER_BASE_BLOB <= ( ( DiffAttr_t * ) pAttr )->m_uiAttr
&& TD_ATTR_USER_BASE_KEY > ( ( DiffAttr_t * ) pAttr )->m_uiAttr )
{
// We will need to jump through it (it may not be
// a regular sizeof( DiffAttr_t )'s length).
iIndex += ( ( DiffBlob_t * ) pAttr )->m_uiLen;
}
// Otherwise...
else
{
// We can just jump over this standard attribute.
iIndex += sizeof( DiffAttr_t );
}
}
}
// Return the default index, or a value (if we found it above).
return iReturn;
}
////////////////////////////////////////////////////////////////////////////
//
// Commad: TdMatchI.equal( )
//
// Purpose: This command performs and exact match check on 2 attribute
// arrays. Unlike the one-way matching, above, these 2 arrays
// must contain all the same attribute/operation/values (although
// they need not be in the same order). This command also
// skips over attributes that are of the value TD_ATTR_NOOP, so that
// irrelevant attributes are not constrained on.
//
////////////////////////////////////////////////////////////////////////////
result_t MdMatch_equal( Mdiff_state_t * state,
DiffAttr_t *p_pAttrArray1,
uint8_t p_uiNumAttrs1,
uint8_t p_uiNumNoOps1,
DiffAttr_t *p_pAttrArray2,
uint8_t p_uiNumAttrs2,
uint8_t p_uiNumNoOps2 )
{
uint8_t ui1 = 0;
uint8_t ui2 = 0;
result_t tReturn = SUCCESS;
// Make sure there is a valid array.
if ( NULL == p_pAttrArray1 )
{
elog( LOG_NOTICE,
"%s [%d] - Unable to use NULL array1 for comparison.\n",
__FILE__,
__LINE__ );
tReturn = FAIL;
}
// Make sure there is a valid array.
else if ( NULL == p_pAttrArray2 )
{
elog( LOG_NOTICE,
"%s [%d] - Unable to use NULL array2 for comparison.\n",
__FILE__,
__LINE__ );
tReturn = FAIL;
}
// Check to see if the attribute counts match (without including the
// number of noops). This is a sanity check before we begin looping
// over the arrays.
else if ( ( p_uiNumAttrs1 - p_uiNumNoOps1 )
!= ( p_uiNumAttrs2 - p_uiNumNoOps2 ) )
{
#ifdef _DEF_TD_DEBUG
elog( LOG_NOTICE,
"%s [%d] - Array 1 and array 2 are different lengths and cannot be equal (%u != %u ).\n",
__FILE__,
__LINE__,
p_uiNumAttrs1 - p_uiNumNoOps1,
p_uiNumAttrs2 - p_uiNumNoOps2 );
#endif
tReturn = FAIL;
}
// If all is well...
else
{
// Loop over the first array...
for ( ui1 = 0;
SUCCESS == tReturn
&& ui1 < p_uiNumAttrs1;
ui1++ )
{
// Set our default mode as failure.
tReturn = FAIL;
// If we encounter a BLOB we will fail. Tiny Diffusion doesn't currently
// support the comparison of BLOBs.
if ( TD_ATTR_USER_BASE_BLOB <= p_pAttrArray1[ ui1 ].m_uiAttr
&& TD_ATTR_USER_BASE_KEY > p_pAttrArray1[ ui1 ].m_uiAttr )
{
elog( LOG_NOTICE,
"%s [%d] - BLOB found in array1. Attr is %u.\n",
__FILE__,
__LINE__,
p_pAttrArray1[ ui1 ].m_uiAttr );
}
// If we encounter a no-op, then we consider this iteration as a success
// (since no-ops are irrelevant, we just continue on).
else if ( TD_ATTR_NOOP == p_pAttrArray1[ ui1 ].m_uiAttr )
{
tReturn = SUCCESS;
}
// Otherwise, if we have a valid attribute in our outter loop...
else
{
// Loop over the second attribute array.
for ( ui2 = 0;
ui2 < p_uiNumAttrs2;
ui2++ )
{
// If we encounter a BLOB here, we will break out of this, inner
// loops and fail the outter one. This is because tiny diffusion does
// not currently support the comparison of BLOBs.
if ( TD_ATTR_USER_BASE_BLOB <= p_pAttrArray2[ ui2 ].m_uiAttr
&& TD_ATTR_USER_BASE_KEY > p_pAttrArray2[ ui2 ].m_uiAttr )
{
elog( LOG_NOTICE,
"%s [%d] - BLOB found in array2. Attr is %u.\n",
__FILE__,
__LINE__,
p_pAttrArray2[ ui2 ].m_uiAttr );
// Breaking here will leave our sentenel in the FAIL mode and we
// will then exit the outter loop and fail the command.
break;
}
// If this attribute is valid, we check to see if it completely matches
// the outter array's attribute.
else if ( p_pAttrArray1[ ui1 ].m_uiAttr == p_pAttrArray2[ ui2 ].m_uiAttr
&& p_pAttrArray1[ ui1 ].m_uiOp == p_pAttrArray2[ ui2 ].m_uiOp
&& p_pAttrArray1[ ui1 ].m_iValue == p_pAttrArray2[ ui2 ].m_iValue )
{
// If we found a match, then all is well on this iteration.
tReturn = SUCCESS;
break;
}
}
}
}
}
return tReturn;
}
////////////////////////////////////////////////////////////////////////////
//
// Commad: TdMatchI.printAttrs( )
//
// Purpose: This command prints the attributes in the input array.
//
////////////////////////////////////////////////////////////////////////////
void MdMatch_printAttrs( Mdiff_state_t * state,
DiffAttr_t *p_pAttrs,
uint8_t p_uiLen )
{
uint8_t ui = 0;
// If we have valid input.
if ( NULL != p_pAttrs )
{
// Loop...
for ( ui = 0;
ui < p_uiLen;
ui++ )
{
// Stop processing on BLOBs.
if ( TD_ATTR_USER_BASE_BLOB <= p_pAttrs[ ui ].m_uiAttr
&& TD_ATTR_USER_BASE_KEY > p_pAttrs[ ui ].m_uiAttr )
{
break;
}
// If this is a valid attr, print it.
else
{
elog( LOG_NOTICE,
"[%u - %u - %d]\n",
p_pAttrs[ ui ].m_uiAttr,
p_pAttrs[ ui ].m_uiOp,
p_pAttrs[ ui ].m_iValue );
}
}
}
}
See more files for this project here