void saNameConcat(SaNameT* nameOut, const SaNameT *prefix, const char* separator, const SaNameT *suffix)
{
    unsigned int curpos = 0;

    if (prefix)
    {
        memcpy(nameOut->value, prefix->value, prefix->length);
        curpos += prefix->length;
    }
    if (separator)
    {
        int amt2Copy = CL_MIN((CL_MAX_NAME_LENGTH-1) - curpos,strlen(separator));
        if (amt2Copy) memcpy(&nameOut->value[curpos], separator, amt2Copy);
        curpos += amt2Copy;
    }
    if (suffix)
    {
        int amt2Copy = CL_MIN((CL_MAX_NAME_LENGTH-1) - curpos,suffix->length);
        if (amt2Copy) memcpy(&nameOut->value[curpos], suffix->value, amt2Copy);
        curpos += amt2Copy;
    }
    assert(curpos < CL_MAX_NAME_LENGTH);
    nameOut->value[curpos]=0;
    nameOut->length=curpos;
}
/*
 * Delete a chunk from the last section matching a data chunk of dataSize
 */
ClRcT clCacheEntryDataDelete(ClCachedCkptSvcInfoT *serviceInfo,
                             ClPtrT data,
                             ClUint32T dataSize)
{
    if (!serviceInfo->cache)
        return CL_ERR_NOT_INITIALIZED;

    ClUint32T *numberOfSections = (ClUint32T*)serviceInfo->cache;
    ClUint32T *sizeOfCache = (ClUint32T*)(numberOfSections + 1);
    ClCachedCkptDataT *ckptData = (ClCachedCkptDataT*)(sizeOfCache + 1);
    ClUint32T hdrSize = (ClUint8T*)ckptData - serviceInfo->cache;
    ClUint32T offset = 0;
    ClRcT rc = CL_OK;

    if(!data || !dataSize)
        return CL_ERR_INVALID_PARAMETER;

    if(!numberOfSections || !*numberOfSections)
        return CL_ERR_INVALID_STATE;

    if(dataSize > *sizeOfCache + hdrSize)
        return CL_ERR_NO_SPACE;

    for(ClUint32T i = 0; i < *numberOfSections; ++i)
    {
        ckptData = (ClCachedCkptDataT*) ( (ClUint8T*)ckptData + offset );
        offset += sizeof(*ckptData) + ckptData->dataSize;
    }

    if(!ckptData->data ||
            dataSize > ckptData->dataSize)
        return CL_ERR_NO_SPACE;

    ClUint32T dataChunks = ckptData->dataSize/dataSize;
    ClUint32T chunkSize = 0;

    offset = 0;
    for(ClUint32T i = 0; i < dataChunks; ++i)
    {
        chunkSize = CL_MIN(ckptData->dataSize - offset, dataSize);
        if(chunkSize != dataSize) break;
        if(!memcmp(ckptData->data + offset, data, chunkSize))
        {
            ckptData->dataSize -= chunkSize;
            *sizeOfCache -= chunkSize;
            if(offset < ckptData->dataSize)
            {
                memmove(ckptData->data + offset, ckptData->data + offset + chunkSize,
                        ckptData->dataSize - offset);
            }
            rc = CL_OK;
            goto found;
        }
        offset += chunkSize;
    }
    rc = CL_ERR_NOT_EXIST;

found:
    return rc;
}
示例#3
0
void clEvtUtilsNameCpy(SaNameT *pNameDst, const SaNameT *pNameSrc)
{

    CL_FUNC_ENTER();

    pNameDst->length = pNameSrc->length;
    memcpy(pNameDst->value, pNameSrc->value, CL_MIN((pNameSrc->length + 1), (ClInt32T)sizeof(pNameDst->value)));
    CL_FUNC_EXIT();
    return;
}
static
ClRcT
clPoolShrinkList(
    ClPoolHeaderT               *pPoolHeader,
    ClExtendedListT             *pList,
    const ClPoolShrinkOptionsT  *pShrinkOptions)
{
    ClExtendedPoolHeaderT *pExtendedPoolHeader = NULL;
    ClExtendedPoolHeaderT *pNext = NULL;
    ClUint32T numExtendedFreePools = 0;
    ClUint32T i;
    ClRcT rc = CL_OK;

    numExtendedFreePools = CL_POOL_EXTENDED_LIST_COUNT (pList);

    switch(pShrinkOptions->shrinkFlags)
    {
        case CL_POOL_SHRINK_DEFAULT:
        /*50 % of the free list*/
            numExtendedFreePools /= 2;
            break;
        case CL_POOL_SHRINK_ONE:
            numExtendedFreePools = CL_MIN (1, numExtendedFreePools);
            break;
        default:
        case CL_POOL_SHRINK_ALL:
            ;
        break;
    }

    if (numExtendedFreePools == 0)
    {
        CL_DEBUG_PRINT (CL_DEBUG_WARN, ("No free list to shrink\n"));
        goto out;
    }

    for(i = 0, pExtendedPoolHeader = pList->pHeadExtendedList; 
        i < numExtendedFreePools && pExtendedPoolHeader; 
        ++i)
    {
        pNext = pExtendedPoolHeader->pNext;
        CL_POOL_EXTENDED_LIST_DEQUEUE(pList, pExtendedPoolHeader);
        rc = clExtendedPoolDestroy (pPoolHeader, pExtendedPoolHeader);
        if(rc != CL_OK)
        {
            CL_DEBUG_PRINT (CL_DEBUG_ERROR,
                            ("Error in destroying extended pool\n"));
            goto out;
        }
        pExtendedPoolHeader = pNext;
    }

    out:
    return rc;
}
ClRcT
clLogInitDataDump(ClHandleDatabaseHandleT  hDb,
                  ClLogHandleT             hLog,
                  ClPtrT                   pCookie)
{
    ClRcT                 rc            = CL_OK;
    ClUint32T             bitmapLen     = 0;
    ClUint32T             i             = 0;
    ClLogClntEoDataT      *pClntEoEntry = NULL;
    ClLogInitHandleDataT  *pData        = NULL;
    ClCharT               ret[MAX_DEBUG_DISPLAY];
    ClCharT               p[MAX_DEBUG_DISPLAY];
    ClCharT               **ppRet       = (ClCharT**) pCookie;
    
    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogClntEoEntryGet(&pClntEoEntry);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clLogClntEoEntryGet(): rc[0x %x]", rc));
        return rc;
    }

    rc = clHandleCheckout(pClntEoEntry->hClntHandleDB, hLog, (void **) (&pData));
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clHandleCheckout(): rc[0x %x]", rc));
        return rc;
    }

    memset(ret, '\0', MAX_DEBUG_DISPLAY);
    memset(p, '\0', MAX_DEBUG_DISPLAY);
    
    if( CL_LOG_INIT_HANDLE == pData->type )
    {
        snprintf(ret, MAX_DEBUG_DISPLAY, "Init handle: %#llX\nCallbacks: %p\nBitmap:%p\n",
                hLog, (void *) pData->pCallbacks,
                (void *) pData->hStreamBitmap);

        bitmapLen = clBitmapLen(pData->hStreamBitmap);
        if( CL_OK != rc )
        {
            CL_LOG_DEBUG_ERROR(("clBitmapLen(): rc[0x %x]", rc));
            return rc;
        }

        snprintf(p, MAX_DEBUG_DISPLAY, "hStreamBitmap:\n");
        strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));
        
        for( i = 0; i < bitmapLen; i++ )
        {
            if( clBitmapIsBitSet(pData->hStreamBitmap, i, &rc) )
            {
                snprintf(p, MAX_DEBUG_DISPLAY, "%d ", 1);
                strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));
            }
            else
            {
                snprintf(p, MAX_DEBUG_DISPLAY, "%d ", 0);
                strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));
            }
        }

        bitmapLen = clBitmapLen(pData->hFileBitmap);
        if( CL_OK != rc )
        {
            CL_LOG_DEBUG_ERROR(("clBitmapLen(): rc[0x %x]", rc));
            return rc;
        }

        snprintf(p, MAX_DEBUG_DISPLAY, "\nhFileBitmap:\n");
        strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));

        for( i = 0; i < bitmapLen; i++ )
        {
            if( clBitmapIsBitSet(pData->hFileBitmap, i, &rc) )
            {
                snprintf(p, MAX_DEBUG_DISPLAY, "%d ", 1);
                strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));
            }
            else
            {
                snprintf(p, MAX_DEBUG_DISPLAY, "%d ", 0);
                strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));
            }
        }
    }

    rc = clHandleCheckin(pClntEoEntry->hClntHandleDB, hLog);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clHandleCheckin(): rc[0x %x]", rc));
        return rc;
    }

    *ppRet = (ClCharT*) clHeapAllocate(strlen(ret) + 1);
    if( NULL == *ppRet )
    {
        CL_LOG_DEBUG_ERROR(("clHeapAllocate(): rc[0x %x]", rc));
        return rc;
    }

    snprintf(*ppRet, strlen(ret)+1, ret);
    
    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
ClRcT
clLogStreamDataDump(ClHandleDatabaseHandleT  hDb,
                    ClLogStreamHandleT       hStream,
                    ClPtrT                   pCookie)
{
    ClRcT                   rc            = CL_OK;
    ClLogStreamHandleDataT  *pData        = NULL;
    ClLogClntStreamDataT    *pStreamInfo  = NULL;
    ClLogClntEoDataT        *pClntEoEntry = NULL;
    ClCharT                 **ppRet       = (ClCharT**) pCookie;
    ClCharT                 ret[MAX_DEBUG_DISPLAY];
    ClCharT                 p[MAX_DEBUG_DISPLAY];


    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogClntEoEntryGet(&pClntEoEntry);
    if( CL_OK != rc )
    {
        return rc;
    }

    rc = clHandleCheckout(hDb, hStream, (void **) (&pData));
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clHandleCheckout(): rc[0x %x]", rc));
        return rc;
    }

    memset(ret, '\0', MAX_DEBUG_DISPLAY);
    memset(p, '\0', MAX_DEBUG_DISPLAY);
    
    if( CL_LOG_STREAM_HANDLE == pData->type )
    {
        snprintf(ret, MAX_DEBUG_DISPLAY, "Stream handle: %#llX\nStreamNode: %p\n",
                hStream, (ClPtrT) pData->hClntStreamNode);

        
        rc = clCntNodeUserDataGet(pClntEoEntry->hClntStreamTable,
                                  pData->hClntStreamNode,
                                  (ClCntDataHandleT *) &pStreamInfo);
        if( CL_OK != rc )
        {
            CL_LOG_DEBUG_ERROR(("clCntNodeUserDataGet(): rc[0x %x]", rc));
            return rc;
        }

        snprintf(p,MAX_DEBUG_DISPLAY, "Stream Header: %p\n",
                (ClCharT *) pStreamInfo->pStreamHeader);
        strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));

        snprintf(p,MAX_DEBUG_DISPLAY, "Shm Name: %.*s", pStreamInfo->shmName.length,
                pStreamInfo->shmName.pValue);
        strncat(ret, p, CL_MIN(strlen(p), (MAX_DEBUG_DISPLAY-strlen(ret)-1)));
        
        rc = clHandleCheckin(hDb, hStream);
        if( CL_OK != rc )
        {
            CL_LOG_DEBUG_ERROR(("clHandleCheckin(): rc[0x %x]", rc));
            return rc;
        }

        *ppRet = (ClCharT*) clHeapAllocate(strlen(ret) + 1);
        if( NULL == *ppRet )
        {
            CL_LOG_DEBUG_ERROR(("clHeapAllocate(): rc[0x %x]", rc));
            return rc;
        }

        snprintf(*ppRet, strlen(ret)+1, ret);
    }

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
ClRcT
clLogClntStreamWriteWithHeader(ClLogClntEoDataT    *pClntEoEntry,
                               ClLogSeverityT      severity,
                               ClUint16T           serviceId,
                               ClUint16T           msgId,
                               const ClCharT             *pMsgHeader,
                               va_list             args,
                               ClCntNodeHandleT    hClntStreamNode)
{
    ClRcT                 rc              = CL_OK;
    ClLogClntStreamDataT  *pClntData      = NULL;
    ClLogStreamHeaderT    *pStreamHeader  = NULL;
    ClUint8T              *pStreamRecords = NULL;
    ClUint32T             nUnAcked        = 0;
    ClUint32T             nDroppedRecords = 0;
    ClUint8T              *pBuffer        = NULL;
    ClUint32T             recordSize = 0;

    CL_LOG_DEBUG_TRACE(("Enter"));
    CL_LOG_DEBUG_VERBOSE(("Severity: %d ServiceId: %hu MsgId: %hu CompId: %u",
                          severity, serviceId, msgId, pClntEoEntry->compId));

    rc = clCntNodeUserDataGet(pClntEoEntry->hClntStreamTable,  hClntStreamNode,
                              (ClCntDataHandleT *) &pClntData);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clCntNodeUserDataGet(): rc[0x %x]", rc));
        return rc;
    }
    pStreamHeader  = pClntData->pStreamHeader;
    pStreamRecords = pClntData->pStreamRecords;
#ifdef NO_SAF
    ClLogStreamKeyT         *pUserKey     = NULL;
    rc = clCntNodeUserKeyGet(pClntEoEntry->hClntStreamTable,
    		                 hClntStreamNode,
                             (ClCntKeyHandleT *) &pUserKey);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clCntNodeUserKeyGet(): rc[0x %x]", rc));
        return rc;
    }
    ClInt32T recSize= pClntData->recSize;
#define __UPDATE_RECORD_SIZE do {                  \
        if(recSize < nbytes )                   \
            recSize = nbytes;                   \
        recSize -= nbytes;                      \
        if(!recSize)                            \
            return CL_OK;                       \
    }while(0)
    ClUint16T streamId = 10;
    ClUint64T sequenceNum = pUserKey->sequenceNum;
    ClUint32T clientId = pClntEoEntry->clientId;
    ClUint8T* pRecord=clHeapAllocate(recSize);
    ClTimeT           timeStamp     = 0;
    ClUint8T          *pRecStart    = pRecord;
    ClUint16T         tmp           = 1;
    ClUint8T          endian        = *(ClUint8T *) &tmp;
    memset(pRecord, 0, recSize);
    if( CL_LOG_MSGID_PRINTF_FMT == msgId )
    {
        ClInt32T nbytes = 0;
        if(recSize < LOG_ASCII_MIN_REC_SIZE ) /* just a minimum record size taking care of the headers*/
        {
            printf("LOG record size has to be minimum [%d] bytes. Got [%d] bytes\n", LOG_ASCII_MIN_REC_SIZE, recSize);
            return CL_LOG_RC(CL_ERR_INVALID_PARAMETER);
        }
        /*
         * In ASCII logging, we dont need header, so just keeping only the
         * required fields
         */
        nbytes = snprintf((ClCharT *)pRecord, recSize, LOG_ASCII_HDR_FMT, endian, severity & 0x1f);
        pRecord += nbytes;
        __UPDATE_RECORD_SIZE;
        {
            ClCharT *pSeverity = (ClCharT *)clLogSeverityStrGet(severity);
            ClCharT c = 0;
            ClInt32T hdrLen = 0;
            ClInt32T len = 0;
            va_list argsCopy;
            ClCharT *pFmtStr ;
            va_copy(argsCopy, args);
            pFmtStr = va_arg(argsCopy, ClCharT *);
            if(pMsgHeader && pMsgHeader[0])
            {
                hdrLen = snprintf(&c, 1, "%s.%05lld : %6s) ",
                                  pMsgHeader, sequenceNum, pSeverity ? pSeverity : "DEBUG");
                if(hdrLen < 0) hdrLen = 0;
            }
            len = vsnprintf(&c, 1, pFmtStr, argsCopy);
            va_end(argsCopy);
            if(len < 0) len = 0;
            hdrLen = CL_MIN(hdrLen, recSize - LOG_ASCII_HDR_LEN - LOG_ASCII_DATA_LEN - 1);
            len = CL_MIN(len, recSize - LOG_ASCII_HDR_LEN - LOG_ASCII_DATA_LEN - hdrLen - 1);
            nbytes = snprintf((ClCharT*)pRecord, recSize - 1, LOG_ASCII_HDR_LEN_FMT, hdrLen);
            pRecord += nbytes;
            __UPDATE_RECORD_SIZE;
            nbytes = snprintf((ClCharT*)pRecord, recSize - 1, LOG_ASCII_DATA_LEN_DELIMITER_FMT, len);
            pRecord += nbytes;
            __UPDATE_RECORD_SIZE;
            if(pMsgHeader && pMsgHeader[0])
            {
                nbytes = snprintf((ClCharT*)pRecord, recSize - 1, "%s.%05lld : %6s) ",
                                  pMsgHeader, sequenceNum, pSeverity ? pSeverity : "DEBUG");
                if(nbytes < 0) nbytes = 0;
                pRecord += nbytes;
                __UPDATE_RECORD_SIZE;
            }
            pFmtStr = va_arg(args, ClCharT *);
            nbytes = vsnprintf((ClCharT*)pRecord, recSize - 1, pFmtStr, args);
            if(nbytes < 0) nbytes = 0;
        }
    }
static ClUint32T __differenceVectorGet(ClDifferenceBlockT *block, ClUint8T *data, ClOffsetT offset, 
                                       ClSizeT dataSize, ClDifferenceVectorT *differenceVector)
{
    ClUint32T i;
    ClMD5T *md5CurList = block->md5List;
    ClMD5T *md5List ;
    ClUint32T md5CurBlocks = block->md5Blocks;
    ClUint32T md5Blocks = 0;
    ClUint32T dataBlocks, sectionBlocks ;
    ClSizeT sectionSize;
    ClSizeT vectorSize = 0;
    ClSizeT lastDataSize = dataSize;
    ClUint8T *pLastData = NULL;
    ClInt32T lastMatch = -1;
    ClBoolT doMD5 = CL_FALSE;
    ClUint32T startBlock, endBlock;
    ClOffsetT startOffset, nonZeroOffset = 0;

    sectionSize = offset + dataSize;
    /*
     * First align to md5 block size
     */
    dataBlocks = ((dataSize + CL_MD5_BLOCK_MASK) & ~CL_MD5_BLOCK_MASK) >> CL_MD5_BLOCK_SHIFT;
    sectionBlocks = ((sectionSize + CL_MD5_BLOCK_MASK) & ~CL_MD5_BLOCK_MASK) >> CL_MD5_BLOCK_SHIFT;
    startOffset = offset & CL_MD5_BLOCK_MASK;
    startBlock = ( offset & ~CL_MD5_BLOCK_MASK ) >> CL_MD5_BLOCK_SHIFT; /* align the start block*/
    endBlock = sectionBlocks;

    md5Blocks = CL_MAX(sectionBlocks, md5CurBlocks);
    md5List = (ClMD5T *) clHeapCalloc(md5Blocks, sizeof(*md5List));
    CL_ASSERT(md5List != NULL);
    
    if(md5CurList)
        memcpy(md5List, md5CurList, md5CurBlocks);
    else 
    {
        md5CurList = md5List;
        md5CurBlocks = md5Blocks;
    }

    /*
     * If the specified vector blocks don't match the data blocks.
     * refill. Reset the md5 for offsetted writes considering its cheaper to 
     * just recompute the md5 for this block on a subsequent write to this block
     */
    if(differenceVector && differenceVector->md5Blocks && differenceVector->md5Blocks == dataBlocks)
    {
        memcpy(md5List + startBlock, differenceVector->md5List, sizeof(*md5List) * differenceVector->md5Blocks);
        /*
         *If data vector already specified, then just update the md5 list and exit.
         */
        if(differenceVector->numDataVectors) 
        {
            clLogTrace("DIFF", "MD5", "Difference vector already specified with md5 list of size [%d] "
                       "with [%d] difference data vectors", dataBlocks, differenceVector->numDataVectors);
            goto out_set;
        }
    }
    else doMD5 = CL_TRUE;

    data += offset;
    pLastData = data;
    
    /*
     * If we are going to allocate datavectors, free the existing set to be overridden
     * with a fresh set.
     */
    if(differenceVector && differenceVector->dataVectors)
    {
        clHeapFree(differenceVector->dataVectors);
        differenceVector->dataVectors = NULL;
        differenceVector->numDataVectors = 0;
    }

    nonZeroOffset |= startOffset;

    for(i = startBlock; i < endBlock; ++i)
    {
        ClSizeT c = CL_MIN(CL_MD5_BLOCK_SIZE - startOffset, dataSize);

        nonZeroOffset &= startOffset;

        if(doMD5)
        { 
            if(!startOffset)
                clMD5Compute(data, c, md5List[i].md5sum);
            else memset(&md5List[i], 0, sizeof(md5List[i]));
        }

        dataSize -= c;
        data += c;

        if(startOffset) 
            startOffset = 0;

        /*
         * Just gather the new md5 list if there is no vector to be accumulated
         */
        if(!differenceVector) continue;

        /*
         * Just gather md5s if we hit the limit for the current data size or if
         * we didnt have an md5 to start with
         */
        if(md5List == md5CurList)
        {
            if(lastMatch < 0) lastMatch = i;
            continue;
        }

        if(i < md5CurBlocks)
        {
            /*
             * Always store offsetted blocks in the difference vector. whose md5 wasnt computed.
             */
            if(!nonZeroOffset && memcmp(md5List[i].md5sum, md5CurList[i].md5sum, sizeof(md5List[i].md5sum)) == 0)
            {
                /*
                 * Blocks are the same. Skip the add for this block.
                 */
                clLogTrace("DIFF", "MD5", "Skipping copying block [%d] to replica", i);
                continue;
            }
        }
        else
        {
            if(lastMatch < 0)
            {
                lastMatch = i;
                pLastData = data - c;
                lastDataSize = dataSize + c;
            }
            continue;
        }

        clLogTrace("DIFF", "MD5", "Copying block [%d] to replica of size [%lld]", i, c);

        if(!(differenceVector->numDataVectors & 7 ) )
        {
            differenceVector->dataVectors = (ClDataVectorT*) clHeapRealloc(differenceVector->dataVectors,
                                                          sizeof(*differenceVector->dataVectors) * 
                                                          (differenceVector->numDataVectors + 8));
            CL_ASSERT(differenceVector->dataVectors != NULL);
            memset(differenceVector->dataVectors + differenceVector->numDataVectors, 0, 
                   sizeof(*differenceVector->dataVectors) * 8);
        }
        differenceVector->dataVectors[differenceVector->numDataVectors].dataBlock = i; /* block mismatched */
        differenceVector->dataVectors[differenceVector->numDataVectors].dataBase = data - c;
        differenceVector->dataVectors[differenceVector->numDataVectors].dataSize = c;
        ++differenceVector->numDataVectors;
        vectorSize += c;
    }

    CL_ASSERT(dataSize == 0);

    if(lastMatch >= 0 && differenceVector) /* impossible but coverity killer : Who knows! */
    {
        if(!(differenceVector->numDataVectors & 7))
        {
            differenceVector->dataVectors = (ClDataVectorT*) clHeapRealloc(differenceVector->dataVectors,
                                                          sizeof(*differenceVector->dataVectors) * 
                                                          (differenceVector->numDataVectors + 8));
            CL_ASSERT(differenceVector->dataVectors != NULL);
            memset(differenceVector->dataVectors + differenceVector->numDataVectors, 0, 
                   sizeof(*differenceVector->dataVectors) * 8);
        }
        clLogTrace("DIFF", "MD5", "Copying block [%d] to replica of size [%lld]", lastMatch, lastDataSize);
        differenceVector->dataVectors[differenceVector->numDataVectors].dataBlock = lastMatch;
        differenceVector->dataVectors[differenceVector->numDataVectors].dataBase = pLastData;
        differenceVector->dataVectors[differenceVector->numDataVectors].dataSize = lastDataSize;
        ++differenceVector->numDataVectors;
        vectorSize += lastDataSize;
    }

    if(differenceVector)
    {
        clLogTrace("DIFF", "MD5", "Vector has [%lld] bytes to be written. Skipped [%lld] bytes.",
                   vectorSize, sectionSize - vectorSize);
    }

    out_set:
    block->md5List = md5List;
    block->md5Blocks = md5Blocks;

    if(doMD5 && differenceVector)
    {
        clLogTrace("DIFF", "MD5", "Copying md5 list preloaded with [%d] blocks to the difference vector "
                   "with [%d] data difference vectors", dataBlocks, differenceVector->numDataVectors);
        if(differenceVector->md5List)
            clHeapFree(differenceVector->md5List);
        differenceVector->md5List = (ClMD5T*) clHeapCalloc(dataBlocks, sizeof(*differenceVector->md5List));
        CL_ASSERT(differenceVector->md5List != NULL);
        memcpy(differenceVector->md5List, md5List + startBlock, sizeof(*differenceVector->md5List) * dataBlocks);
        differenceVector->md5Blocks = dataBlocks;
    }

    if(md5CurList != md5List)
        clHeapFree(md5CurList);

    return sectionBlocks;
}
ClRcT clBackingStorageReadWalkFile(ClBackingStorageHandleT handle,
                                   ClBackingStorageCallbackT pCallback,
                                   ClPtrT pArg,
                                   ClUint32T readSize,
                                   ClPtrT pPrivateData)
{
    ClBackingStorageAttributesFileT *pAttr = (ClBackingStorageAttributesFileT *) pPrivateData;
    ClCharT data[0xffff+1];
    ClSizeT size = 0;
    ClOffsetT curOffset = 0;
    struct stat st = {0};
    ClRcT rc = CL_BACKING_STORAGE_RC(CL_ERR_LIBRARY);

    if(fstat(pAttr->fd, &st) < 0)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                   "stat error [%s]", strerror(errno));
        goto out;
    }
    if(!st.st_size)
    {
        rc = CL_OK;
        clLogWarning(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                     "File [%s] size is empty", pAttr->baseAttr.location);
        goto out;
    }
    curOffset = lseek(pAttr->fd, 0, SEEK_CUR);
    if(curOffset < 0)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                   "lseek error [%s]", strerror(errno));
        goto out;
    }
    if(lseek(pAttr->fd, 0, SEEK_SET) < 0)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                   "lseek error [%s]", strerror(errno));
        goto out;
    }

    size = st.st_size;
    while(size > 0)
    {
        ClInt32T err = 0;
        ClCharT *pData = data;
        ClInt32T chunkSize = CL_MIN((ClInt32T)sizeof(data), size);
        ClUint32T bytes = 0;

        if(readSize)
        {
            if(size < readSize)
            {
                clLogError(CL_LOG_AREA_BACKING_STORAGE,
                           CL_LOG_CONTEXT_READW_FILE,
                           "Read walk error. Chunksize doesnt match readsize [%d]",
                           chunkSize);
                goto out_restore;
            }
            chunkSize = readSize;
            pData = (ClCharT*) clHeapAllocate(chunkSize);
            if(!pData)
            {
                clLogError(CL_LOG_AREA_BACKING_STORAGE, 
                           CL_LOG_CONTEXT_READW_FILE,
                           "No memory");
                goto out_restore;
            }
        }
        while(chunkSize > 0)
        {
            err = read(pAttr->fd, pData+bytes, chunkSize);
            if(err < 0)
            {
                clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                           "read error [%s]", strerror(errno));
                if(pData != data)
                {
                    clHeapFree(pData);
                }
                goto out_restore;
            }
            bytes += err;
            chunkSize -= err;
        }

        rc = pCallback(handle, (ClPtrT)pData, bytes, pArg);
        if(rc != CL_OK)
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                       "readwalk callback error [%#x]", rc);
            if(pData != data)
            {
                clHeapFree(pData);
            }
            goto out_restore;
        }
        size -= bytes;
    }
    rc = CL_OK;

    out_restore:
    lseek(pAttr->fd, curOffset, SEEK_SET);

    out:
    return rc;
}
ClRcT clBackingStorageReadVectorFile(ClBackingStorageHandleT handle, struct iovec **ppIOVec, ClUint32T *pNumVectors, ClOffsetT offset,  ClUint32T readSize, ClPtrT pPrivateData)
{
    ClBackingStorageAttributesFileT *pAttr = (ClBackingStorageAttributesFileT *) pPrivateData;
    ClRcT rc = CL_BACKING_STORAGE_RC(CL_ERR_LIBRARY);
    struct iovec *pIOVec = NULL;
    ClUint32T numVectors = 0;
    ClSizeT size = 0, n = 0;
    ClInt32T err =0 , i = 0;
    struct stat st;
    ClCharT **ppDataBlocks = NULL;
    ClOffsetT curOffset = 0;
    ClInt32T whence = SEEK_SET;
    ClInt32T lastBatchStart = 0;

    *ppIOVec = NULL;
    *pNumVectors = 0;

    if(readSize > 0x7fff)
    {
        rc = CL_BACKING_STORAGE_RC(CL_ERR_INVALID_PARAMETER);
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE, 
                   "Invalid readSize [%d]", readSize);
        goto out;
    }

    if(fstat(pAttr->fd, &st))
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE, "stat error [%s]", strerror(errno));
        goto out;
    }

    size = st.st_size;
    if(!size)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE, 
                   "File [%s] empty", pAttr->baseAttr.location);
        goto out;
    }
    if(offset != (ClOffsetT)-1)
    {
        curOffset = lseek(pAttr->fd, 0, SEEK_CUR);
        if(curOffset < 0)
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE,
                       "lseek save error [%s]", strerror(errno));
            goto out;
        }
        if(offset < 0 )
        {
            size = -offset;
            whence = SEEK_END;
        }
        else
        {
            size -= offset;
        }
        if(lseek(pAttr->fd, offset, whence) < 0)
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE,
                       "lseek error [%s]", strerror(errno));
            goto out;
        }
    }

    if(readSize && (size % readSize))
    {
        rc = CL_BACKING_STORAGE_RC(CL_ERR_INVALID_PARAMETER);
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE, 
                   "File size [%lld] not a multiple of readsize [%d]",
                   size, readSize);
        goto out_restore;
    }

    if(!readSize)
    {
        readSize =  0x3fff+1;
    }

    rc = CL_BACKING_STORAGE_RC(CL_ERR_NO_MEMORY);
    numVectors = size/readSize;
    if(( size % readSize))
        ++numVectors;

    pIOVec = (struct iovec*) clHeapCalloc(numVectors, sizeof(*pIOVec));
    if(!pIOVec)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE, "No memory");
        goto out_restore;
    }
    ppDataBlocks = (ClCharT**) clHeapCalloc(numVectors, sizeof(*ppDataBlocks));
    if(!ppDataBlocks)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE, "No memory");
        goto out_restore;
    }

    for(i = 0; (i < (ClInt32T) numVectors) && (size > 0);++i)
    {
        ClUint32T bytes = CL_MIN(readSize, size);
        ppDataBlocks[i] = (ClCharT*) clHeapAllocate(bytes);
        if(!ppDataBlocks[i])
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE, "No memory");
            goto out_free;
        }
        pIOVec[i].iov_base = ppDataBlocks[i];
        pIOVec[i].iov_len = bytes;
        size -= readSize;
        n += readSize;
        if((i+1 >= (ClInt32T)numVectors) || (readSize >=  0x3fff) || (n >= 0x3fff) )
        {
            if(n >= 0x3fff)
            {
                n = 0;
            }
            err = readv(pAttr->fd, &pIOVec[lastBatchStart], i-lastBatchStart+1);
            if(err < 0)
            {
                clLogError(CL_LOG_AREA_BACKING_STORAGE, 
                           CL_LOG_CONTEXT_READV_FILE,
                           "readv error [%s]", strerror(errno));
                goto out_restore;
            }
            lastBatchStart = i+1;
        }
    }

    *ppIOVec = pIOVec;
    *pNumVectors = numVectors;
    rc = CL_OK;
    goto out;

    out_restore:
    if(offset != (ClOffsetT)-1)
    {
        if(lseek(pAttr->fd, curOffset, SEEK_SET) < 0)
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READV_FILE,
                       "lseek error  restoring back [%s]", strerror(errno));
        }
    }
    out_free:
    {
        ClInt32T j;
        for(j = 0; j < i; ++j)
            clHeapFree(ppDataBlocks[j]);
    }
    if(pIOVec)
        clHeapFree(pIOVec);
    if(ppDataBlocks)
        clHeapFree(ppDataBlocks);

    out:
    return rc;
}
ClRcT clBackingStorageWriteFile(ClBackingStorageHandleT handle, ClPtrT pData, ClUint32T size, ClOffsetT offset, ClPtrT pPrivateData)
{
    ClBackingStorageAttributesFileT *pAttr = (ClBackingStorageAttributesFileT *) pPrivateData;
    ClRcT  rc = CL_OK;
    ClInt32T err = 0;
    ClOffsetT curOffset = 0;
    ClInt32T whence = SEEK_SET;

    rc = CL_BACKING_STORAGE_RC(CL_ERR_LIBRARY);
    if( offset != (ClOffsetT)-1)
    {
        curOffset = lseek(pAttr->fd, 0, SEEK_CUR);
        if(curOffset < 0 )
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, 
                       "File lseek save error [%s]", strerror(errno));
            goto out;
        }
        if(offset < 0)
        {
            whence = SEEK_END;
            size = -offset;
        }
        else
        {
            size -= offset;
        }
        if(lseek(pAttr->fd, offset, whence) < 0)
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "File lseek error [%s]", strerror(errno));
            goto out;
        }
    }

    while(size > 0 )
    {
        ClInt32T n = CL_MIN(size, 32768);
        err = write(pAttr->fd, pData, n);
        if(err < 0 )
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "Write error [%s]", strerror(errno));
            if(offset != (ClOffsetT)-1)
            {
                if(lseek(pAttr->fd, curOffset, SEEK_SET) < 0)
                {
                    clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "lseek error [%s] restoring back offset", strerror(errno));
                }
            }
            goto out;
        }
        if(err != n)
        {
            clLogWarning(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "Write wrote [%d] bytes. Expected [%d] bytes", err, n);
        }
        size -= err;
        pData = (ClPtrT)((ClUint8T*)pData + err);
    }

    rc = CL_OK;
    out:
    return rc;
    
}
static ClRcT clEoClientNotification(ClIocNotificationT *notification)
{
    ClUint32T i;
    ClIocNotificationIdT event;
    ClIocNodeAddressT node;
    ClIocPortT port;
    ClEoCallbackRecT *pMatchedRecords = NULL;
    ClUint32T numMatchedRecs = 0;
    ClUint32T numRecs = 0;
    ClIocAddressT address = {{0}};

    if(!notification) return CL_EO_RC(CL_ERR_INVALID_PARAMETER);
    event = ntohl(notification->id);
    node = ntohl(notification->nodeAddress.iocPhyAddress.nodeAddress);
    port = ntohl(notification->nodeAddress.iocPhyAddress.portId);

    if(event == CL_IOC_NODE_ARRIVAL_NOTIFICATION ||
       event == CL_IOC_NODE_LINK_UP_NOTIFICATION ||
       event == CL_IOC_NODE_LEAVE_NOTIFICATION ||
       event == CL_IOC_NODE_LINK_DOWN_NOTIFICATION) 
    {
        port = 0;
    }

    address.iocPhyAddress.nodeAddress = node;
    address.iocPhyAddress.portId = port;

    /*
     * db numRecs could change behind our back. Hence pre-fetching it
     * to have temp db allocations without the lock.
     */
    clOsalMutexLock(&gpCallbackDb.lock);
    numRecs = gpCallbackDb.numRecs;
    clOsalMutexUnlock(&gpCallbackDb.lock);

    /*
     * Better to allocate without the lock. to reduce lock
     * granularity and give scope for further client registrations
     * in this window.
     */
    pMatchedRecords = clHeapAllocate(sizeof(*pMatchedRecords) * numRecs);
    if(!pMatchedRecords)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Memory allocation error\n"));
        return CL_EO_RC(CL_ERR_NO_MEMORY);
    }
    
    clOsalMutexLock(&gpCallbackDb.lock);
    
    numRecs = CL_MIN(gpCallbackDb.numRecs, numRecs);
    
    for(i = 0; i < numRecs; i++)
    {
        if(gpCallbackDb.pDb[i] != NULL &&
           (gpCallbackDb.pDb[i]->node == node || gpCallbackDb.pDb[i]->node == CL_IOC_BROADCAST_ADDRESS) &&
           (!port || gpCallbackDb.pDb[i]->port == port || !gpCallbackDb.pDb[i]->port)
           )
        {
            memcpy(&pMatchedRecords[numMatchedRecs++],
                   gpCallbackDb.pDb[i],
                   sizeof(*pMatchedRecords));
        }
    }

    clOsalMutexUnlock(&gpCallbackDb.lock);

    for(i = 0; i < numMatchedRecs; ++i)
    {
        pMatchedRecords[i].pFunc(event, pMatchedRecords[i].pArg, &address);
    }
    
    clHeapFree(pMatchedRecords);

    return CL_OK;
}
ClRcT clNodeCacheUpdate(ClIocNodeAddressT nodeAddress, ClUint32T version, ClUint32T capability, SaNameT *nodeName)
{
    ClRcT   rc = CL_OK;
    ClNodeCacheEntryT *entry;

    if(nodeAddress >= CL_IOC_MAX_NODES) return CL_ERR_INVALID_PARAMETER;

    rc = clOsalSemLock(gClNodeCacheSem);
    if (rc != CL_OK)
    {
        clLogError("CACHE", "SET", "Cannot update node cache; error taking lock");        
        return rc;
    }
    

    if(!gpClNodeCache)
    {
        clOsalSemUnlock(gClNodeCacheSem);
        clLogError("CACHE", "SET", "Cannot update node cache; not initialized");        
        return CL_ERR_NOT_INITIALIZED;
    }

    if(!CL_NODE_MAP_TEST(CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->nodeMap, nodeAddress))
    {
        CL_NODE_MAP_SET(CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->nodeMap, nodeAddress);
        CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->currentNodes += 1;
    }

    entry = &CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[nodeAddress];
    if(version)
        entry->version = version;
    if(capability)
        entry->capability = capability;
    if(nodeName)
    {
        entry->nodeName[0] = 0;
        strncat(entry->nodeName, (const ClCharT*)nodeName->value, CL_MIN(nodeName->length, sizeof(entry->nodeName)-1));
    }
    
    /*
     * Update node min version/address.
     */
    if(version && 
       (!CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->minVersion || 
        version < CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->minVersion))
    {
        CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->minVersion = version;
        CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->minVersionNode = nodeAddress;
        gClMinVersion = version;
        gClMinVersionNode = nodeAddress;
    }

    if (1)
    {
        ClNodeCacheEntryT temp;
        memcpy(&temp,entry,sizeof(ClNodeCacheEntryT));
        
        clOsalSemUnlock(gClNodeCacheSem);
        /* I do not want to log inside the node cache sem lock because logging can block, esp if its going to stdout */
        clLogInfo("CACHE", "SET", "Updating node cache entry for node [%d: %s] with version [%#x], capability [%#x] (%s,%s,%s)",
                nodeAddress, temp.nodeName, temp.version, temp.capability, CL_NODE_CACHE_LEADER_CAPABILITY(temp.capability) ? "LEADER":"_", CL_NODE_CACHE_SC_CAPABILITY(temp.capability) ? "Controller" : "_", CL_NODE_CACHE_SC_PROMOTE_CAPABILITY(temp.capability) ? "Controller-promotable" : "_" );
    }
    
    return CL_OK;
}