/*********************************************************************** * * Copyright (C) 2006 Novell, Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, Novell, Inc. * * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. * * Author: Juan Carlos Luciani * ***********************************************************************/ //===[ Include files ]===================================================== #include "ipcint.h" #include "cchannel.h" #include "clientreq.h" //===[ External data ]===================================================== //===[ External prototypes ]=============================================== //===[ Manifest constants ]================================================ //===[ Type definitions ]================================================== //===[ Function prototypes ]=============================================== //===[ Global variables ]================================================== //===[ Type definitions ]================================================== //===[ Function prototypes ]=============================================== //===[ Global variables ]================================================== // // Object Counters // unsigned long numClientReqObjects = 0; //++======================================================================= ClientReq::ClientReq( uint32_t reqId) : m_reqId (reqId), m_pServerData (NULL), m_submitThreadActive (true), m_completed (false), m_internalProblem (false) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { DbgTrace(1, "ClientReq::ClientReq- Start, Obj = %0X\n", this); // Initialize the mutex if (pthread_mutex_init(&m_mutex, NULL) != 0) { DbgTrace(0, "ClientReq::ClientReq- Mutex initialization failed\n", 0); // Throw exception throw bad_alloc(); } // Initialize the condition if (pthread_cond_init(&m_condition, NULL) != 0) { DbgTrace(0, "ClientReq::ClientReq- Condition initialization failed\n", 0); // Destroy the allocated mutex pthread_mutex_destroy(&m_mutex); // Throw exception throw bad_alloc(); } // Increment the object count InterlockedIncrement(&numClientReqObjects); DbgTrace(1, "ClientReq::ClientReq- End\n", 0); } /*-- ClientReq::ClientReq() --*/ //++======================================================================= ClientReq::~ClientReq(void) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { DbgTrace(1, "ClientReq::~ClientReq- Start, Obj = %0X\n", this); // Cleanup resources allocated for the object pthread_mutex_destroy(&m_mutex); pthread_cond_destroy(&m_condition); // Release any server data that we may have if (m_pServerData != NULL) free(m_pServerData); // Decrement the object count InterlockedDecrement(&numClientReqObjects); DbgTrace(1, "ClientReq::~ClientReq- End\n", 0); } /*-- ClientReq::~ClientReq() --*/ //++======================================================================= void ClientReq::processServerData( char *pServerData, int serverDataLength) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { DbgTrace(1, "ClientReq::processServerData- Start, Obj = %0X\n", this); // Acquire exclusive access to the object pthread_mutex_lock(&m_mutex); // Save server dataetup the ServerData object m_pServerData = pServerData; m_serverDataLen = serverDataLength; // Mark the request as completed m_completed = true; // Check if we must awaken the thread that submitted the request // so that it can service the server data. if (!m_submitThreadActive) { // The submit thread is not active, awaken it. m_submitThreadActive = true; pthread_cond_signal(&m_condition); } // Release exclusive access to the object pthread_mutex_unlock(&m_mutex); DbgTrace(1, "ClientReq::processServerData- End\n", 0); } /*-- ClientReq::processServerData() --*/ //++======================================================================= void ClientReq::processError(void) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { DbgTrace(1, "ClientReq::processError- Start, Obj = %0X\n", this); // Acquire exclusive access to the object pthread_mutex_lock(&m_mutex); // Record that we suffered an internal problem and mark the // request as completed. m_internalProblem = true; m_completed = true; // Check if we must awaken the thread that submitted the request // so that it can deal with the problem. if (!m_submitThreadActive) { // The submit thread is not active, awaken it. m_submitThreadActive = true; pthread_cond_signal(&m_condition); } // Release exclusive access to the object pthread_mutex_unlock(&m_mutex); DbgTrace(1, "ClientReq::processError- End\n", 0); } /*-- ClientReq::processError() --*/ //++======================================================================= int ClientReq::waitForCompletion( char **ppResponseData, int *pResponseDataLength) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { int retStatus; int oldCancelState; DbgTrace(1, "ClientReq::waitForCompletion- Start, Obj = %0X\n", this); // Make sure that the thread can not be cancelled while executing // in this routine. pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldCancelState); // Acquire exclusive access to the object pthread_mutex_lock(&m_mutex); // Continue until the request completes while (!m_completed) { // Wait to be awaken // // Indicate that we are no longer active m_submitThreadActive = false; pthread_cond_wait(&m_condition, &m_mutex); } // Release exclusive access to the object pthread_mutex_unlock(&m_mutex); // Determine the parameters that should be returned if (!m_internalProblem) { retStatus = 0; *ppResponseData = m_pServerData; *pResponseDataLength = m_serverDataLen; // Forget about the server data buffer m_pServerData = NULL; } else retStatus = -1; DbgTrace(1, "ClientReq::waitForCompletion- End, retStatus = %0X\n", retStatus); // Restore the threads cancel state pthread_setcancelstate(oldCancelState, NULL); return retStatus; } /*-- ClientReq::waitForCompletion() --*/ //++======================================================================= ClientReq::CompletionStatus ClientReq::completionStatus(void) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { CompletionStatus compStatus; DbgTrace(1, "ClientReq::completionStatus- Start, Obj = %0X\n", this); // Check if we encountered any issues if (m_internalProblem) { compStatus = ErrorCompletionStatus; } else { compStatus = SuccessCompletionStatus; } DbgTrace(1, "ClientReq::completionStatus- End, compStatus = %0X\n", compStatus); return compStatus; } /*-- ClientReq::completionStatus() --*/ //========================================================================= //=========================================================================