1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef VMPI_H
#define VMPI_H
#ifdef _WIN32
#pragma once
#endif
#include "vmpi_defs.h"
#include "messbuf.h"
#include "iphelpers.h"
// These are called to handle incoming messages.
// Return true if you handled the message and false otherwise.
// Note: the first byte in each message is the packet ID.
typedef bool (*VMPIDispatchFn)( MessageBuffer *pBuf, int iSource, int iPacketID );
typedef void (*VMPI_Disconnect_Handler)( int procID, const char *pReason );
// Which machine is the master.
#define VMPI_MASTER_ID 0
#define VMPI_SEND_TO_ALL -2
#define VMPI_PERSISTENT -3 // If this is set as the destination for a packet, it is sent to all
// workers, and also to new workers that connect.
#define MAX_VMPI_PACKET_IDS 32
#define VMPI_TIMEOUT_INFINITE 0xFFFFFFFF
// Instantiate one of these to register a dispatch.
class CDispatchReg
{
public:
CDispatchReg( int iPacketID, VMPIDispatchFn fn );
};
// Enums for all the command line parameters.
#define VMPI_PARAM_SDK_HIDDEN 0x0001 // Hidden in SDK mode.
#define VMPI_PARAM( paramName, paramFlags, helpText ) paramName,
enum EVMPICmdLineParam
{
k_eVMPICmdLineParam_FirstParam=0,
k_eVMPICmdLineParam_VMPIParam,
#include "vmpi_parameters.h"
k_eVMPICmdLineParam_LastParam
};
#undef VMPI_PARAM
// Shared by all the tools.
extern bool g_bUseMPI;
extern bool g_bMPIMaster; // Set to true if we're the master in a VMPI session.
extern int g_iVMPIVerboseLevel; // Higher numbers make it spit out more data.
extern bool g_bMPI_Stats; // Send stats to the MySQL database?
extern bool g_bMPI_StatsTextOutput; // Send text output in the stats?
// These can be watched or modified to check bandwidth statistics.
extern int g_nBytesSent;
extern int g_nMessagesSent;
extern int g_nBytesReceived;
extern int g_nMessagesReceived;
extern int g_nMulticastBytesSent;
extern int g_nMulticastBytesReceived;
extern int g_nMaxWorkerCount;
enum VMPIRunMode
{
VMPI_RUN_NETWORKED,
VMPI_RUN_LOCAL // Just make a local process and have it do the work.
};
enum VMPIFileSystemMode
{
VMPI_FILESYSTEM_MULTICAST, // Multicast out, find workers, have them do work.
VMPI_FILESYSTEM_BROADCAST, // Broadcast out, find workers, have them do work.
VMPI_FILESYSTEM_TCP // TCP filesystem.
};
// If this precedes the dependency filename, then it will transfer all the files in the specified directory.
#define VMPI_DEPENDENCY_DIRECTORY_TOKEN '*'
// It's good to specify a disconnect handler here immediately. If you don't have a handler
// and the master disconnects, you'll lockup forever inside a dispatch loop because you
// never handled the master disconnecting.
//
// Note: runMode is only relevant for the VMPI master. The worker always connects to the master
// the same way.
bool VMPI_Init(
int &argc,
char **&argv,
const char *pDependencyFilename,
VMPI_Disconnect_Handler handler = NULL,
VMPIRunMode runMode = VMPI_RUN_NETWORKED, // Networked or local?,
bool bConnectingAsService = false
);
// Used when hosting a patch.
void VMPI_Init_PatchMaster( int argc, char **argv );
void VMPI_Finalize();
VMPIRunMode VMPI_GetRunMode();
VMPIFileSystemMode VMPI_GetFileSystemMode();
// Note: this number can change on the master.
int VMPI_GetCurrentNumberOfConnections();
// Dispatch messages until it gets one with the specified packet ID.
// If subPacketID is not set to -1, then the second byte must match that as well.
//
// Note: this WILL dispatch packets with matching packet IDs and give them a chance to handle packets first.
//
// If bWait is true, then this function either succeeds or Error() is called. If it's false, then if the first available message
// is handled by a dispatch, this function returns false.
bool VMPI_DispatchUntil( MessageBuffer *pBuf, int *pSource, int packetID, int subPacketID = -1, bool bWait = true );
// This waits for the next message and dispatches it.
// You can specify a timeout in milliseconds. If the timeout expires, the function returns false.
bool VMPI_DispatchNextMessage( unsigned long timeout=VMPI_TIMEOUT_INFINITE );
// This should be called periodically in modal loops that don't call other VMPI functions. This will
// check for disconnected sockets and call disconnect handlers so the app can error out if
// it loses all of its connections.
//
// This can be used in place of a Sleep() call by specifying a timeout value.
void VMPI_HandleSocketErrors( unsigned long timeout=0 );
enum VMPISendFlags
{
k_eVMPISendFlags_GroupPackets = 0x0001
};
// Use these to send data to one of the machines.
// If iDest is VMPI_SEND_TO_ALL, then the message goes to all the machines.
// Flags is a combination of the VMPISendFlags enums.
bool VMPI_SendData( void *pData, int nBytes, int iDest, int fVMPISendFlags=0 );
bool VMPI_SendChunks( void const * const *pChunks, const int *pChunkLengths, int nChunks, int iDest, int fVMPISendFlags=0 );
bool VMPI_Send2Chunks( const void *pChunk1, int chunk1Len, const void *pChunk2, int chunk2Len, int iDest, int fVMPISendFlags=0 ); // for convenience..
bool VMPI_Send3Chunks( const void *pChunk1, int chunk1Len, const void *pChunk2, int chunk2Len, const void *pChunk3, int chunk3Len, int iDest, int fVMPISendFlags=0 );
// Flush any groups that were queued with k_eVMPISendFlags_GroupPackets.
// If msInterval is > 0, then it will check a timer and only flush that often (so you can call this a lot, and have it check).
void VMPI_FlushGroupedPackets( unsigned long msInterval=0 );
// This registers a function that gets called when a connection is terminated ungracefully.
void VMPI_AddDisconnectHandler( VMPI_Disconnect_Handler handler );
// Returns false if the process has disconnected ungracefully (disconnect handlers
// would have been called for it too).
bool VMPI_IsProcConnected( int procID );
// Returns true if the process is just a service (in which case it should only get file IO traffic).
bool VMPI_IsProcAService( int procID );
// Simple wrapper for Sleep() so people can avoid including windows.h
void VMPI_Sleep( unsigned long ms );
// VMPI sends machine names around first thing.
const char* VMPI_GetLocalMachineName();
const char* VMPI_GetMachineName( int iProc );
bool VMPI_HasMachineNameBeenSet( int iProc );
// Returns 0xFFFFFFFF if the ID hasn't been set.
unsigned long VMPI_GetJobWorkerID( int iProc );
void VMPI_SetJobWorkerID( int iProc, unsigned long jobWorkerID );
// Search a command line to find arguments. Looks for pName, and if it finds it, returns the
// argument following it. If pName is the last argument, it returns pDefault. If it doesn't
// find pName, returns NULL.
const char* VMPI_FindArg( int argc, char **argv, const char *pName, const char *pDefault = "" );
// (Threadsafe) get and set the current stage. This info winds up in the VMPI database.
void VMPI_GetCurrentStage( char *pOut, int strLen );
void VMPI_SetCurrentStage( const char *pCurStage );
// VMPI is always broadcasting this job in the background.
// This changes the password to 'debugworker' and allows more workers in.
// This can be used if workers are dying on certain work units. Then a programmer
// can run vmpi_service with -superdebug and debug the whole thing.
void VMPI_InviteDebugWorkers();
bool VMPI_IsSDKMode();
// Lookup a command line parameter string.
const char* VMPI_GetParamString( EVMPICmdLineParam eParam );
int VMPI_GetParamFlags( EVMPICmdLineParam eParam );
const char* VMPI_GetParamHelpString( EVMPICmdLineParam eParam );
bool VMPI_IsParamUsed( EVMPICmdLineParam eParam ); // Returns true if the specified parameter is on the command line.
// Can be called from error handlers and if -mpi_Restart is used, it'll automatically restart the process.
bool VMPI_HandleAutoRestart();
#endif // VMPI_H
|