📄 stafsemservice.cpp
字号:
/*****************************************************************************//* Software Testing Automation Framework (STAF) *//* (C) Copyright IBM Corp. 2001, 2004, 2005 *//* *//* This software is licensed under the Common Public License (CPL) V1.0. *//*****************************************************************************/#include "STAF.h"#include "STAFProc.h"#include "STAFProcUtil.h"#include "STAFSemService.h"#include "STAFCommandParser.h"#include "STAFHandleService.h"#include "STAFHandleManager.h"#include "STAFUtil.h"STAFHandleService *handleService;STAFSemService::STAFSemService() : STAFService("SEM"){ // Set up Request Parser fRequestParser.addOption("REQUEST", 1, STAFCommandParser::kValueNotAllowed); fRequestParser.addOption("MUTEX", 1, STAFCommandParser::kValueRequired); fRequestParser.addOption("TIMEOUT", 1, STAFCommandParser::kValueRequired); fRequestParser.addOptionGroup("MUTEX", 1, 1); // Set up Release Parser fReleaseParser.addOption("RELEASE", 1, STAFCommandParser::kValueNotAllowed); fReleaseParser.addOption("MUTEX", 1, STAFCommandParser::kValueRequired); fReleaseParser.addOption("FORCE", 1, STAFCommandParser::kValueNotAllowed); fRequestParser.addOptionGroup("MUTEX", 1, 1); // Set up Post/Pulse Parser fPostPulseParser.addOption("POST", 1, STAFCommandParser::kValueNotAllowed); fPostPulseParser.addOption("PULSE", 1, STAFCommandParser::kValueNotAllowed); fPostPulseParser.addOption("EVENT", 1, STAFCommandParser::kValueRequired); fPostPulseParser.addOptionGroup("EVENT", 1, 1); fPostPulseParser.addOptionGroup("POST PULSE", 1, 1); // Set up Reset Parser fResetParser.addOption("RESET", 1, STAFCommandParser::kValueNotAllowed); fResetParser.addOption("EVENT", 1, STAFCommandParser::kValueRequired); fResetParser.addOptionGroup("EVENT", 1, 1); // Set up Wait Parser fWaitParser.addOption("WAIT", 1, STAFCommandParser::kValueNotAllowed); fWaitParser.addOption("EVENT", 1, STAFCommandParser::kValueRequired); fWaitParser.addOption("TIMEOUT", 1, STAFCommandParser::kValueRequired); fWaitParser.addOptionGroup("EVENT", 1, 1); // Delete Parser Setup fDeleteParser.addOption("DELETE", 1, STAFCommandParser::kValueNotAllowed); fDeleteParser.addOption("MUTEX", 1, STAFCommandParser::kValueRequired); fDeleteParser.addOption("EVENT", 1, STAFCommandParser::kValueRequired); fDeleteParser.addOptionGroup("MUTEX EVENT", 1, 1); // Query Parser Setup fQueryParser.addOption("QUERY", 1, STAFCommandParser::kValueNotAllowed); fQueryParser.addOption("MUTEX", 1, STAFCommandParser::kValueRequired); fQueryParser.addOption("EVENT", 1, STAFCommandParser::kValueRequired); fQueryParser.addOptionGroup("MUTEX EVENT", 1, 1); // List Parser Setup fListParser.addOption("LIST", 1, STAFCommandParser::kValueNotAllowed); fListParser.addOption("MUTEX", 1, STAFCommandParser::kValueNotAllowed); fListParser.addOption("EVENT", 1, STAFCommandParser::kValueNotAllowed); fListParser.addOptionGroup("MUTEX EVENT", 1, 1); // staf_callback Parser Setup fSTAFCallbackParser.addOption("STAF_CALLBACK", 1, STAFCommandParser::kValueNotAllowed); fSTAFCallbackParser.addOption("HANDLEDELETED", 1, STAFCommandParser::kValueNotAllowed); fSTAFCallbackParser.addOption("HANDLE", 1, STAFCommandParser::kValueRequired); fSTAFCallbackParser.addOption("MACHINE", 1, STAFCommandParser::kValueRequired); fSTAFCallbackParser.addOption("UUID", 1, STAFCommandParser::kValueRequired); fSTAFCallbackParser.addOption("KEY", 1, STAFCommandParser::kValueRequired); handleService = STAFHandleService::getInstance(); // Construct map class for listing mutex semaphore information fMutexInfoClass = STAFMapClassDefinition::create( "STAF/Service/Sem/MutexInfo"); fMutexInfoClass->addKey("name", "Name"); fMutexInfoClass->addKey("state", "State"); fMutexInfoClass->addKey("pendingRequests", "Pending Requests"); // Construct map class for listing event semaphore information fEventInfoClass = STAFMapClassDefinition::create( "STAF/Service/Sem/EventInfo"); fEventInfoClass->addKey("name", "Name"); fEventInfoClass->addKey("state", "State"); fEventInfoClass->addKey("waiters", "Waiters"); // Construct map class for detailed information on an event semaphore fQueryEventClass = STAFMapClassDefinition::create( "STAF/Service/Sem/QueryEvent"); fQueryEventClass->addKey("state", "State"); fQueryEventClass->addKey("lastPosted", "Last Posted"); fQueryEventClass->addKey("lastReset", "Last Reset"); fQueryEventClass->addKey("waiterList", "Waiters"); // Construct map class for detailed information on a mutex semaphore fQueryMutexClass = STAFMapClassDefinition::create( "STAF/Service/Sem/QueryMutex"); fQueryMutexClass->addKey("state", "State"); fQueryMutexClass->addKey("owner", "Owner"); fQueryMutexClass->addKey("requestList", "Pending Requests"); // Construct map class for an event semaphore requester fEventRequesterClass = STAFMapClassDefinition::create( "STAF/Service/Sem/EventRequester"); fEventRequesterClass->addKey("machine", "Machine"); fEventRequesterClass->addKey("handleName", "Handle Name"); fEventRequesterClass->addKey("handle", "Handle"); fEventRequesterClass->addKey("user", "User"); fEventRequesterClass->addKey("endpoint", "Endpoint"); fEventRequesterClass->addKey("timestamp", "Date-Time"); // Construct map class for an event semaphore requester fMutexOwnerClass = STAFMapClassDefinition::create( "STAF/Service/Sem/MutexOwner"); fMutexOwnerClass->addKey("machine", "Machine"); fMutexOwnerClass->addKey("handleName", "Handle Name"); fMutexOwnerClass->addKey("handle", "Handle"); fMutexOwnerClass->addKey("user", "User"); fMutexOwnerClass->addKey("endpoint", "Endpoint"); fMutexOwnerClass->addKey("requestTimestamp", "Date-Time Requested"); fMutexOwnerClass->addKey("acquireTimestamp", "Date-Time Acquired"); // Construct map class for an mutex semaphore requester fPendingRequestClass = STAFMapClassDefinition::create( "STAF/Service/Sem/PendingRequest"); fPendingRequestClass->addKey("machine", "Machine"); fPendingRequestClass->addKey("handleName", "Handle Name"); fPendingRequestClass->addKey("handle", "Handle"); fPendingRequestClass->addKey("user", "User"); fPendingRequestClass->addKey("endpoint", "Endpoint"); fPendingRequestClass->addKey("requestTimestamp", "Date-Time Requested");}STAFSemService::~STAFSemService(){ /* Do Nothing */}STAFString STAFSemService::info(unsigned int) const{ return name() + ": Internal";}STAFServiceResult STAFSemService::acceptRequest( const STAFServiceRequest &requestInfo){ STAFString action = requestInfo.fRequest.subWord(0, 1).lowerCase(); if (action == "request") return handleRequest(requestInfo); else if (action == "release") return handleRelease(requestInfo); else if (action == "post" || action == "pulse") return handlePostPulse(requestInfo); else if (action == "reset") return handleReset(requestInfo); else if (action == "wait") return handleWait(requestInfo); else if (action == "delete") return handleDelete(requestInfo); else if (action == "query") return handleQuery(requestInfo); else if (action == "list") return handleList(requestInfo); else if (action == "staf_callback") return handleSTAFCallback(requestInfo); else if (action == "help") return handleHelp(requestInfo); else return kSTAFInvalidRequestString;}STAFServiceResult STAFSemService::handleRequest( const STAFServiceRequest &requestInfo){ // Verify that the requesting machine/user has at least trust level 3 IVALIDATE_TRUST(3, "REQUEST"); // Parse the request STAFCommandParseResultPtr parsedResult = fRequestParser.parse(requestInfo.fRequest); if (parsedResult->rc != kSTAFOk) { return STAFServiceResult(kSTAFInvalidRequestString, parsedResult->errorBuffer, 0); } DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo); STAFString errorBuffer; STAFString result; STAFString semName; STAFRC_t rc = RESOLVE_STRING_OPTION("MUTEX", semName); if (rc) return STAFServiceResult(rc, errorBuffer); STAFString uppercaseSemName = semName.toUpperCase(); unsigned int timeout = STAF_EVENT_SEM_INDEFINITE_WAIT; rc = RESOLVE_DEFAULT_UINT_OPTION("TIMEOUT", timeout, STAF_EVENT_SEM_INDEFINITE_WAIT); if (rc) return STAFServiceResult(rc, errorBuffer); fMutexSemListSem.request(); // GCH // Register for notification when the handle ends gHandleManagerPtr->addNotification(requestInfo.fHandle, requestInfo.fMachine, requestInfo.fSTAFInstanceUUID, name(), "SemServiceMutex"); if (fMutexSemList.find(uppercaseSemName) != fMutexSemList.end()) { // The sempahore exists. Get it and lock it. MutexSemPtr sem = fMutexSemList[uppercaseSemName]; sem->lockPtr->request(); if (sem->isOwned) { // It is safe to unlock the semaphore list here, as this // semaphore can't be deleted with requests pending fMutexSemListSem.release(); // Add a request to the list, unlock the semaphore, // and wait to acquire ownership MutexRequest request(requestInfo.fSTAFInstanceUUID, requestInfo.fMachine, requestInfo.fHandleName, requestInfo.fHandle, requestInfo.fUser, requestInfo.fEndpoint); STAFEventSemPtr myTurn = request.avail; sem->requestList.push_back(request); sem->lockPtr->release(); myTurn->wait(timeout); sem->lockPtr->request(); // Check if the handle that submitted this request was garbage // collected while we were waiting to acquire the mutex semaphore, // and if so, return an error. if (*request.garbageCollectedPtr) { sem->lockPtr->release(); return STAFServiceResult( kSTAFRequestCancelled, "The handle that submitted this request no longer exists"); } if (myTurn->query() == kSTAFEventSemPosted) { // We were posted. So, we should have been given // ownership. Yeah. sem->lockPtr->release(); } else { // We timed out waiting for the semaphore, so remove // us from the list int foundUs = 0; MutexRequestList::iterator iter; for(iter = sem->requestList.begin(); !foundUs && iter != sem->requestList.end(); iter++) { if ((iter->stafInstanceUUID == requestInfo.fSTAFInstanceUUID) && (iter->handle == requestInfo.fHandle)) { foundUs = 1; sem->requestList.erase(iter); break; } } // Now unlock the semaphore and return a timeout error sem->lockPtr->release(); return kSTAFTimeout; } } else { // Take ownership of the semaphore sem->isOwned = 1; sem->owner = MutexRequest(requestInfo.fSTAFInstanceUUID, requestInfo.fMachine, requestInfo.fHandleName, requestInfo.fHandle, requestInfo.fUser, requestInfo.fEndpoint); sem->acquireTimeDate = STAFTimestamp::now(); // Now release the locks on the semphore and the list fMutexSemListSem.release(); sem->lockPtr->release(); } } else { // The semaphore doesn't exist, so create it. fMutexSemList[uppercaseSemName] = MutexSemPtr(new MutexSem(semName, 1, MutexRequest( requestInfo.fSTAFInstanceUUID, requestInfo.fMachine, requestInfo.fHandleName, requestInfo.fHandle, requestInfo.fUser, requestInfo.fEndpoint)), MutexSemPtr::INIT); // Now release the lock on the list fMutexSemListSem.release(); } return STAFServiceResult(kSTAFOk, result);}STAFServiceResult STAFSemService::handleRelease( const STAFServiceRequest &requestInfo){ STAFCommandParseResultPtr parsedResult = fReleaseParser.parse(requestInfo.fRequest); if (parsedResult->rc != kSTAFOk) { return STAFServiceResult(kSTAFInvalidRequestString, parsedResult->errorBuffer, 0); } DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo); STAFString errorBuffer; STAFString result; STAFString semName; STAFRC_t rc = RESOLVE_STRING_OPTION("MUTEX", semName); if (rc) return STAFServiceResult(rc, errorBuffer); STAFString uppercaseSemName = semName.toUpperCase(); // Verify that the requesting machine/user has at least trust level 3 if // FORCE is not specified and at least trust level 4 if FORCE is specified if (parsedResult->optionTimes("FORCE") == 0) { IVALIDATE_TRUST(3, "RELEASE"); } else { IVALIDATE_TRUST(4, "RELEASE FORCE"); } fMutexSemListSem.request(); if (fMutexSemList.find(uppercaseSemName) == fMutexSemList.end()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -