Dryad/DryadVertex/VertexHost/system/common/src/dryadstandaloneini.cpp

608 lines
19 KiB
C++

/*
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.
*/
#include "DrCommon.h"
#include "dryadstandaloneini.h"
#include "dryadnativeport.h"
#include "dryaderrordef.h"
#include "dryadmetadata.h"
#pragma unmanaged
DryadNativePort* g_dryadNativePort;
static XDRESSIONHANDLE s_session;
static XCPROCESSHANDLE s_processHandle;
static bool g_initialized = false;
//
// Initialize the XCompute layer
//
DrError DryadInitializeXCompute(const char* netLibName, const char* iniFileName,
int argc, char* argv[], int* pNOpts)
{
DrError err = DrError_OK;
*pNOpts = 0;
//
// Only initialize XCompute Once
//
if (g_initialized)
{
return DryadError_AlreadyInitialized;
}
g_initialized = true;
// todo: why is this code commented / should it be removed?
/* JC
if (iniFileName == NULL) {
iniFileName = s_configFileName;
}
*/
//
// If library name not set, set it to DryadApplication.X
// where X = process id
// otherwise, copy name into "component" string
//
char component[32];
if (netLibName == NULL)
{
err = ::StringCbPrintfA(component,
sizeof(component),
"DryadApplication.%u",
::GetCurrentProcessId());
LogAssert(SUCCEEDED(err));
netLibName = component;
}
else
{
strcpy(component, netLibName);
}
//
// Initialize Xcompute, providing this semi-unique
// component name and any config file specified
//
err = XcInitialize(iniFileName, component);
if (err != DrError_OK)
{
//
// If initialization fails, report and exit
//
DrLogE( "DryadConfigurationManager - XcInitialize failed, error=%s",
DRERRORSTRING(err));
goto exit;
}
//
// Open an Xcompute session, using default session settings
//
err = XcOpenSession(NULL, &s_session, NULL);
if (err != DrError_OK)
{
//
// If opening session failed, report and exit
//
DrLogE( "DryadConfigurationManager - XcOpenSession failed, error=%s",
DRERRORSTRING(err));
goto exit;
}
//
// Get handle to session process
//
err = XcOpenCurrentProcessHandle(s_session, &s_processHandle);
if (err == DrError_UnknownProcess && s_processHandle == INVALID_XCPROCESSHANDLE)
{
// todo: remove commented code
//JC //Job manager not running under a CN will have to do the following initialization
//JC CreateGlobalJob();
//
// If process cannot be found, report and exit
//
DrLogE( "DryadConfigurationManager - XcOpenCurrentProcessHandle failed (because not running on a compute node?), error=%s",
DRERRORSTRING(err));
goto exit;
}
else if(err != DrError_OK)
{
//
// If failure other than unknown process, report and exit
//
DrLogE( "DryadConfigurationManager - XcOpenCurrentProcessHandle failed, error=%s",
DRERRORSTRING(err));
goto exit;
}
//
// Initialize the dryad metadata and start listening for IO completion events
//
DryadInitialize();
err = DrError_OK;
exit:
return err;
}
//
// Shut down the completion port and xcompute session
//
DrError DryadShutdownXCompute()
{
DrError err = DrError_OK;
//
// Get the number of outstanding requests remaining
// todo: do we want this log? if so, use logging framework
//
UInt32 n = g_dryadNativePort->GetOutstandingRequests();
//VS fprintf(stdout, "DryadShutdownXCompute: %u outstanding requests\n", n);
while (n > 1) // There will always be 1 outstanding request for the next vertex command
{
//
// While their are requests remaining beyond 1, wait 10 seconds and try again
// todo: do we want this log? probably not since this could be indefinite
// todo: is 10 seconds appropriate?
//
Sleep(10);
n = g_dryadNativePort->GetOutstandingRequests();
//VS fprintf(stdout, "DryadShutdownXCompute: %u outstanding requests\n", n);
}
//
// Close the xcompute session
//
err = XcCloseSession(s_session);
return err;
}
//
// Initialize the dryad metadata and start up a completion port waiting for events
//
void DryadInitialize()
{
// todo: check whether this commented out code matters
//JC DryadInitPropertyTable();
//JC DryadInitTagTable();
//JC DryadInitErrorTable();
//
// Initialize the tables defining the metadata
//
DryadInitMetaDataTable();
//
// Create a port and start it
//
g_dryadNativePort = new DryadNativePort(4, 2);
g_dryadNativePort->Start();
}
XDRESSIONHANDLE GetSessionHandle()
{
return s_session;
}
XCPROCESSHANDLE GetProcessHandle()
{
return s_processHandle;
}
//JC
#if 0
#include <dryadpropertydumper.h>
#include <IConfiguration.h>
#include <Configuration.h>
#include <ConfigurationMap.h>
#include <ConfigurationManager.h>
#include <dryadnativeport.h>
#include <dryadmetadata.h>
#include <dryaderrordef.h>
static char* s_configFileName = "cosmos.ini";
#if 0
static char* s_cosmosOptionPrefix = "--inioption:";
#endif
static char* s_verbosePrefix = "--verbose";
static char* s_popupPrefix = "--popup";
static char* s_debugBreakPrefix = "--debugbreak";
static char* s_assertHandlerPrefix = "--asserthandler";
static char* s_disableProfiler = "--disableProfiler";
static const char* s_defaultParameters[] = {
"Counters", "NoCountersFile", "1",
"Dryad", "Cluster", "{!machinename}",
"Dryad", "DumpAllSentMessages", "false",
"Dryad", "DumpAllReceivedMessages", "false",
"stdout", "LogSourceInfo", "1",
"LogRules", "Rule1", "*,*,*,localLog",
"LogRules", "Rule120", "*,A,*,terminate",
"LogRules", "Rule121", "*,SEAW,*,stdout",
"localLog", "FileNameBase", "local\\Log",
"localLog", "MaxFiles", "100",
"localLog", "MaxFileSize", "10000000",
"localLog", "BufferSize", "10000",
NULL
};
static const char* s_dryadProfilerLogRule = "Rule122";
class DryadConfigurationManager : public ConfigurationManager
{
private:
DrStr64 m_strNetLibName;
DrStr128 m_strIniFileName;
int m_argc;
char** m_argv; // heap allocated copy
int m_nOpts; // number of command line arguments consumed
public:
DryadConfigurationManager(
const char* netLibName,
const char* iniFileName,
int argc,
char* argv[])
{
m_strNetLibName = netLibName;
m_strIniFileName = iniFileName;
m_argc = argc;
m_nOpts = 0;
if (argc == 0) {
m_argv = NULL;
} else {
LogAssert(argv != NULL);
m_argv = new char *[argc];
LogAssert(m_argv != NULL);
for (int i = 0; i < argc; i++) {
if (argv[i] == NULL) {
m_argv[i] = NULL;
} else {
size_t len = strlen(argv[i])+1;
m_argv[i] = new char[len];
LogAssert(m_argv[i] != NULL);
memcpy(m_argv[i], argv[i], len);
}
}
}
}
~DryadConfigurationManager()
{
for (int i = 0; i < m_argc; i++) {
if (m_argv[i] != NULL) {
delete[] m_argv[i];
}
}
if (m_argv != NULL) {
delete[] m_argv;
}
}
int GetNumOptsConsumed()
{
return m_nOpts;
}
DrError ApplyProfilerConfig(IMutableConfiguration *cosmosFile) {
DrError err = DrError_OK;
cosmosFile->SetParameter("LogRules",
s_dryadProfilerLogRule, "DryadProfiler,*,*,collectorDryadProfiler");
cosmosFile->SetParameter("collectorDryadProfiler",
"FileNameBase", "collector\\dryadProfiler");
cosmosFile->SetParameter("collectorDryadProfiler",
"MaxFiles", "0");
cosmosFile->SetParameter("collectorDryadProfiler",
"MaxFileSize", "10000000");
cosmosFile->SetParameter("collectorDryadProfiler",
"BufferSize", "10000");
return err;
}
// returns the number of arguments consumed in *pNOpts
DrError ApplyDryadConfigOverrides(
int argc, // Number of command line arguments eligible for parsing
char* argv[], // Command line arguments eligible for parsing
int* pNOpts, // Returned # of command line arguments consumed
IMutableConfiguration *cosmosFile) // Returned autopilot.ini contents
{
DrError err = DrError_OK;
bool disableProfiler = false;
*pNOpts = 0;
++argv;
--argc;
while (argc > 0)
{
#if 0
if (::_strnicmp(argv[0], s_cosmosOptionPrefix,
::strlen(s_cosmosOptionPrefix)) == 0)
{
if (argc < 2)
{
err = DrError_InvalidParameter;
goto exit;
}
if (::strcmp(argv[1], "-") == 0)
{
cosmosFile->RemoveSectionFromArg(argv[0]);
}
else if (::strchr(argv[1], '=') == NULL)
{
cosmosFile->RemoveParameterFromArg(argv[0], argv[1]);
}
else
{
cosmosFile->SetParameterFromArg(argv[0], argv[1]);
}
argv += 2;
argc -= 2;
(*pNOpts) += 2;
}
else
#endif
if (::_strnicmp(argv[0], s_verbosePrefix,
::strlen(s_verbosePrefix)) == 0)
{
cosmosFile->SetParameter("Dryad",
"DumpAllSentMessages", "true");
cosmosFile->SetParameter("Dryad",
"DumpAllReceivedMessages", "true");
cosmosFile->SetParameter("Dryad",
"MessageDumpFile",
"messages.{!component}.{!nodename}.txt");
cosmosFile->SetParameter("LogRules",
"Rule121", "*,ISEAW,*,stdout");
argv += 1;
argc -= 1;
(*pNOpts) += 1;
}
else if (::_strnicmp(argv[0], s_popupPrefix,
::strlen(s_popupPrefix)) == 0)
{
cosmosFile->SetParameter("LogRules",
"Rule120", "*,A,*,popup");
argv += 1;
argc -= 1;
(*pNOpts) += 1;
}
else if (::_strnicmp(argv[0], s_assertHandlerPrefix,
::strlen(s_assertHandlerPrefix)) == 0)
{
cosmosFile->SetParameter("LogRules",
"Rule122", "*,A,*,applicationcallback");
argv += 1;
argc -= 1;
(*pNOpts) += 1;
}
else if (::_strnicmp(argv[0], s_debugBreakPrefix,
::strlen(s_debugBreakPrefix)) == 0)
{
argv += 1;
argc -= 1;
(*pNOpts) += 1;
::DebugBreak();
}
else if (::_strnicmp(argv[0], s_disableProfiler,
::strlen(s_disableProfiler)) == 0)
{
argv += 1;
argc -= 1;
(*pNOpts) += 1;
disableProfiler = true;
}
else
{
break;
}
}
err = DrError_OK;
if (!disableProfiler) {
err = ApplyProfilerConfig(cosmosFile);
}
return err;
}
bool DoInitialize()
{
if (m_valid) {
// We don't want perf counter files
Counters::SetInitNoPerfFiles();
}
// Register ourselves as the singleton config manager
if (!m_valid || !Configuration::PreInitialize(this)) {
DrLogA( "DryadConfigurationManager",
"Failed to preinitialize dryad configuration manager");
m_valid = false;
}
if (m_valid) {
if (!CommonInit(m_strIniFileName.GetString(), 0, -1 )) {
DrLogA( "DryadConfigurationManager",
"Failed to initialize dryad configuration manager");
m_valid = false;
}
}
return m_valid;
}
/**
* Called at the start of InitBootstrapConfiguration, this method is a last chance for a subclass to mess with the bootstrap configuration before it is used.
*
* On entry, bootstrapConfigPathname is the fully qualified name of the bootstrap file.
* bootstrapConfiguration is the raw (no macro expansion or override collapsing) configuration, or NULL if the configuration was not found.
*
* On exit, bootstrapConfiguration is the final raw (no macro expansion or override collapsing) bootstrap configuration. If NULL, initialization will fail.
*
* The default implementation does nothing.
*
* Returns false if initialization should fail.
*/
virtual bool PreprocessBootstrapConfiguration(const char *bootstrapConfigPathname, Ptr<const IConfiguration>& bootstrapConfiguration)
{
if (bootstrapConfiguration == NULL) {
// The bootstrap config file is missing -- build a default one
DrStr64 strDataDirLocation;
DrStr32 strRelDataDirLocation;
strRelDataDirLocation.SetF(".\\DataDir.%u", GetCurrentProcessId());
DrError err = DrCanonicalizeFilePath(strDataDirLocation, strRelDataDirLocation);
if (err != DrError_OK) {
DrLogE( "DryadConfigurationManager",
"Failed to canonicalize data directory name %s error=%s",
strRelDataDirLocation.GetString(), DRERRORSTRING(err));
return false;
}
Ptr<IMutableConfiguration> cfg = Configuration::GenerateDefaultBootstrapConfig(
strDataDirLocation.GetString(),
"...",
"default",
NULL);
if (cfg == NULL) {
DrLogE( "DryadConfigurationManager",
"Failed to create default bootstrap file");
return false;
}
bootstrapConfiguration = cfg;
}
return true;
}
/**
* Called immediately after attempted loading of the default configuration, this method is a last chance for a subclass to
* mess with the default configuration before it is used.
*
* On entry, defaultConfigPathname is the fully qualified name of the default configuration.
* "configuration" is the default filtered view of the configuration, or NULL if the configuration was not found
* rawConfiguration is the raw (no macro expansion or override collapsing) configuration, or NULL if the configuration was not found.
*
* On exit, rawConfiguration is the final raw (no macro expansion or override collapsing) default configuration. If NULL, initialization will fail.
*
* The default implementation does nothing.
*
* Returns false if initialization should fail.
*/
virtual bool PreprocessDefaultConfiguration(
const char *defaultConfigPathname,
const IConfiguration *configuration,
Ptr<const IConfiguration>& rawConfiguration)
{
// Create an editable version of the configuration
Ptr<IMutableConfiguration> newConfig;
if (configuration == NULL) {
// The config file is missing -- build a default one
newConfig = Configuration::GenerateDefaultConfig();
if (newConfig == NULL) {
DrLogE( "DryadConfigurationManager",
"Failed to create default config file");
return false;
}
for (const char **ppDefaults = s_defaultParameters; *ppDefaults != NULL; ppDefaults += 3) {
const char *section = ppDefaults[0];
const char *param = ppDefaults[1];
LogAssert(param != NULL);
const char *value = ppDefaults[2];
LogAssert(value != NULL);
newConfig->SetParameter(section, param, value);
}
} else {
newConfig = new ConfigurationMap(configuration);
if (newConfig == NULL) {
DrLogE( "DryadConfigurationManager",
"Failed to create copy of config file");
return false;
}
}
// process the command line to override values
DrError err = ApplyDryadConfigOverrides(m_argc, m_argv, &m_nOpts, newConfig);
if (err != DrError_OK) {
DrLogE( "DryadConfigurationManager",
"Failed to apply command line overrides to config file: %s", err);
return false;
}
// replace the configuration with the edited one. Note that overrides, etc. have already been applied and removed.
rawConfiguration = newConfig;
return true;
}
};
DrJobTicket* CreateGlobalJob()
{
DrError hr = S_OK;
DrServiceDescriptor sd;
DrRef<DrJobTicket> jobTicket = g_pDryadConfig->GetDefaultJobTicket();
sd.Set("xcps", g_pDryadConfig->GetDefaultClusterName(), NULL, "rd.RDRBasic.XComputeProcessScheduler_0");
DrRef<XcPsCreateJobRequest> msg;
msg.Attach(new XcPsCreateJobRequest());
msg->SetCreateJobTicket(jobTicket);
XcJobConstraint& constraint = msg->CreateJobConstraint();
constraint.SetMaxConcurrentProcesses(999);
constraint.SetMaxExecutionTime(DrTimeInterval_Hour);
g_pDrClient->SendTo(msg, sd);
msg->WaitForResponse( &hr );
if (hr != DrError_OK)
{
DrLogE( "DryadConfigurationManager",
"CreateJob failied, error=%s",
DRERRORSTRING(hr));
LogAssert(false);
}
return jobTicket.Detach();
}
#endif // if 0