/* Copyright (c) Microsoft Corporation All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ /*++ Module Name: node.cpp Abstract: This module contains the public interface and support routines for the xcompute node functionality on top of the HPC scheduler. --*/ #include "stdafx.h" using namespace System; using namespace System::Collections::Generic; using namespace System::Collections::Specialized; using namespace System::Runtime::InteropServices; gcroot g_NodeList = gcnew System::Collections::Specialized::StringCollection(); CComAutoCriticalSection g_NodeListLock; XCPROCESSNODEID NodeNameToID(System::String ^name) { String ^N = name->ToUpper(); CComCritSecLock lock(g_NodeListLock); int index = g_NodeList->IndexOf(N); if (index == -1) { index = g_NodeList->Add(N); } return (XCPROCESSNODEID)(index+1); } System::String ^ NodeIDToName(XCPROCESSNODEID nodeID) { int i = (int)nodeID; CComCritSecLock lock(g_NodeListLock); return (String ^)g_NodeList->default[i-1]; } /*++ XcGetProcessNodeId API Description: Gets the process node on which the process has been assigned. If the process state anything other than XCPROCESSSTATE_ASSIGNEDTOPN an error is returned. Arguments: hProcessHandle Process handle pProcessNodeId Pointer to process node Id Return Value: XCERROR_OK The call succeded --*/ XCOMPUTEAPI_EXT XCERROR XCOMPUTEAPI XcGetProcessNodeId( IN XCPROCESSHANDLE hProcessHandle, OUT PXCPROCESSNODEID pProcessNodeId ) { try { if (hProcessHandle == CURRENT_PROCESS_ID) { *pProcessNodeId = NodeNameToID(Microsoft::Research::Dryad::AzureUtils::CurrentHostName); } else { System::String ^nodeName = Microsoft::Research::Dryad::VertexScheduler::GetInstance()->GetAssignedNode((int)hProcessHandle); if (System::String::IsNullOrEmpty(nodeName)) { return E_FAIL; } *pProcessNodeId = NodeNameToID(nodeName); } } catch (System::Exception ^e) { return System::Runtime::InteropServices::Marshal::GetHRForException(e); } return S_OK; } /*++ XcEnumerateProcessNodes Description: This API enumerates all the process nodes that are controlled by the Process scheduler and returns an array of processNodeIds Arguments: hSession Handle to a session associated with this call pNumNodeIds Pointer to a int which gets filled with the number of process Node Ids in the ppProcessNodeIds array ppProcessNodeIds Pointer to array of processNode Ids. Use the XcFreeMemory() API to deallocate. pAsyncInfo The async info structure. Its an alias to the CS_ASYNC_INFO defined in Cosmos.h. If this parameter is NULL, then function completes in synchronous manner and error code is returned as return value. If parameter is not NULL then operation is carried on in asynchronous manner. If asynchronous operation has been successfully started then function terminates immediately with HRESULT_FROM_WIN32(ERROR_IO_PENDING) return value. Any other return value indicates that it was impossible to start asynchronous operation. Return Value: if pAsyncInfo is NULL XCERROR_OK indicates call succeeded Any other error code, indicates the failure reason. if pAsyncInfo != NULL HRESULT_FROM_WIN32(ERROR_IO_PENDING) indicates the async operation was successfully started Any other return value indicates it was impossible to start asynchronous operation --*/ XCOMPUTEAPI_EXT XCERROR XCOMPUTEAPI XcEnumerateProcessNodes( IN XCSESSIONHANDLE hSession, OUT UINT32* pNumNodeIds, OUT PXCPROCESSNODEID* ppProcessNodeIds, IN PCXC_ASYNC_INFO pAsyncInfo ) { PASYNC async; CAPTURE_ASYNC(async); if (pNumNodeIds == NULL || ppProcessNodeIds == NULL) { return COMPLETE_ASYNC(async, E_INVALIDARG); } array ^nodes =Microsoft::Research::Dryad::VertexScheduler::GetInstance()->EnumerateProcessNodes(); if (nodes == nullptr) { return COMPLETE_ASYNC(async, E_UNEXPECTED); } // // Now get the list of allocated nodes. // int numNodes = nodes->Length; // // Allocate a buffer large enough to hold all the node IDs // XCPROCESSNODEID *nodeIds = (XCPROCESSNODEID *)::LocalAlloc(LMEM_FIXED, numNodes * sizeof(XCPROCESSNODEID)); if (nodeIds == NULL) { return COMPLETE_ASYNC(async, E_OUTOFMEMORY); } int i=0; for each (String ^node in nodes) { nodeIds[i++] = NodeNameToID(node); } *ppProcessNodeIds = nodeIds; *pNumNodeIds = i; return COMPLETE_ASYNC(async, S_OK); } /*++ XcFetchProcessNodeMetaData Description: This API fetches the process node related metadata. This call can result in a call to the Process Scheduler, if the metadata for a given process node is missing. Arguments: hSession Handle to a session associated with this call pProcessNodeIds Array of IDs of the nodes for which the metadata is required numNodeIds Number of node ids in the pProcessNodeIds array pAsyncInfo The async info structure. Its an alias to the CS_ASYNC_INFO defined in Cosmos.h. If this parameter is NULL, then function completes in synchronous manner and error code is returned as return value. If parameter is not NULL then operation is carried on in asynchronous manner. If asynchronous operation has been successfully started then function terminates immediately with HRESULT_FROM_WIN32(ERROR_IO_PENDING) return value. Any other return value indicates that it was impossible to start asynchronous operation. Return Value: if pAsyncInfo is NULL XCERROR_OK indicates call succeeded Any other error code, indicates the failure reason. if pAsyncInfo != NULL HRESULT_FROM_WIN32(ERROR_IO_PENDING) indicates the async operation was successfully started Any other return value indicates it was impossible to start asynchronous operation --*/ XCOMPUTEAPI_EXT XCERROR XCOMPUTEAPI XcFetchProcessNodeMetaData( IN XCSESSIONHANDLE hSession, IN UINT32 numNodeIds, IN PXCPROCESSNODEID pProcessNodeIds, IN PCXC_ASYNC_INFO pAsyncInfo ) { PASYNC async; CAPTURE_ASYNC(async); return COMPLETE_ASYNC(async, E_NOTIMPL); } /*++ XcGetCurrentProcessNodeId API Description: Gets the current Process Node Id. The Process Node Id to the node name map is maintained internally. Arguments: hSession Handle to an XCompute session associated with this call. pProcessNodeId Pointer to Pointer of the Id of the node Return Value: CsError_OK indicates call succeeded --*/ XCOMPUTEAPI_EXT XCERROR XCOMPUTEAPI XcGetCurrentProcessNodeId( IN XCSESSIONHANDLE hSession, OUT PXCPROCESSNODEID pProcessNodeId ) { *pProcessNodeId = NodeNameToID(Microsoft::Research::Dryad::AzureUtils::CurrentHostName); return S_OK; } /*++ XcProcessNodeIdFromName API Description: Gets the Process Node Id for a node given the node name. The Process Node Id to the node name map is maintained internally. If a node name is not found in the internal map, then a new entry is created and the corrosponding id is returned back Arguments: hSession Handle to an XCompute session associated with this call. Reserved for future use. Must be NULL. pszProcessNodeName Name of the process node for which Id is needed pProcessNodeId Pointer to Pointer of the Id of the node Return Value: CsError_OK indicates call succeeded --*/ XCOMPUTEAPI_EXT XCERROR XCOMPUTEAPI XcProcessNodeIdFromName( IN XCSESSIONHANDLE hSession, IN PCSTR pszProcessNodeName, OUT PXCPROCESSNODEID pProcessNodeId ) { *pProcessNodeId = NodeNameToID(gcnew String(pszProcessNodeName)); return S_OK; } /*++ XcProcessNodeNameFromId API Description: Gets the Process Node name from the given Process Node Id.The Process Node Id to the node name map is maintained internally. Arguments: hSession Handle to an XCompute session associated with this call. processNodeId The process Node Id for which the node name is needed ppszProcessNodeName Name of the process node corrosponding to Id Note: the returned process node name string is permanently allocated and will remain valid for the life of the process. There is no need to make a copy of this string. Return Value: CsError_OK indicates call succeeded --*/ XCOMPUTEAPI_EXT XCERROR XCOMPUTEAPI XcProcessNodeNameFromId( IN XCSESSIONHANDLE hSession, IN XCPROCESSNODEID processNodeId, OUT PCSTR* ppszProcessNodeName ) { // // If we've returned this name before, return the // same pointer again. // String ^s = NodeIDToName(processNodeId); *ppszProcessNodeName = (PCSTR)Marshal::StringToHGlobalAnsi(s).ToPointer(); return S_OK; }