📄 scorder.cxx
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
Module Name:
scorder.cxx
Abstract:
Small client -- implementation of message ordering class
--*/
#include <sc.hxx>
#include <scorder.hxx>
#include <svsutil.hxx>
#include <scqueue.hxx>
#include <scqman.hxx>
#include <scsman.hxx>
#include <sccomp.hxx>
unsigned int ScSequenceCollection::Hash (GUID *pguid, GUID *pOtherGuid) {
unsigned int uiRes = 0;
unsigned int *p1 = (unsigned int *)pguid;
unsigned int *p2 = (unsigned int *)&pOtherGuid;
for (int i = 0 ; i < 4 ; ++i, ++p1, ++p2)
uiRes += (*p1) ^ (*p2);
return uiRes % SCSEQUENCE_HASH_BUCKETS;
}
unsigned int ScSequenceCollection::Hash (WCHAR *sz) {
int uiRes = 0;
for ( ; ; ) {
if (sz[0] == '\0')
break;
if (sz[1] == '\0') {
uiRes += towupper (sz[0]);
break;
}
uiRes += towupper (sz[0]) ^ towupper (sz[1]);
sz += 2;
}
return uiRes % SCSEQUENCE_HASH_BUCKETS;
}
unsigned int ScSequenceCollection::Hash (GUID *pGuid) {
unsigned int uiRes = 0;
unsigned int *p1 = (unsigned int *)pGuid;
uiRes += p1[0] ^ p1[3] + p1[1] ^ p1[2];
return uiRes % SCSEQUENCE_HASH_BUCKETS;
}
ScOrderSeq *ScSequenceCollection::HashOrderSequence (ScQueue *pQueue, GUID *pguidStreamId, GUID *pguidQueueName, GUID *pguidOrderAckName, unsigned int uiSequenceFlags) {
// SVSUTIL_ASSERT (pQueue->qp.bIsIncoming);
// SVSUTIL_ASSERT (pQueue->qp.bTransactional);
int iPos = Hash (pguidStreamId, pguidQueueName);
ScOrderSeq *pSeq = pSeqBuckets[iPos];
while (pSeq) {
//
// Same server can be known by different names, only guid equivalence is to be tested...
//
if (((! pQueue) || (pSeq->p->guidQ == pQueue->qp.guid)) && (pSeq->p->guidStreamId == *pguidStreamId) && (pSeq->p->guidQueueName == *pguidQueueName)) {
return pSeq;
}
pSeq = pSeq->pNextHash;
}
if (! pguidOrderAckName)
return NULL;
pSeq = (ScOrderSeq *)svsutil_GetFixed (pfmOrderSeq);
if (! pSeq)
return NULL;
pSeq->p = PersistBlock();
if (! pSeq->p) {
svsutil_FreeFixed (pSeq, pfmOrderSeq);
return NULL;
}
pSeq->pQueue = pQueue;
pSeq->fActive = FALSE;
pSeq->ipAddr.S_un.S_addr = INADDR_NONE;
pSeq->pPrevActive = NULL;
pSeq->pNextActive = NULL;
pSeq->pNextHash = pSeqBuckets[iPos];
pSeqBuckets[iPos] = pSeq;
pSeq->p->guidQ = pQueue->qp.guid;
pSeq->p->guidQueueName = *pguidQueueName;
pSeq->p->guidStreamId = *pguidStreamId;
pSeq->p->guidOrderAck = *pguidOrderAckName;
pSeq->p->llCurrentSeqID = 0;
pSeq->p->uiCurrentSeqN = 0;
pSeq->p->uiLastAccessS = 0;
pSeq->p->uiBlockFlags = uiSequenceFlags;
return pSeq;
}
int ScSequenceCollection::SaveSequence (ScOrderSeq *pSeq) {
SVSUTIL_ASSERT (pSeq->pQueue);
SVSUTIL_ASSERT (pSeq->p);
int iCluster = FindCluster (pSeq->p);
if (iCluster < 0)
return FALSE;
pSeq->p->uiLastAccessS = scutil_now ();
if ((! pSeq->fActive) && pSeq->p->llCurrentSeqID) {
SVSUTIL_ASSERT (pSeq->p->uiCurrentSeqN);
SVSUTIL_ASSERT(! pSeq->pPrevActive);
SVSUTIL_ASSERT(! pSeq->pNextActive);
pSeq->fActive = TRUE;
pSeq->pNextActive = pSeqActive;
pSeqActive = pSeq;
if (pSeq->pNextActive)
pSeq->pNextActive->pPrevActive = pSeq;
else // Only start pulsing on the first active event...
svsutil_SetAttrTimer (gMem->pTimer, (SVSHandle)hSequencePulse, SCSEQUENCE_R_ACKSEND * gMachine->uiOrderAckScale * 1000);
}
ppClusters[iCluster]->iDirty = TRUE;
return FlushBackup ();
}
void ScSequenceCollection::DeleteQueue (ScQueue *pQueue) {
SVSUTIL_ASSERT (gMem->IsLocked());
if (! (pQueue->qp.bIsIncoming && pQueue->qp.bTransactional))
return;
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Deleting sequences associated with %s...\n", pQueue->lpszFormatName);
#endif
for (int i = 0 ; i < SCSEQUENCE_HASH_BUCKETS ; ++i) {
ScOrderSeq *pSeq = pSeqBuckets[i];
ScOrderSeq *pParentSeq = NULL;
while (pSeq) {
SVSUTIL_ASSERT (pSeq->p->uiLastAccessS);
if (pSeq->pQueue == pQueue) {
SVSUTIL_ASSERT (pSeq->p->guidQ == pQueue->qp.guid);
if (pSeq->fActive) {
if (pSeq == pSeqActive) {
pSeqActive = pSeq->pNextActive;
if (pSeqActive)
pSeqActive->pPrevActive = NULL;
} else {
SVSUTIL_ASSERT (pSeq->pPrevActive);
pSeq->pPrevActive->pNextActive = pSeq->pNextActive;
if (pSeq->pNextActive)
pSeq->pNextActive->pPrevActive = pSeq->pPrevActive;
}
} else
SVSUTIL_ASSERT ((! pSeq->pPrevActive) && (! pSeq->pNextActive));
if (! pParentSeq)
pSeqBuckets[i] = pSeq->pNextHash;
else
pParentSeq->pNextHash = pSeq->pNextHash;
int iCluster = FindCluster (pSeq->p);
SVSUTIL_ASSERT ((iCluster >= 0) && (iCluster < (int)uiClustersCount));
SVSUTIL_ASSERT ((ppClusters[iCluster]->h.uiFirstFreeBlock < SCSEQUENCE_ENTRIES_PER_BLOCK) || (ppClusters[iCluster]->h.uiFirstFreeBlock == -1));
ppClusters[iCluster]->iNumFree++;
ppClusters[iCluster]->iDirty = TRUE;
pSeq->p->uiLastAccessS = 0;
pSeq->p->uiCurrentSeqN = ppClusters[iCluster]->h.uiFirstFreeBlock;
ppClusters[iCluster]->h.uiFirstFreeBlock = pSeq->p - ppClusters[iCluster]->pos;
SVSUTIL_ASSERT (ppClusters[iCluster]->h.uiFirstFreeBlock < SCSEQUENCE_ENTRIES_PER_BLOCK);
ScOrderSeq *pSeqNext = pSeq->pNextHash;
svsutil_FreeFixed (pSeq, pfmOrderSeq);
pSeq = pSeqNext;
continue;
}
pParentSeq = pSeq;
pSeq = pSeq->pNextHash;
}
}
FlushBackup ();
}
int ScSequenceCollection::CloseBackup (void) {
if (hBackupFile != INVALID_HANDLE_VALUE)
CloseHandle (hBackupFile);
hBackupFile = INVALID_HANDLE_VALUE;
return TRUE;
}
int ScSequenceCollection::CloseStrings (void) {
if (hStringFile != INVALID_HANDLE_VALUE)
CloseHandle (hStringFile);
hStringFile = INVALID_HANDLE_VALUE;
return TRUE;
}
int ScSequenceCollection::OpenBackup (void) {
if (hBackupFile != INVALID_HANDLE_VALUE)
return TRUE;
hBackupFile = CreateFile (lpszBackupName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
if (hBackupFile != INVALID_HANDLE_VALUE)
return TRUE;
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Failed to open file %s\n", lpszBackupName);
#endif
return FALSE;
}
int ScSequenceCollection::OpenStrings (void) {
if (hStringFile != INVALID_HANDLE_VALUE)
return TRUE;
hStringFile = CreateFile (lpszStringName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
if (hStringFile != INVALID_HANDLE_VALUE) {
if (SetFilePointer (hStringFile, 0, NULL, FILE_END) == 0xffffffff) {
CloseStrings ();
return FALSE;
}
return TRUE;
}
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Failed to open file %s\n", lpszStringName);
#endif
return FALSE;
}
int ScSequenceCollection::FlushBackup (void) {
for (int i = 0 ; i < (int)uiClustersCount ; ++i) {
if (ppClusters[i]->iDirty) {
if (! OpenBackup ())
return FALSE;
if (SetFilePointer (hBackupFile, i * SC_FS_UNIT, 0, FILE_BEGIN) == 0xffffffff) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Can't seek to %d in %s\n", i * SC_FS_UNIT, lpszBackupName);
#endif
return FALSE;
}
DWORD dwBytes = 0;
if ((! WriteFile (hBackupFile, ppClusters[i]->ac, sizeof(ppClusters[i]->ac), &dwBytes, NULL)) ||
(dwBytes != sizeof(ppClusters[i]->ac))) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Can't write %d bytes to %s\n", sizeof(ppClusters[i]->ac), lpszBackupName);
#endif
return FALSE;
}
ppClusters[i]->iDirty = FALSE;
}
}
if (hBackupFile != INVALID_HANDLE_VALUE) {
if (SetFilePointer (hBackupFile, i * SC_FS_UNIT, 0, FILE_BEGIN) == 0xffffffff) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Can't seek to %d in %s\n", i * SC_FS_UNIT, lpszBackupName);
#endif
return FALSE;
}
SetEndOfFile (hBackupFile);
FlushFileBuffers (hBackupFile);
uiLastBackupAccessT = GetTickCount ();
}
return TRUE;
}
int ScSequenceCollection::AddNewCluster (void) {
if (uiClustersCount == uiClustersAlloc) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Adding new sequence cluster...\n");
#endif
unsigned int l_uiClustersAlloc = uiClustersAlloc + SCSEQUENCE_CLUSTERALLOC;
ScOrderCluster **l_ppClusters = (ScOrderCluster **)g_funcAlloc (sizeof(ScOrderCluster *) * l_uiClustersAlloc, g_pvAllocData);
if (! l_ppClusters) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Failed to expand cluster array - no memory...\n");
#endif
return FALSE;
}
if (ppClusters) {
memcpy (l_ppClusters, ppClusters, sizeof(ScOrderCluster *) * uiClustersAlloc);
g_funcFree (ppClusters, g_pvFreeData);
}
ppClusters = l_ppClusters;
uiClustersAlloc = l_uiClustersAlloc;
}
ScOrderCluster *pCluster = (ppClusters[uiClustersCount] = (ScOrderCluster *)g_funcAlloc (sizeof(ScOrderCluster), g_pvAllocData));
if (! pCluster) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_ORDER, L"Failed to alloc new sequence cluster...\n");
#endif
return FALSE;
}
++uiClustersCount;
memset (&pCluster->ac, 0, sizeof(pCluster->ac));
pCluster->iNumFree = SCSEQUENCE_ENTRIES_PER_BLOCK;
pCluster->iDirty = TRUE;
pCluster->h.uiFirstFreeBlock = 0;
pCluster->h.uiMagic1 = SCSEQUENCE_MAGIC1;
pCluster->h.uiMagic2 = SCSEQUENCE_MAGIC2;
pCluster->h.uiVersion = SCSEQUENCE_VERSION;
for (int i = 0 ; i < SCSEQUENCE_ENTRIES_PER_BLOCK - 1; ++i)
pCluster->pos[i].uiCurrentSeqN = i + 1;
pCluster->pos[i].uiCurrentSeqN = (DWORD)-1;
return TRUE;
}
ScPersistOrderSeq *ScSequenceCollection::PersistBlock (void) {
for (int i = 0 ; i < (int)uiClustersCount ; ++i) {
if (ppClusters[i]->h.uiFirstFreeBlock != -1) {
SVSUTIL_ASSERT (ppClusters[i]->h.uiFirstFreeBlock < SCSEQUENCE_ENTRIES_PER_BLOCK);
ScPersistOrderSeq *p = &ppClusters[i]->pos[ppClusters[i]->h.uiFirstFreeBlock];
SVSUTIL_ASSERT (p->uiLastAccessS == 0);
SVSUTIL_ASSERT (p->uiCurrentSeqN < SCSEQUENCE_ENTRIES_PER_BLOCK);
ppClusters[i]->iDirty = TRUE;
ppClusters[i]->h.uiFirstFreeBlock = p->uiCurrentSeqN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -