apiht.c
来自「用c/c++实现的一个CMPP API」· C语言 代码 · 共 1,753 行 · 第 1/4 页
C
1,753 行
pCellAddr = pHTMalloc( pHTLink ); if( pCellAddr == NULL ) { //ErrMsg( "Error When pHTMalloc\n " ); return SHMHT_NOSPACE; } memcpy( pCellAddr->pvKey, pvKeyAddr, nKeySize ); pCellAddr->nKeySize = nKeySize; memcpy( pCellAddr->pvPck, pvCellAddr, nCellSize ); pCellAddr->nPckSize = nCellSize; pCellAddr->tMsgTime = time(NULL); /*记录该消息的操作时间*/ if ( pHTLink->pBucket[nBucket] == NULL ) /* 首记录 作为第一个元素插入 */ { pCellAddr->pNext = pCellAddr; pCellAddr->pPrev = pCellAddr; pHTLink->pBucket[nBucket] = pCellAddr; } else /*作为第一个元素插入*/ { pFirstCell = pHTLink->pBucket[nBucket]; /*首指针*/ pPrevCell = pFirstCell->pPrev; pCellAddr->pNext = pFirstCell; pCellAddr->pPrev = pPrevCell; pPrevCell->pNext = pCellAddr; pFirstCell->pPrev = pCellAddr; pHTLink->pBucket[nBucket] = pCellAddr; } /* *记录进程ID和操作时间 */ //pHTLink->nMsgPid = getpid(); /*哈希表最后一条操作消息进程ID*/ //pHTLink->tMsgTime = time(NULL); /*哈希表中最后一条操作消息时间*/ return SHMHT_OK;}/**描述: 从一个桶中取出一个超时的记录*输入: pHLink HT表句柄,nBucket 桶的下标, nTimeOut 超过时间间隔 输出pvKeyAddr KEY值指针, nKeySize KEY长度, pvCellAddr 查找的包指针,nCellSize 包的长度。 如果pvKeyAddr, nKeySize , pvCellAddr, nCellSize 为空的话, 清除所有超时的包 *输出:>=0 成功 清除的包的个数, SHMHT_FAILED 失败 */int nGetABucketTimeOutCell( void* pvHTLink, int nBucket, int nTimeOut, void* pvKeyAddr, int nKeySize, void* pvCellAddr, int nCellSize ){ time_t tNowTime; recHTCell* pHTLink; recHashCell* pMarkCell; /*哨兵结点*/ recHashCell* pCell; /*变化的结点*/ int nSumPackCell = 0; /*清空的包的个数*/ int nRet; if( nTimeOut <= 0 || pvHTLink == NULL ) return SHMHT_FAILED; pHTLink = (recHTCell* )pvHTLink; if( nBucket <0 || nBucket >= pHTLink->nBucket ) return SHMHT_FAILED; while( 1 ) { /*该桶链表的哨兵,会因为nDelABukcetCell调用而变化*/ pMarkCell = pHTLink->pBucket[nBucket]; if( pMarkCell == NULL ) { break; } pCell = pMarkCell->pPrev; /*从后往前查,保证先进先出*/ /*具体的操作*/ tNowTime = time(NULL); if( tNowTime - pCell->tMsgTime > nTimeOut ) /*如果超时*/ { nRet = nDelABucketCell( pHTLink, nBucket, pCell, pvCellAddr, nCellSize, pvKeyAddr, nKeySize ); if ( nRet != SHMHT_OK ) { return SHMHT_FAILED ; } else { nSumPackCell ++; if ( pvCellAddr != NULL ) /*如果是要取出包*/ { return nSumPackCell; } } } else /*最早的都没有超过时间*/ { break; } }/* end of while */ return nSumPackCell;}/**note : 写日志函数待实现*/int nGetTimeOutACellApi( void* pvHTLink, int nTimeOut, void* pvKeyAddr, int nKeySize, void* pvCellAddr, int nCellSize ){ int nBucket; recHTCell* pHTLink; int nSumPackCell = 0; /*清空的包的个数*/ int nRet; if( nTimeOut <= 0 || pvHTLink == NULL) return SHMHT_FAILED; pHTLink = (recHTCell* )pvHTLink; for( nBucket=0; nBucket<pHTLink->nBucket; nBucket++ ) { nRet = nGetABucketTimeOutCell( pHTLink, nBucket, nTimeOut, pvKeyAddr, nKeySize, pvCellAddr, nCellSize ); if( nRet < 0 ) { ErrMsg( "Error When nGetABucketTimeOutCell\n" ); return SHMHT_OK; } if( pvCellAddr != NULL && nRet == 1 ) /*得到了一个要取出的包*/ { return 1; } nSumPackCell += nRet; } return nSumPackCell; }/**描述: 调试工具 显示出以该记录为首的链表的所有结点和内容。**/static void vListChain( FILE* fp, recHashCell* pCell ){ FILE* fD; int nSum; /*总的结点数目*/ recHashCell* pMarkCell ; /*哨兵结点*/ recHashCell* pVarCell; /*变化的结点*/ fD = ( fp == NULL )? stdout:fp ; if ( pCell == NULL ) { fprintf( fD, "Total Sum of Chain = %d\n\n", 0 ); fflush( fD ); return ; } nSum = 0; pMarkCell = pCell ; pVarCell = pCell; while( pMarkCell != NULL ) /*找了一遍*/ { /* fprintf( fD, "\tNo.%d pCur[x]=%x, pNext[x]=%x,pPrev[x]=%x\n", nSum, (int)pVarCell, (int)pVarCell->pNext, (int)pVarCell->pPrev ); fprintf( fD, "\tNo.%d pvPck[%d]=%s,pvKey[%d]=%s\n", nSum, pVarCell->nPckSize, (char*)pVarCell->pvPck, pVarCell->nKeySize, (char*)pVarCell->pvKey ); */ nSum++; pVarCell = pVarCell->pNext; if( pVarCell == pMarkCell ) break; } fprintf( fD, "Total Sum of Chain = %d\n\n", nSum ); fflush( fD ); return ;}#ifdef USEDSHAREMEMORYint nRemoveShmHT( int nShmId ){ if ( nShmId <= 0 ) return SHMHT_FAILED; return shmctl( nShmId, IPC_RMID, NULL );}#endif/*---------beg of memory hash function------------*//*--------------------------* *内存表的三个函数定义 * ---------------------------*//*描述: 初始化固定长度的HASH表内存输入: nKeySize KEY值的长度。 nPckSize 包体长度 nBucket 桶的个数, nPckCount 包的个数 *返回:HT表句柄 >0 成功 , NULL 失败*/void* pvInitMemHT( int nKeySize, int nPckSize, int nBucket, int nPckCount ){ int nRet; /*函数调用结果值*/ size_t sizeMemory; /*需要申请内存的大小*/ char* pvMemAddr; /*内存首地址*/ if ( nKeySize<= 0 || nPckSize <= 0 || nBucket <= 0 || nPckCount <= 0 ) return NULL; sizeMemory = /*连接控制信息内存区*/ sizeof( recHTCell ) + /*包内容内存区域*/ ( sizeof( recHashCell ) + nKeySize+nPckSize )* nPckCount + /*bucket指针数组的存贮空间*/ nBucket*sizeof( recHashCell* ) + /* 空闲队列的地址存贮空间*/ nPckCount*sizeof( void*) ; pvMemAddr = ( char *)malloc( sizeMemory ); if ( pvMemAddr == NULL ) /* operation failed. */ { ErrRet( "Error When malloc(%d)\n", (int)sizeMemory ); return NULL; } /* *注意:内存空间的的分配为: * 1整个的控制信息(recHTCell) 的空间 * 2Bucket的首指针数组空间 * 3空闲队列的地址数组空间 * 4整个包体的控制信息和内容空间 */ nRet = nInitHTLink( pvMemAddr, sizeMemory, pvMemAddr+sizeof( recHTCell )+ nBucket*sizeof(recHashCell*)+nPckCount*sizeof(void*), pvMemAddr+sizeMemory, nPckSize, nKeySize, nBucket, nPckCount ); if ( nRet != 0 ) { ErrMsg( "Error When nInitQLink, pvShmAddr[x] = %x\n", (int)pvMemAddr ); return NULL; } /*vDumpHT( NULL, pvMemAddr );*/ return pvMemAddr;}/**描述: 释放该HASH表的内存*输入: pvHTLink HT表句柄*输出: 无 *返回: SHMHT_OK 成功,SHMHT_FAILED 错误*/int nRemoveMemHT( void* pvHTLink ){ if( pvHTLink == NULL ) return SHMHT_FAILED; free( pvHTLink ); return SHMHT_OK;} /*描述: 复位HASH表内存输入: pvHLink HT表句柄, 输出: 返回: SHMHT_OK 成功,SHMHT_FAILED 错误*/int nResetMemHT( void* pvHTLink ){ if( pvHTLink == NULL ) return SHMHT_FAILED; return nResetShmHTApi( pvHTLink );}#ifdef USEDSHAREMEMORY/**描述: 内存分配函数 *输入参数:nShmKey , 关键字 lShmSize 大小, *输出参数: pnShmId 输出内存ID,为NULL不输出*返回值: > 0 成功,* Null 失败 */ #define MacShmFlag 0666static void* pShmMalloc( int nShmKey, long lShmSize, int* pnShmId ){ int nShmId; /*内存ID*/ void* pvShmAddr = NULL; /*内存首地址*/ struct shmid_ds StuShm_Ds; /*内存信息的数据结构*/ int nRet; nShmId = shmget( nShmKey, lShmSize, IPC_CREAT | MacShmFlag ); if ( nShmId < 0 ) { ErrRet( "Error When Shmget, nKey[x] = %x, Size[x] = %x\n", nShmKey, lShmSize ); nShmId = shmget( nShmKey, 0, IPC_CREAT | MacShmFlag ); if ( nShmId < 0 ) { ErrRet( "Error When Shmget, nKey[x] = %x, Size[x] = %x\n", nShmKey, 0 ); return NULL; } } /*为防止版本不对,在这里对大小进行严格的匹配*/ nRet = shmctl( nShmId, IPC_STAT, &StuShm_Ds ); if( nRet < 0 ) { ErrRet( "Error When shmctl, nShmId[x]=%x", nShmId ); return NULL; } if( StuShm_Ds.shm_segsz != lShmSize ) /*大小不对*/ { ErrMsg( "Error InitShm\nBecause Current Version Not Matching " "The Exist Version\nRequire Shmem Size[x]=%x, Existing" "Shmem Size[x]=%x\n" "Pls check the version or remove the share memory, KEY[x]=%d", lShmSize, StuShm_Ds.shm_segsz, nShmKey ); return NULL; } pvShmAddr = ( void *)shmat( nShmId, NULL, 0 ); if ( !pvShmAddr || (int)pvShmAddr == -1 ) /* operation failed. */ { ErrRet( "Error When shmat, nShmId = %d\n", nShmId ); return NULL; } if( pnShmId != NULL ) /*输出ID */ { *pnShmId = nShmId; } return pvShmAddr; } #endif // USEDSHAREMEMORY/*---------end of memory hash function------------*///#define SELFTEST#ifdef SELFTEST//#define MacSHMKEY 0xbbbb#define MacPckSize 512#define MacKeySize 8#define MacPckCount 1000#define MacBucket 100int main(){ int i; int nRet; char sKey[ MacKeySize+1 ]; char sPck[ MacPckSize+1 ]; void* pvHT; memset( sKey, 0, sizeof( sKey ) ); memset( sPck, 0, sizeof( sPck ) ); pvHT = pvInitMemHT( MacKeySize, MacPckSize, MacBucket, MacPckCount ); if( pvHT == NULL ) { printf( "Error when pvInitMemHT \n" ); return -1; } else { printf( "OK, Init, pvHT = %p\n", pvHT ); } for( i=0; i<10; ++i) { printf( "now i = %d\n", i ); snprintf( sKey, sizeof( sKey ), "%d", i ); snprintf( sPck, sizeof( sPck ), "%d", i ); nRet = nAddACellApi( pvHT, sKey, MacKeySize, sPck, MacPckSize ); printf( "nRet = %d after nAddACell\n", nRet ); } for( i=0; i<10; ++i) { printf( "now i = %d\n", i ); snprintf( sKey, sizeof( sKey ), "%d", i ); nRet = nDelACellApi( pvHT, sKey, MacKeySize, sPck, MacPckSize ); printf( "nRet = %d after nDelACell\n", nRet ); printf( "sPck = %s\n", sPck ); } return 0;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?