Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1579 lines
56 KiB

  1. /*
  2. */
  3. Include('types.js');
  4. Include('utils.js');
  5. Include('staticstrings.js');
  6. Include('MsgQueue.js');
  7. /*
  8. This script is invoked by harness.js to provide async
  9. communications to the slave machines running "slave.js"
  10. Communication between slaveproxy and harness is exclusivly thru
  11. "messages".
  12. */
  13. var g_FSObj;
  14. var g_aPublishedEnlistments = null;
  15. var g_aFiles = null;
  16. var g_fUpdatePublicDataPending = false;
  17. var g_MasterQueue = null;
  18. var g_cDialogIndex = 0;
  19. // If a build machine is reset after a build has completed, its OK to send it the "restart" command.
  20. var g_fOKToRestartLostMachine = false;
  21. var g_strConfigError = 'ConfigError';
  22. var g_strOK = 'ok';
  23. var g_strNoEnvTemplate = 'Must set config and environment templates first';
  24. var g_strStartFailed = "An error occurred in StartRemoteMachine: ";
  25. var g_strSlaveBusy = "A build server in your distributed build is already busy.";
  26. var g_strSendCmdRemoteMachine = "SendCmdRemoteMachine failed: ";
  27. var g_strSendCmdDisconnect = "The connection to the build server no longer exists";
  28. var g_SlaveProxyThreadReady = 'SlaveProxyThreadReady';
  29. var g_SlaveProxyThreadFailed = 'SlaveProxyThreadFailed';
  30. // "'Update<machinename>'" is a placeholder. The real name is setup in ScriptMain.
  31. var g_SlaveProxyWaitFor = ['SlaveProxyThreadExit', 'RebuildWaitArray', 'Update<machinename>'];
  32. var g_strRemoteMachineName = '';
  33. var g_MyName = 'slaveproxy';
  34. var g_aDepotIndex = new Object(); // associate depot name to depot index.
  35. //var g_fDirectCopy = true; // If true, execute XCOPY directly, instead of with a batch file.
  36. var g_nBuildPass = 0;
  37. function SPLogMsg(msg)
  38. {
  39. LogMsg('(' + g_strRemoteMachineName + ') ' + msg, 1);
  40. }
  41. function slaveproxy_js::OnScriptError(strFile, nLine, nChar, strText, sCode, strSource, strDescription)
  42. {
  43. return CommonOnScriptError("slaveproxy_js", strFile, nLine, nChar, strText, sCode, strSource, strDescription);
  44. }
  45. function slaveproxy_js::ScriptMain()
  46. {
  47. var nEvent;
  48. var aWaitQueues;
  49. g_MasterQueue = GetMsgQueue(ScriptParam);
  50. g_MyName = g_MasterQueue.strName;
  51. g_strRemoteMachineName = g_MyName.split(',')[1];
  52. SignalThreadSync(g_SlaveProxyThreadReady);
  53. CommonVersionCheck(/* $DROPVERSION: */ "V(########) F(!!!!!!!!!!!!!!)" /* $ */);
  54. SPLogMsg("Queue name for this thread: " + g_MyName);
  55. g_SlaveProxyWaitFor[2] = 'Update' + g_strRemoteMachineName;
  56. g_FSObj = new ActiveXObject("Scripting.FileSystemObject");
  57. do
  58. {
  59. aWaitQueues = new Array();
  60. aWaitQueues[0] = g_MasterQueue;
  61. nEvent = WaitForMultipleQueues(aWaitQueues, g_SlaveProxyWaitFor.toString(), SlaveProxyMsgProc, 0);
  62. if (nEvent > 0 && nEvent <= g_SlaveProxyWaitFor.length)
  63. {
  64. ResetSync(g_SlaveProxyWaitFor[nEvent - 1]);
  65. if (nEvent == 3)
  66. {
  67. RefreshPublicData(false);
  68. }
  69. }
  70. }
  71. while (nEvent != 1); // While not SlaveProxyThreadExit
  72. AbortRemoteMachines();
  73. SPLogMsg(g_MyName + ' Exit');
  74. }
  75. /*
  76. slaveproxy_js::OnEventSourceEvent
  77. Dispatch the event to the appropriate handler.
  78. */
  79. function slaveproxy_js::OnEventSourceEvent(RemoteObj, DispID, cmd, params)
  80. {
  81. mach = PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote;
  82. if (RemoteObj != mach.obj)
  83. SPLogMsg("Event from stale remote object? [" + [DispID, cmd, params].toString() + "]");
  84. RemoteObj = mach;
  85. var vRet = '';
  86. try
  87. {
  88. OnEventSourceEventSlave(RemoteObj, cmd, params)
  89. }
  90. catch(ex)
  91. {
  92. JAssert(false, "(" + g_strRemoteMachineName + ") " + "an error occurred in OnEventSourceEvent(" + cmd + ") \n" + ex);
  93. }
  94. }
  95. /*
  96. OnEventSourceEventSlave
  97. Handle NotifyScript() events from slave.js
  98. */
  99. function OnEventSourceEventSlave(RemoteObj, cmd, params)
  100. {
  101. var aDepotIdx;
  102. var i;
  103. switch(cmd)
  104. {
  105. case 'ScriptError':
  106. NotifyScriptError(RemoteObj, params);
  107. break;
  108. }
  109. }
  110. /*
  111. SlaveProxyMsgProc
  112. Handle MsgQueue messages from harness.js
  113. These messages are of course sent async between harness and slaveproxy.
  114. They are received and dispatched in slaveproxy_js::ScriptMain().
  115. */
  116. function SlaveProxyMsgProc(queue, msg)
  117. {
  118. try
  119. {
  120. var newmach;
  121. var nTracePoint = 0;
  122. var vRet = g_strOK;
  123. var params = msg.aArgs;
  124. var mach;
  125. SPLogMsg('(' + g_MyName + ') (g_MasterQueue, msg): ' + params[0]);
  126. switch (params[0])
  127. {
  128. case 'test':
  129. SPLogMsg('Recieved a test message. ArgCount=' + params.length + ' arg1 is: ' + params[1]);
  130. break;
  131. case 'start':
  132. newmach = new Machine();
  133. newmach.strName = g_strRemoteMachineName;
  134. PublicData.aBuild[0].hMachine[g_strRemoteMachineName] = newmach;
  135. if (PrivateData.objConfig.Options.fRestart)
  136. vRet = StartRemoteMachine('restart', true);
  137. else
  138. vRet = StartRemoteMachine('start', false);
  139. break;
  140. case 'restartcopyfiles':
  141. vRet = SendCmdRemoteMachine("restartcopyfiles", 0);
  142. break;
  143. case 'abort':
  144. vRet = AbortRemoteMachines();
  145. break;
  146. case 'copyfilestoslaves':
  147. SPLogMsg("CopyFilesToSlaves");
  148. vRet = CopyFilesToSlaves();
  149. break;
  150. case 'copyfilestopostbuild':
  151. vRet = CopyFilesToPostBuild();
  152. break;
  153. case 'nextpass':
  154. ++g_nBuildPass;
  155. SPLogMsg("nextpass counter is " + params[1]);
  156. vRet = SendCmdRemoteMachine("nextpass", 0);
  157. break;
  158. case 'createmergedpublish.log':
  159. if (PrivateData.objConfig.Options.fCopyPublishedFiles)
  160. vRet = CreateMergedPublishLog();
  161. else
  162. SPLogMsg("Skipping CreateMergedPublishLog - as specified in the config template");
  163. break;
  164. case 'ignoreerror':
  165. case 'remote':
  166. case 'seval':
  167. case 'eval':
  168. vRet = SendCmdRemoteMachine(params[0], params[1]);
  169. break;
  170. case 'proxeval':
  171. try
  172. {
  173. SPLogMsg("slaveproxy for " + g_strRemoteMachineName + " executing command " + params[1]);
  174. vRet = MyEval(params[1]);
  175. }
  176. catch(ex)
  177. {
  178. vRet = 'Unhandled exception: ' + ex;
  179. }
  180. SPLogMsg("proxeval result was: " + vRet);
  181. break;
  182. case 'refreshpublicdata':
  183. RefreshPublicData(true);
  184. break;
  185. case 'getspdata':
  186. getspdata();
  187. break;
  188. case 'restarttask': // task id: "machine.nID"
  189. break;
  190. default:
  191. vRet = 'invalid command: ' + cmd;
  192. break;
  193. }
  194. }
  195. catch(ex)
  196. {
  197. SPLogMsg("Exception thrown processing '" + params[0] + "'" + ex);
  198. //throw(ex);
  199. }
  200. return vRet;
  201. }
  202. function SendCmdRemoteMachine(cmd, arg)
  203. {
  204. SPLogMsg("Enter");
  205. var vRet = g_strOK;
  206. var fRetry = false;
  207. if (PrivateData.hRemoteMachine[g_strRemoteMachineName] != null)
  208. {
  209. SPLogMsg("About to " + cmd + ", arg = " + arg);
  210. var mach = PrivateData.hRemoteMachine[g_strRemoteMachineName];
  211. do
  212. {
  213. try
  214. {
  215. vRet = mach.objRemote.Exec(cmd, arg);
  216. }
  217. catch(ex)
  218. { // must have already died
  219. SPLogMsg("Send failed: " + ex);
  220. fRetry = RestartLostMachine();
  221. vRet = g_strSendCmdRemoteMachine + cmd;
  222. }
  223. } while (fRetry);
  224. }
  225. else
  226. {
  227. vRet = g_strSendCmdDisconnect;
  228. }
  229. SPLogMsg("Exit");
  230. return vRet;
  231. }
  232. function AbortRemoteMachines()
  233. {
  234. SPLogMsg("Enter");
  235. var vRet = g_strOK;
  236. if (PrivateData.hRemoteMachine[g_strRemoteMachineName] != null)
  237. {
  238. SPLogMsg("Machine is connected. Aborting...");
  239. var mach = PrivateData.hRemoteMachine[g_strRemoteMachineName];
  240. try
  241. {
  242. mach.objRemote.Unregister();
  243. }
  244. catch(ex)
  245. { // must have already died?
  246. SPLogMsg("Abort failed (UnregisterEventSource): " + ex);
  247. }
  248. try
  249. {
  250. if (mach.fSetConfig)
  251. mach.objRemote.Exec('setmode', 'idle');
  252. delete mach.objRemote;
  253. }
  254. catch(ex)
  255. { // must have already died
  256. SPLogMsg("Abort failed: " + ex);
  257. }
  258. ResetDepotStatus();
  259. if (PublicData.aBuild[0].hMachine[g_strRemoteMachineName])
  260. PublicData.aBuild[0].hMachine[g_strRemoteMachineName].fSuccess = false;
  261. delete PrivateData.hRemoteMachine[g_strRemoteMachineName];
  262. }
  263. SPLogMsg("Exit");
  264. return vRet;
  265. }
  266. function ResetDepotStatus()
  267. {
  268. var nLocalDepotIdx;
  269. var Remote_aBuildZero;
  270. var nDepotIdx;
  271. if (!PrivateData.hRemotePublicDataObj[g_strRemoteMachineName])
  272. return;
  273. Remote_aBuildZero = PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0];
  274. if (!Remote_aBuildZero)
  275. return;
  276. for(nDepotIdx = 0; nDepotIdx < Remote_aBuildZero.aDepot.length; ++nDepotIdx)
  277. {
  278. nLocalDepotIdx = g_aDepotIndex[Remote_aBuildZero.aDepot[nDepotIdx].strName.toLowerCase()];
  279. PublicData.aBuild[0].aDepot[nLocalDepotIdx].strStatus = ABORTED;
  280. PublicData.aBuild[0].aDepot[nLocalDepotIdx].objUpdateCount.nCount++;
  281. }
  282. }
  283. function SetDisconnectedDepotStatus(strErrMsg)
  284. {
  285. var nLocalDepotIdx;
  286. var Remote_aBuildZero;
  287. var nDepotIdx;
  288. var xTask;
  289. var item;
  290. var objMachine;
  291. if (!PrivateData.hRemotePublicDataObj[g_strRemoteMachineName])
  292. return;
  293. Remote_aBuildZero = PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0];
  294. if (!Remote_aBuildZero)
  295. return;
  296. for(nDepotIdx = 0; nDepotIdx < Remote_aBuildZero.aDepot.length; ++nDepotIdx)
  297. {
  298. nLocalDepotIdx = g_aDepotIndex[Remote_aBuildZero.aDepot[nDepotIdx].strName.toLowerCase()];
  299. objDepot = new Depot;
  300. for(item in Remote_aBuildZero.aDepot[nDepotIdx])
  301. {
  302. if (!Remote_aBuildZero.aDepot[nDepotIdx].__isPublicMember(item))
  303. continue;
  304. objDepot[item] = Remote_aBuildZero.aDepot[nDepotIdx][item];
  305. }
  306. objDepot.objUpdateCount = new UpdateCount();
  307. objDepot.aTask = new Array();
  308. xTask = new Task();
  309. xTask.strName = ERROR;
  310. xTask.strStatus = ERROR;
  311. xTask.fSuccess = false;
  312. xTask.strFirstLine = " Connection lost to " + g_strRemoteMachineName + " ";
  313. xTask.strSecondLine = strErrMsg;
  314. objDepot.aTask[0] = xTask;
  315. objDepot.objUpdateCount.nCount = 0;
  316. objDepot.fDisconnected = true;
  317. PublicData.aBuild[0].aDepot[nLocalDepotIdx] = objDepot;
  318. SPLogMsg("Marking " + objDepot.strName + " as disconnected");
  319. objMachine = {fSuccess:false, strBuildPassStatus:""};
  320. if (PublicData.aBuild[0].hMachine[g_strRemoteMachineName])
  321. objMachine.strBuildPassStatus = PublicData.aBuild[0].hMachine[g_strRemoteMachineName].strBuildPassStatus;
  322. PublicData.aBuild[0].hMachine[g_strRemoteMachineName] = objMachine;
  323. }
  324. }
  325. function CreateErrorDepot(strErrMsg)
  326. {
  327. var tmpDepot = new Depot;
  328. var xTask;
  329. tmpDepot.strStatus = ERROR;
  330. tmpDepot.strMachine = g_strRemoteMachineName;
  331. tmpDepot.strName = 'root';
  332. tmpDepot.aTask = new Array();
  333. xTask = new Task();
  334. xTask.strName = ERROR;
  335. xTask.strStatus = ERROR;
  336. xTask.strFirstLine = " Cannot connect to " + g_strRemoteMachineName + " ";
  337. xTask.strSecondLine = strErrMsg;
  338. tmpDepot.aTask[0] = xTask;
  339. if (PublicData.aBuild[0].hMachine[g_strRemoteMachineName])
  340. PublicData.aBuild[0].hMachine[g_strRemoteMachineName].fSuccess = false;
  341. UpdatePublicDataDepot(tmpDepot);
  342. }
  343. function RestartLostMachine()
  344. {
  345. var vRet;
  346. var RemoteObj;
  347. var strTmp;
  348. var nRetryCount;
  349. RemoteObj = PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote;
  350. if (RemoteObj.fMachineReset)
  351. {
  352. if (g_fOKToRestartLostMachine)
  353. {
  354. SPLogMsg("ABOUT TO RESTART REMOTE MACHINE");
  355. vRet = StartRemoteMachine('restart', false);
  356. // StartRemoteMachine recreates RemoteObj -- we must grab an updated copy.
  357. RemoteObj = PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote;
  358. if (vRet == g_strOK)
  359. {
  360. // Wait a little while for the remote machine to get to its completed state.
  361. nRetryCount = 15;
  362. if (!Already)
  363. {
  364. Already = true;
  365. throw new Error(-1, "Bogus nogus");
  366. }
  367. do
  368. {
  369. strTmp = MyEval(newremotemach.objRemote.Exec('getpublic', 'PublicData.strMode'));
  370. if (strTmp == COMPLETED)
  371. break;
  372. Sleep(500);
  373. nRetryCount--;
  374. } while(nRetryCount);
  375. RemoteObj.fStopTryingToGetPublicData = true;
  376. SPLogMsg("Restart remote machine successfull, retries=" + nRetryCount);
  377. return true;
  378. }
  379. }
  380. else
  381. RemoteObj.fStopTryingToGetPublicData = true;
  382. }
  383. SPLogMsg("failed fMachineReset = " + RemoteObj.fMachineReset + ", g_fOKToRestartLostMachine = " + g_fOKToRestartLostMachine);
  384. return false;
  385. }
  386. function StartRemoteMachine(strStart, fReconnectRunningBuild)
  387. {
  388. vRet = ConnectToRemoteMachine(strStart, fReconnectRunningBuild);
  389. if (vRet == g_strOK)
  390. {
  391. SPLogMsg("Started machine " + g_strRemoteMachineName + ", now sending message");
  392. return g_strOK;
  393. }
  394. else
  395. {
  396. if (vRet == "alreadyset")
  397. vRet = "machine in use";
  398. CreateErrorDepot(vRet);
  399. ReportError("Starting build", "Cannot " + strStart + " build on machine : " + g_strRemoteMachineName + "\n" + vRet);
  400. g_MasterQueue.SendMessage('abort', 0);
  401. return vRet;
  402. }
  403. }
  404. function ConnectToRemoteMachine(strStart, fReconnectRunningBuild)
  405. {
  406. var vRet = g_strOK;
  407. var newremotemach;
  408. var strTmp;
  409. var RemotePublicData;
  410. try
  411. {
  412. newremotemach = new RemoteMachine();
  413. newremotemach.objRemote = new RemoteWrapper(g_strRemoteMachineName);
  414. if (fReconnectRunningBuild)
  415. {
  416. strTmp = MyEval(newremotemach.objRemote.Exec('getpublic', 'PublicData.strMode'));
  417. if (strTmp != 'idle')
  418. {
  419. SPLogMsg("Remote machine already busy, same templates?");
  420. RemotePublicData = MyEval(newremotemach.objRemote.Exec('getpublic', 'root'));
  421. if (RemotePublicData.aBuild && RemotePublicData.aBuild[0])
  422. {
  423. if (RemotePublicData.aBuild[0].strEnvTemplate == PublicData.aBuild[0].strEnvTemplate)
  424. {
  425. newremotemach.fSetConfig = true;
  426. PrivateData.hRemoteMachine[g_strRemoteMachineName] = newremotemach;
  427. newremotemach.objRemote.Register();
  428. SPLogMsg("Remote machine env template matches -- no need to restart it");
  429. return vRet;
  430. }
  431. SPLogMsg("Remote templates:" + RemotePublicData.aBuild[0].strConfigTemplate + ", " + RemotePublicData.aBuild[0].strEnvTemplate);
  432. }
  433. else
  434. SPLogMsg("Remote machine is not idle, but aBuild[0] is missing.");
  435. SPLogMsg("Remote machine template mismatch -- forcing idle");
  436. vRet = newremotemach.objRemote.Exec('setmode', 'idle');
  437. SPLogMsg("Setmode returns " + vRet);
  438. }
  439. }
  440. SPLogMsg('Setconfig on machine');
  441. vRet = newremotemach.objRemote.Exec('setstringmap', PrivateData.aStringMap.toString());
  442. if (vRet != g_strOK)
  443. return vRet;
  444. vRet = newremotemach.objRemote.Exec('setconfig', PublicData.aBuild[0].strConfigTemplate);
  445. if (vRet == g_strOK)
  446. {
  447. // If setconfig returns OK, then we know we have the undivided attention of the
  448. // slave machine. If setconfig does not return OK, then the remote machine
  449. // may already be busy with some other build. In this case it would be really
  450. // bad for us to issue a 'setmode idle' command.
  451. newremotemach.fSetConfig = true;
  452. strTmp = MyEval(newremotemach.objRemote.Exec('getpublic', 'PublicData.strMode'));
  453. if (strTmp != 'idle')
  454. vRet = g_strSlaveBusy + " '" + g_strRemoteMachineName + "' (" + strTmp + ")";
  455. }
  456. if (vRet == g_strOK)
  457. {
  458. vRet = newremotemach.objRemote.Exec('setenv', PublicData.aBuild[0].strEnvTemplate);
  459. SPLogMsg(' setenv returned: ' + vRet);
  460. }
  461. if (vRet == g_strOK)
  462. {
  463. vRet = newremotemach.objRemote.Exec('setmode', 'slave');
  464. SPLogMsg(' setmode returned: ' + vRet);
  465. }
  466. if (vRet == g_strOK)
  467. {
  468. vRet = newremotemach.objRemote.Exec(strStart, 0);
  469. SPLogMsg(' ' + strStart + ' returned: ' + vRet);
  470. }
  471. if (vRet == g_strOK)
  472. {
  473. PrivateData.hRemoteMachine[g_strRemoteMachineName] = newremotemach;
  474. newremotemach.objRemote.Register();
  475. SPLogMsg("Started machine " + g_strRemoteMachineName);
  476. }
  477. }
  478. catch(ex)
  479. {
  480. // Oddly, if the remote machine is not found, "ex" has a helpful error message.
  481. // However, if the remote machine is found, has mtscript.exe registered, but mtscript.exe
  482. // is unable to run (somebody deleted it perhaps), then "ex" has only "number" set
  483. // to the value -2147024894.
  484. if (ex.description == null || ex.description.length == 0) //ex.number == -2147024894) // Mtscript.exe cannot run
  485. {
  486. vRet = "An error occurred connecting to mtscript.exe on machine " + g_strRemoteMachineName + ". Error is " + ex.number;
  487. SPLogMsg(vRet + "\n" + ex);
  488. }
  489. else
  490. {
  491. vRet = g_strStartFailed + ex;
  492. SPLogMsg(vRet);
  493. }
  494. }
  495. return vRet;
  496. }
  497. /*
  498. UpdatePublicDataDepot()
  499. Update the local copy of depot public data from our
  500. remote machine.
  501. */
  502. function UpdatePublicDataDepot(objDepot)
  503. {
  504. var nLocalDepotIdx;
  505. nLocalDepotIdx = g_aDepotIndex[objDepot.strName.toLowerCase()];
  506. //JAssert(nLocalDepotIdx != null, "(" + g_strRemoteMachineName + ") " + "Unknown depot! " + objDepot.strName);
  507. if (nLocalDepotIdx == null)
  508. { // This happens when there is an "error" depot - a depot with a bad enlistment directory.
  509. SPLogMsg("Unknown depot " + objDepot.strName + " - assign new index");
  510. TakeThreadLock('NewDepot');
  511. try
  512. {
  513. nLocalDepotIdx = PublicData.aBuild[0].aDepot.length;
  514. PublicData.aBuild[0].aDepot[nLocalDepotIdx] = null; // Extend the length of the array
  515. }
  516. catch(ex)
  517. {
  518. SPLogMsg("Exception while creating a new depot, " + ex);
  519. }
  520. ReleaseThreadLock('NewDepot');
  521. g_aDepotIndex[objDepot.strName.toLowerCase()] = nLocalDepotIdx;
  522. SPLogMsg("New index is " + nLocalDepotIdx + " new length is " + PublicData.aBuild[0].aDepot.length);
  523. }
  524. JAssert(!PublicData.aBuild[0].aDepot[nLocalDepotIdx] ||
  525. PublicData.aBuild[0].aDepot[nLocalDepotIdx].strName == objDepot.strName,
  526. "Overwriting another depot in the master depot list!");
  527. PublicData.aBuild[0].aDepot[nLocalDepotIdx] = objDepot;
  528. }
  529. /*
  530. SmartGetPublic(fForceRoot)
  531. Refresh our copy of the remote machines PublicData.
  532. If we have never retrieved status from the remote machine
  533. then get a full copy.
  534. Otherwise do a "smart" update - ask for a status update
  535. on just the depots that have changed.
  536. Always get fresh copies of elapsed time and error dialog.
  537. */
  538. function SmartGetPublic(fForceRoot)
  539. {
  540. var objTracePoint = { fnName:'SmartGetPublic', nTracePoint:0 };
  541. var fRetry;
  542. var RemoteObj;
  543. do
  544. {
  545. try
  546. {
  547. fRetry = false;
  548. RemoteObj = PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote;
  549. if (RemoteObj.fMachineReset && !g_fOKToRestartLostMachine)
  550. return false;
  551. if (RemoteObj.fStopTryingToGetPublicData)
  552. return true;
  553. SmartGetPublicWorker(objTracePoint, RemoteObj, fForceRoot);
  554. if (RemoteObj.fMachineReset)
  555. SPLogMsg("SmartGetPublic should have failed -- machine is reset");
  556. return true;
  557. }
  558. catch(ex)
  559. {
  560. SPLogMsg("SmartGetPublic() failed, TracePoint = " + objTracePoint.nTracePoint + ", " + ex);
  561. return RestartLostMachine();
  562. }
  563. } while (fRetry);
  564. SPLogMsg("failed to get public data");
  565. return false;
  566. }
  567. /*
  568. GetPublicRoot(objTracePoint, RemoteObj)
  569. Get a full copy of the remote machines PublicData.
  570. Prune the object of the parts we are not interested in.
  571. Place it in our own PublicData.
  572. */
  573. function GetPublicRoot(objTracePoint, RemoteObj)
  574. {
  575. var objRemotePublicData;
  576. objTracePoint.fnName = 'GetPublicRoot';
  577. objRemotePublicData = RemoteObj.Exec('getpublic', 'root');
  578. objRemotePublicData = PrivateData.objUtil.fnMyEval(objRemotePublicData);
  579. objTracePoint.nTracePoint = 1;
  580. if (objRemotePublicData != null)
  581. {
  582. objTracePoint.nTracePoint = 2;
  583. delete objRemotePublicData.nDataVersion;
  584. delete objRemotePublicData.strStatus;
  585. delete objRemotePublicData.strMode;
  586. objTracePoint.nTracePoint = 6;
  587. if (objRemotePublicData.aBuild != null && objRemotePublicData.aBuild[0] != null)
  588. {
  589. objTracePoint.nTracePoint = 7;
  590. if (objRemotePublicData.aBuild[0].hMachine[g_strRemoteMachineName] != null)
  591. {
  592. objTracePoint.nTracePoint = 8;
  593. delete objRemotePublicData.aBuild[0].hMachine[g_strRemoteMachineName].strName;
  594. delete objRemotePublicData.aBuild[0].hMachine[g_strRemoteMachineName].strStatus;
  595. delete objRemotePublicData.aBuild[0].hMachine[g_strRemoteMachineName].strLog
  596. delete objRemotePublicData.aBuild[0].hMachine[g_strRemoteMachineName].aEnlistment;
  597. objTracePoint.nTracePoint = 9;
  598. }
  599. else
  600. SPLogMsg("hMachine IS null");
  601. }
  602. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName] = objRemotePublicData;
  603. }
  604. }
  605. function SmartGetPublicWorker(objTracePoint, RemoteObj, fForceRoot)
  606. {
  607. objTracePoint.fnName = 'SmartGetPublicWorker';
  608. if (fForceRoot ||
  609. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName] == null ||
  610. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].hMachine == null ||
  611. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].hMachine[g_strRemoteMachineName] == null)
  612. {
  613. GetPublicRoot(objTracePoint, RemoteObj);
  614. }
  615. else
  616. {
  617. var str = "";
  618. var comma = "";
  619. var i;
  620. var aDepot;
  621. if (PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0] != null)
  622. {
  623. aDepot = PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].aDepot;
  624. if (aDepot != null)
  625. {
  626. for(i = 0 ; i < aDepot.length; ++i)
  627. {
  628. /*
  629. fDisconnected is never explicitly reset.
  630. Once the connection to the remote machine is reestablished
  631. the Depot object is simply replaced with the depot object from the
  632. remote machine. Thus, "fDisconnected" disappears entirely.
  633. Below, if "fDisconneced" is true we do not list this depot
  634. in the list sent to "getdepotupdate". This forces getdepotupdate
  635. to return status for this depot, since as far as it knows
  636. we do not have any status information for this depot.
  637. */
  638. if (aDepot[i].fDisconnected != true)
  639. {
  640. strDepotID = aDepot[i].strMachine + "," + aDepot[i].strName;
  641. str += comma + "'" + strDepotID + "'" + ":" + aDepot[i].objUpdateCount.nCount;
  642. comma = ",";
  643. }
  644. }
  645. }
  646. }
  647. str = "var _o0 = {" + str + " }; _o0";
  648. objTracePoint.nTracePoint = 1;
  649. var aUpdateDepot = RemoteObj.Exec('getdepotupdate', str);
  650. objTracePoint.nTracePoint = 2;
  651. aUpdateDepot = PrivateData.objUtil.fnMyEval(aUpdateDepot);
  652. objTracePoint.nTracePoint = 3;
  653. for(i = 0; i < aUpdateDepot.length; ++i)
  654. {
  655. if (aUpdateDepot[i] != null)
  656. aDepot[i] = aUpdateDepot[i];
  657. }
  658. var aThingsToFetch =
  659. [
  660. 'PublicData.aBuild[0].objElapsedTimes',
  661. 'PublicData.objDialog',
  662. 'PublicData.aBuild[0].hMachine["' + g_strRemoteMachineName + '"].strBuildPassStatus',
  663. 'PublicData.aBuild[0].hMachine["' + g_strRemoteMachineName + '"].fSuccess'
  664. ];
  665. objTracePoint.nTracePoint = 4;
  666. var obj = RemoteObj.Exec('getpublic', '[' + aThingsToFetch.toString() + ']');
  667. objTracePoint.nTracePoint = 5;
  668. var obj = PrivateData.objUtil.fnMyEval(obj);
  669. objTracePoint.nTracePoint = 6;
  670. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].objElapsedTimes = obj[0];
  671. objTracePoint.nTracePoint = 7;
  672. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].objDialog = obj[1];
  673. objTracePoint.nTracePoint = 8;
  674. if (PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].hMachine != null &&
  675. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].hMachine[g_strRemoteMachineName] != null)
  676. {
  677. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].hMachine[g_strRemoteMachineName].strBuildPassStatus = obj[2];
  678. PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0].hMachine[g_strRemoteMachineName].fSuccess = obj[3];
  679. }
  680. }
  681. }
  682. /*
  683. RefreshPublicData()
  684. We have received notification that the remote machine public
  685. data has changed. We need to grab a copy and place it in our
  686. own public data.
  687. The depot status information can be copied in its entirty, with
  688. just a simple mapping of depot indices.
  689. Each slave machine knows only about the depots its building.
  690. (From enviro_templates\foo_env.xml)
  691. The build machine (this machine) knows about all the depots
  692. being built.
  693. */
  694. function RefreshPublicData(fForceRoot)
  695. {
  696. var iRemoteDepot;
  697. var dlg;
  698. var Remote_aBuildZero;
  699. var nTracePoint = 0;
  700. try // BUGBUG remove the nTracePoint stuff when the cause of the exception here is determined.
  701. {
  702. if (PrivateData.hRemoteMachine[g_strRemoteMachineName] == null)
  703. return;
  704. nTracePoint = 1;
  705. if (!SmartGetPublic(fForceRoot))
  706. {
  707. return;
  708. }
  709. var RemoteObj = PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote;
  710. nTracePoint = 2;
  711. if (PrivateData.hRemotePublicDataObj[g_strRemoteMachineName] != null)
  712. {
  713. delete PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].hRemotePublicDataObj;
  714. // Before we update the depot info, first check to see that
  715. // the remote machine has created aBuild[0], and that we have setup hMachine.
  716. if (PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0] != null && PublicData.aBuild[0].hMachine[g_strRemoteMachineName] != null)
  717. {
  718. nTracePoint = 3;
  719. Remote_aBuildZero = PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].aBuild[0];
  720. for (iRemoteDepot = 0; iRemoteDepot < Remote_aBuildZero.aDepot.length; ++iRemoteDepot)
  721. UpdatePublicDataDepot(Remote_aBuildZero.aDepot[iRemoteDepot]);
  722. // now copy the status info stored in hMachine
  723. nTracePoint = 4;
  724. if (Remote_aBuildZero.hMachine[g_strRemoteMachineName] != null)
  725. {
  726. PublicData.aBuild[0].hMachine[g_strRemoteMachineName] = Remote_aBuildZero.hMachine[g_strRemoteMachineName];
  727. }
  728. nTracePoint = 5;
  729. MergeDates(PublicData, PrivateData.hRemotePublicDataObj[g_strRemoteMachineName]);
  730. nTracePoint = 6;
  731. CheckBuildStatus();
  732. nTracePoint = 7;
  733. }
  734. nTracePoint = 8;
  735. if (PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].objDialog != null)
  736. {
  737. dlg = PrivateData.hRemotePublicDataObj[g_strRemoteMachineName].objDialog;
  738. nTracePoint = 9;
  739. DisplayDialog(dlg);
  740. }
  741. }
  742. }
  743. catch(ex)
  744. {
  745. SPLogMsg("RefreshPublicData caught an exception nTracePoint=" + nTracePoint + " " + ex);
  746. }
  747. }
  748. function ReportError(strTitle, strMsg)
  749. {
  750. dlg = new Dialog();
  751. dlg.fShowDialog = true;
  752. dlg.cDialogIndex = 0;
  753. dlg.strTitle = strTitle;
  754. dlg.strMessage = strMsg;
  755. dlg.aBtnText[0] = "OK";
  756. g_MasterQueue.SendMessage('displaydialog',dlg);
  757. }
  758. function MergeDates(pd, rpd)
  759. {
  760. try
  761. {
  762. var objElapsedTimes;
  763. var objRemoteElapsed;
  764. var aDateMembers;
  765. var i = -1;
  766. var dlg;
  767. var fLocked = false;
  768. if (pd.aBuild[0].objElapsedTimes && rpd.aBuild[0].objElapsedTimes)
  769. {
  770. objElapsedTimes = pd.aBuild[0].objElapsedTimes;
  771. objRemoteElapsed = rpd.aBuild[0].objElapsedTimes;
  772. aDateMembers = ['dateScorch', 'dateSync', 'dateBuild', 'dateCopyFiles', 'datePost'];
  773. TakeThreadLock("MergeDates");
  774. fLocked = true;
  775. for(i = 0; i < aDateMembers.length; ++i)
  776. {
  777. objElapsedTimes[aDateMembers[i] + "Start"] = DateCmp(objElapsedTimes, objRemoteElapsed, aDateMembers[i] + "Start", Math.min);
  778. objElapsedTimes[aDateMembers[i] + "Finish"] = DateCmp(objElapsedTimes, objRemoteElapsed, aDateMembers[i] + "Finish", Math.max);
  779. }
  780. ReleaseThreadLock("MergeDates");
  781. fLocked = false;
  782. }
  783. }
  784. catch(ex)
  785. {
  786. JAssert(false, "(" + g_strRemoteMachineName + ") " + "MergeDates crashed, i = " + i + ", " + ex);
  787. if (fLocked)
  788. ReleaseThreadLock("MergeDates");
  789. }
  790. }
  791. // Compare 2 dates from PublicData.
  792. // Paramaters are: the 2 public data objElapsedTimes objects,
  793. // the member name, and a comparision function (min or max).
  794. //
  795. // An empty time (null) is greater than any other time because an unspecified
  796. // time is considered to mean "now". A value of 'unset' means the value has
  797. // never been touched. For obj1, 'unset' is always replaced with the value
  798. // of obj2, and for obj2 'unset' is treated the same as null.
  799. //
  800. // Boolean Matrix: (* = don't care, null = null or empty)
  801. //
  802. // fnCmp = Math.min: fnCmp = Math.max:
  803. //
  804. // obj1 obj2 result obj1 obj2 result
  805. // --------------------------- --------------------------
  806. // "unset" * obj2 "unset" * obj2
  807. // * "unset" same as obj2=null * "unset" same as obj2=null
  808. // null null null null null null
  809. // null date date ####-> null date null <-####
  810. // date null date date null null
  811. // date1 date2 min(date1,date2) date1 date2 max(date1,date2)
  812. //
  813. // The above matrix can be accomplished by treating null as a time which is
  814. // later than all other times (such as the current time or some always future
  815. // date). Note that "unset" and null must be distiguishable due to the case
  816. // marked with "####" above.
  817. //
  818. function DateCmp(obj1, obj2, member, fnCmp)
  819. {
  820. var t1 = obj1[member];
  821. var t2 = obj2[member];
  822. if (t1 == null || t1.length == 0)
  823. t1 = "December 31 9999 23:59:59 UTC";
  824. else if (t1 == 'unset')
  825. return t2;
  826. if (t2 == null || t2.length == 0 || t2 == 'unset')
  827. t2 = "December 31 9999 23:59:59 UTC";
  828. var delta = Date.parse(t1) - Date.parse(t2);
  829. if (fnCmp(delta, 0) == delta)
  830. return obj1[member];
  831. return obj2[member];
  832. }
  833. function NotifyScriptError(RemoteObj, params)
  834. {
  835. var dlg;
  836. var btn;
  837. if (params != null)
  838. {
  839. dlg = PrivateData.objUtil.fnMyEval(params);
  840. DisplayDialog(dlg);
  841. }
  842. }
  843. function DisplayDialog(dlg)
  844. {
  845. if (dlg.cDialogIndex > g_cDialogIndex)
  846. {
  847. SPLogMsg("*** DisplayDialog " + dlg.cDialogIndex + " " + dlg.strTitle + ", " + dlg.strMessage);
  848. g_cDialogIndex = dlg.cDialogIndex;
  849. g_MasterQueue.SendMessage('displaydialog',dlg);
  850. PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote.Exec('dialog', 'hide,' + dlg.cDialogIndex);
  851. }
  852. }
  853. /*
  854. Check to see if our slave machine has completed a pass
  855. and is waiting for the "nextpass" command.
  856. If it is waiting, then first publish the files in its
  857. publish.log, then signal to harness that this slave is
  858. ready to subscribe and continue to the next pass.
  859. */
  860. function CheckBuildStatus()
  861. {
  862. var strPubLog;
  863. var strStat;
  864. var nPass;
  865. var mach;
  866. mach = PrivateData.hRemoteMachine[g_strRemoteMachineName];
  867. strStat = PublicData.aBuild[0].hMachine[g_strRemoteMachineName].strBuildPassStatus.split(',');
  868. nPass = strStat[1];
  869. strStat = strStat[0];
  870. switch(strStat)
  871. {
  872. case WAIT + SCORCH:
  873. case WAIT + SYNC:
  874. break;
  875. case WAITBEFOREBUILDINGMERGED:
  876. /*
  877. First, get the publish.log
  878. Then, remove build out our list of published files
  879. and remove duplicates.
  880. Then, tell slave to publish this list of file and change
  881. its status to WAITCOPYTOPOSTBUILD
  882. TODO: The slave currently doesn't actually do the file copies. It oughta.
  883. */
  884. if (g_aPublishedEnlistments != null)
  885. return;
  886. SPLogMsg("strBuildPassStatus is " + PublicData.aBuild[0].hMachine[g_strRemoteMachineName].strBuildPassStatus + ", pass is " + g_nBuildPass);
  887. strPubLog = mach.objRemote.Exec('GetPublishLog', 0);
  888. g_aPublishedEnlistments = MyEval(strPubLog);
  889. PreCopyFilesToPostBuild(g_aPublishedEnlistments);
  890. break;
  891. case WAITAFTERMERGED:
  892. strPubLog = mach.objRemote.Exec('GetPublishLog', 0);
  893. FakeCopyFilesToPostBuild(MyEval(strPubLog));
  894. break;
  895. case WAIT + BUILD:
  896. case WAITCOPYTOPOSTBUILD:
  897. case WAITNEXT: // impatiently waiting. Lets poke harness again it case it missed something!
  898. case WAITPHASE:
  899. break;
  900. case WAIT + POSTBUILD:
  901. case WAIT + COPYFILES:
  902. case BUSY:
  903. case "":
  904. break;
  905. case COMPLETED:
  906. g_fOKToRestartLostMachine = true;
  907. break;
  908. default:
  909. JAssert(false, "(" + g_strRemoteMachineName + ") " + "CheckBuildStatus failed: unknown status '" + PublicData.aBuild[0].hMachine[g_strRemoteMachineName].strBuildPassStatus + "'");
  910. break;
  911. }
  912. }
  913. // FakeCopyFilesToPostBuild()
  914. // Called after the postbuild machine build mergedcomponents.
  915. // no file copies need to happen here -- we just need to get the
  916. // files onto the list of published files so that the other slaves
  917. // will pick them up during CopyFilesToSlaves
  918. function FakeCopyFilesToPostBuild(aPublishedEnlistments)
  919. {
  920. var aFiles;
  921. var i;
  922. for(i = 0; i < aPublishedEnlistments.length; ++i)
  923. {
  924. PublishFilesInEnlistment(aPublishedEnlistments[i]);
  925. }
  926. RemoveDuplicateFileNames(g_strRemoteMachineName);
  927. JAssert(aPublishedEnlistments != null, "(" + g_strRemoteMachineName + ") ");
  928. if (aPublishedEnlistments)
  929. {
  930. aFiles = CreateListOfPublishedFiles(FS_NOTYETCOPIED, FS_COPIEDTOMASTER);
  931. vRet = SendCmdRemoteMachine("nextpass", 0);
  932. }
  933. }
  934. // Initiate file copy from the slaves to post build machine
  935. function PreCopyFilesToPostBuild(aPublishedEnlistments)
  936. {
  937. g_aFiles = null;
  938. var i;
  939. for(i = 0; i < aPublishedEnlistments.length; ++i)
  940. {
  941. PublishFilesInEnlistment(aPublishedEnlistments[i]);
  942. }
  943. RemoveDuplicateFileNames(g_strRemoteMachineName);
  944. JAssert(aPublishedEnlistments != null, "(" + g_strRemoteMachineName + ") ");
  945. if (aPublishedEnlistments)
  946. {
  947. g_aFiles = CreateListOfPublishedFiles(FS_NOTYETCOPIED, FS_COPIEDTOMASTER);
  948. strNewStat = PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote.Exec('setbuildpassstatus', WAITCOPYTOPOSTBUILD);
  949. SPLogMsg("setbuildpassstatus to '" + WAITCOPYTOPOSTBUILD + "' returned '" + strNewStat + "'");
  950. PublicData.aBuild[0].hMachine[g_strRemoteMachineName].strBuildPassStatus = strNewStat;
  951. }
  952. }
  953. function CopyFilesToPostBuild()
  954. {
  955. var strNewStat;
  956. if (g_aFiles)
  957. {
  958. //SPLogMsg("CopyFilesToPostBuild " + PrivateData.objUtil.fnUneval(g_aFiles));
  959. strNewStat = PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote.Exec('copyfilestopostbuild', PrivateData.objUtil.fnUneval(g_aFiles));
  960. PublicData.aBuild[0].hMachine[g_strRemoteMachineName].strBuildPassStatus = strNewStat;
  961. }
  962. g_aPublishedEnlistments = null;
  963. }
  964. /*
  965. Generate a merged publish.log file consisting of all the files published on all of the machines.
  966. Publish.log file format is:
  967. Full_Path_Of_file Original_File_path FileNameOnly
  968. BC does not record "Original_File_path" information from the original publish log files
  969. so it simply writes placeholder "BC_EmptyColumn" in this column.
  970. */
  971. function CreateMergedPublishLog()
  972. {
  973. var strSrcName;
  974. var strDest;
  975. var strPostBuildMachineDir ;
  976. var strLogPath;
  977. var sdFile;
  978. var aPartsTo;
  979. var strFileName;
  980. strPostBuildMachineDir = PrivateData.objEnviron.BuildManager.Enlistment;
  981. if (strPostBuildMachineDir.charAt(strPostBuildMachineDir.length - 1) == '\\')
  982. strPostBuildMachineDir = substr(0, strPostBuildMachineDir.length - 1);
  983. strLogPath = "\\\\" +
  984. PrivateData.objEnviron.BuildManager.PostBuildMachine + "\\" +
  985. strPostBuildMachineDir.charAt(0) + "$" +
  986. strPostBuildMachineDir.slice(2) +
  987. PUBLISHLOGFILE;
  988. SPLogMsg("Creating publish.log file " + strLogPath);
  989. PrivateData.objUtil.fnDeleteFileNoThrow(strLogPath);
  990. sdFile = LogCreateTextFile(g_FSObj, strLogPath, true);
  991. for(strFileName in PrivateData.hPublishedFiles)
  992. {
  993. if (!PrivateData.hPublishedFiles.__isPublicMember(strFileName))
  994. continue;
  995. objFile = PrivateData.hPublishedFiles[strFileName];
  996. if (objFile.PublishedFile.strPublishedStatus == FS_ADDTOPUBLISHLOG)
  997. {
  998. // The first reference is always the reference into the
  999. // non-duplicate "hPublisher" entry for this particular file.
  1000. // Any other aReferences entries will be duplicates.
  1001. objFile.PublishedFile.strPublishedStatus = FS_COMPLETE;
  1002. nDirLength = objFile.aReferences[0].strDir.length; // For example: "C:\mt\nt";
  1003. if (nDirLength > 0)
  1004. { // If strDir happened to include a trailing "\", remove it.
  1005. if (objFile.aReferences[0].strDir.charAt(nDirLength - 1) == '\\')
  1006. nDirLength--;
  1007. }
  1008. JAssert(objFile.aReferences[0].strDir.IsEqualNoCase(objFile.PublishedFile.strName.substr(0, nDirLength)));
  1009. strPostBuildFileName = strPostBuildMachineDir + // Example: "F:\nt"
  1010. objFile.PublishedFile.strName.substr(nDirLength); // Example: \public\sdk\lib\i386\uuid.lib
  1011. var aPartsTo = strPostBuildFileName.SplitFileName();
  1012. strSrcName = "\\\\" +
  1013. objFile.aReferences[0].strName + "\\" +
  1014. objFile.aReferences[0].strDir.charAt(0) + "$" +
  1015. objFile.PublishedFile.strName.slice(2);
  1016. sdFile.WriteLine(strPostBuildFileName + " " + strSrcName + " " + aPartsTo[1] + aPartsTo[2]);
  1017. }
  1018. }
  1019. sdFile.Close();
  1020. }
  1021. /*
  1022. PublishFilesInEnlistment
  1023. Called once for each enlistment on the remote machine.
  1024. */
  1025. function PublishFilesInEnlistment(objPublishedFiles)
  1026. {
  1027. JAssert(g_strRemoteMachineName == objPublishedFiles.strLocalMachine, "(" + g_strRemoteMachineName + ") " + "PublishFilesInEnlistment - local machine name doesn't match!");
  1028. var PubData;
  1029. var publishEnlistment;
  1030. var i;
  1031. var nFileCount = objPublishedFiles.aNames.length;
  1032. var strSrcUNCPrefix = MakeUNCPath(objPublishedFiles.strLocalMachine,
  1033. objPublishedFiles.strRootDir,
  1034. "");
  1035. SPLogMsg("Publish files from host " +
  1036. objPublishedFiles.strLocalMachine +
  1037. ", enlistment is " +
  1038. objPublishedFiles.strRootDir);
  1039. if (PrivateData.hPublisher[objPublishedFiles.strLocalMachine] == null)
  1040. {
  1041. PrivateData.hPublisher[objPublishedFiles.strLocalMachine] = new Publisher();
  1042. }
  1043. PubData = PrivateData.hPublisher[objPublishedFiles.strLocalMachine];
  1044. if (PubData.hPublishEnlistment[objPublishedFiles.strRootDir] == null)
  1045. PubData.hPublishEnlistment[objPublishedFiles.strRootDir] = new PublishEnlistment;
  1046. publishEnlistment = PubData.hPublishEnlistment[objPublishedFiles.strRootDir];
  1047. publishEnlistment.strSrcUNCPrefix = strSrcUNCPrefix;
  1048. for(i = 0; i < nFileCount; ++i)
  1049. {
  1050. var file = new PublishedFile();
  1051. SPLogMsg("Published file[" + i + "] " + objPublishedFiles.aNames[i]);
  1052. file.strPublishedStatus = FS_NOTYETCOPIED;
  1053. file.strName = objPublishedFiles.aNames[i];
  1054. publishEnlistment.aPublishedFile[publishEnlistment.aPublishedFile.length] = file;
  1055. }
  1056. }
  1057. function CreateListOfPublishedFiles(strOldPublishedStatus, strNewPublishedStatus)
  1058. {
  1059. try
  1060. {
  1061. var i;
  1062. var PubData = PrivateData.hPublisher[g_strRemoteMachineName];
  1063. var strSDRoot;
  1064. var publishEnlistment;
  1065. var aPublishedEnlistments = new Array();
  1066. var objFiles;
  1067. for (strSDRoot in PubData.hPublishEnlistment)
  1068. {
  1069. if (!PubData.hPublishEnlistment.__isPublicMember(strSDRoot))
  1070. continue;
  1071. publishEnlistment = PubData.hPublishEnlistment[strSDRoot];
  1072. objFiles = new Object();
  1073. objFiles.strLocalMachine = g_strRemoteMachineName;
  1074. objFiles.strRootDir = strSDRoot;
  1075. objFiles.aNames = new Array();
  1076. for (i = 0; i < publishEnlistment.aPublishedFile.length; ++i)
  1077. {
  1078. if (publishEnlistment.aPublishedFile[i].strPublishedStatus == strOldPublishedStatus)
  1079. {
  1080. SPLogMsg("Published file: " + publishEnlistment.aPublishedFile[i].strName);
  1081. objFiles.aNames[objFiles.aNames.length] = publishEnlistment.aPublishedFile[i].strName;
  1082. publishEnlistment.aPublishedFile[i].strPublishedStatus = strNewPublishedStatus;
  1083. }
  1084. }
  1085. aPublishedEnlistments[aPublishedEnlistments.length] = objFiles;
  1086. }
  1087. }
  1088. catch(ex)
  1089. {
  1090. SPLogMsg("an error occurred while executing 'CreateListOfPublishedFiles'\n" + ex);
  1091. throw ex;
  1092. }
  1093. return aPublishedEnlistments;
  1094. }
  1095. /*
  1096. Copy all Publushed files to the remote machines
  1097. */
  1098. function CopyFilesToSlaves()
  1099. {
  1100. var strFileName;
  1101. var aStrSrcUNCPrefix = new Array(); // Array of enlistment UNCs for this machine
  1102. var hEnlistments = new Object();
  1103. var strSDRoot;
  1104. var i = 0;
  1105. var j;
  1106. var aReferences;
  1107. var aNames = new Array();
  1108. var nEnlistments = 0;
  1109. try
  1110. {
  1111. // First, make a list of my enlistments
  1112. for(i = 0; i < PrivateData.objEnviron.Machine.length; ++i)
  1113. {
  1114. if (PrivateData.objEnviron.Machine[i].Name.IsEqualNoCase(g_strRemoteMachineName))
  1115. {
  1116. // SPLogMsg("hEnlistments[" + PrivateData.objEnviron.Machine[i].Enlistment + "] = 1");
  1117. hEnlistments[PrivateData.objEnviron.Machine[i].Enlistment] = 1;
  1118. nEnlistments++;
  1119. aStrSrcUNCPrefix[aStrSrcUNCPrefix.length] = MakeUNCPath(g_strRemoteMachineName, PrivateData.objEnviron.Machine[i].Enlistment, "");
  1120. }
  1121. }
  1122. // Now for each file, add it to the list of files to copy.
  1123. for(strFileName in PrivateData.hPublishedFiles)
  1124. {
  1125. if (!PrivateData.hPublishedFiles.__isPublicMember(strFileName))
  1126. continue;
  1127. ScanEnlistments:
  1128. for(i = 0; i < aStrSrcUNCPrefix.length; ++i)
  1129. {
  1130. // Optimization: If a slave has only one enlistment, and
  1131. // the slave generated this file, do not copy it
  1132. SPLogMsg("File " + strFileName + " status is " + PrivateData.hPublishedFiles[strFileName].PublishedFile.strPublishedStatus);
  1133. if (PrivateData.hPublishedFiles[strFileName].PublishedFile.strPublishedStatus == FS_COPYTOSLAVE)
  1134. {
  1135. // SPLogMsg("nEnlistments = " + nEnlistments);
  1136. if (nEnlistments == 1)
  1137. {
  1138. aReferences = PrivateData.hPublishedFiles[strFileName].aReferences;
  1139. for(j = 0; j < aReferences.length; ++j)
  1140. {
  1141. // SPLogMsg("aReferences[" + j + "].strName = " + aReferences[j].strName + ", " + aReferences[j].strDir);
  1142. if (g_strRemoteMachineName == aReferences[j].strName)
  1143. {
  1144. if (hEnlistments[aReferences[j].strDir] != null)
  1145. {
  1146. SPLogMsg("Optimizing out copy of " + strFileName + " to " + aStrSrcUNCPrefix[i] + strFileName);
  1147. continue ScanEnlistments;
  1148. }
  1149. }
  1150. }
  1151. }
  1152. // BUGBUG: This is supposed to specify which enlistment on the slave machine to copy to.
  1153. // It does not. Thus the for "i" loop is irrelavent.
  1154. // If we ever support multiple enlistments on a machine, this will be a problem.
  1155. aNames[aNames.length] = strFileName;
  1156. }
  1157. }
  1158. }
  1159. return PrivateData.hRemoteMachine[g_strRemoteMachineName].objRemote.Exec('copyfilesfrompostbuildtoslave', PrivateData.objUtil.fnUneval(aNames));
  1160. }
  1161. catch(ex)
  1162. {
  1163. SPLogMsg("an error occurred while executing 'CopyFilesToSlaves'\n" + ex);
  1164. throw ex;
  1165. }
  1166. }
  1167. // This oughta be a member of PublishedFiles.
  1168. function PublishedFilesAddReference(obj, strMachineName, strSDRoot)
  1169. {
  1170. var nCount = obj.aReferences.length;
  1171. obj.aReferences[nCount] = new DepotInfo;
  1172. obj.aReferences[nCount].strName = strMachineName;
  1173. obj.aReferences[nCount].strDir = strSDRoot;
  1174. }
  1175. /*
  1176. This function gets called to merge each machines published files into the
  1177. global list of files.
  1178. When a file is published its status defaults to FS_NOTYETCOPIED. If a
  1179. FS_NOTYETCOPIED file is encountered, and it is found in the global
  1180. list of files (PrivateData.hPublishedFiles), then it is marked FS_DUPLICATE, and reported.
  1181. Otherwise it is added to PrivateData.hPublishedFiles.
  1182. */
  1183. function RemoveDuplicateFileNames()
  1184. {
  1185. TakeThreadLock('RemoveDuplicates');
  1186. try
  1187. {
  1188. var i;
  1189. var PubData = PrivateData.hPublisher[g_strRemoteMachineName];
  1190. var strSDRoot;
  1191. var publishEnlistment;
  1192. var strFileName;
  1193. var objPublishedFiles;
  1194. var n;
  1195. var strSDRootPublic;
  1196. for (strSDRoot in PubData.hPublishEnlistment)
  1197. {
  1198. if (!PubData.hPublishEnlistment.__isPublicMember(strSDRoot))
  1199. continue;
  1200. strSDRootPublic = strSDRoot + "\\Public";
  1201. publishEnlistment = PubData.hPublishEnlistment[strSDRoot];
  1202. for (i = 0; i < publishEnlistment.aPublishedFile.length; ++i)
  1203. {
  1204. strFileName = publishEnlistment.aPublishedFile[i].strName.slice(strSDRootPublic.length).toLowerCase();
  1205. if (publishEnlistment.aPublishedFile[i].strPublishedStatus == FS_NOTYETCOPIED)
  1206. {
  1207. if (PrivateData.hPublishedFiles[strFileName] != null)
  1208. {
  1209. SPLogMsg("duplicate file eliminated: " + strFileName);
  1210. publishEnlistment.aPublishedFile[i].strPublishedStatus = FS_DUPLICATE;
  1211. }
  1212. else
  1213. {
  1214. objPublishedFiles = new PublishedFiles;
  1215. PrivateData.hPublishedFiles[strFileName] = objPublishedFiles;
  1216. PrivateData.hPublishedFiles[strFileName].PublishedFile = publishEnlistment.aPublishedFile[i];
  1217. }
  1218. // TODO: Place the enlistment name instead of strSDRoot.
  1219. PublishedFilesAddReference(PrivateData.hPublishedFiles[strFileName], g_strRemoteMachineName, strSDRoot);
  1220. }
  1221. else
  1222. { // The file has already ben processed. Assert that we have an entry in hPublishedFiles.
  1223. JAssert(PrivateData.hPublishedFiles[strFileName] != null, "(" + g_strRemoteMachineName + ") ");
  1224. }
  1225. }
  1226. }
  1227. }
  1228. catch(ex)
  1229. {
  1230. ReleaseThreadLock('RemoveDuplicates');
  1231. SPLogMsg("an error occurred while executing 'RemoveDuplicateFileNames " + ex);
  1232. throw ex;
  1233. }
  1234. ReleaseThreadLock('RemoveDuplicates');
  1235. }
  1236. function RemoteWrapper(strMachineName)
  1237. {
  1238. RemoteWrapper.prototype.Exec = RemoteWrapperExec;
  1239. RemoteWrapper.prototype.StatusValue = RemoteWrapperStatusValue;
  1240. RemoteWrapper.prototype.Connect = RemoteWrapperConnect;
  1241. RemoteWrapper.prototype.Register = RemoteWrapperRegister;
  1242. RemoteWrapper.prototype.Unregister = RemoteWrapperUnregister;
  1243. RemoteWrapper.prototype.Reconnect = RemoteWrapperReconnect;
  1244. RemoteWrapper.prototype.VersionCheck = RemoteWrapperVersionCheck;
  1245. RemoteWrapper.prototype.RetryCmd = RemoteWrapperRetryCmd;
  1246. RemoteWrapper.strErrorMessage = "";
  1247. this.fRegistered = false;
  1248. this.strMachineName = strMachineName;
  1249. this.fMachineReset = false;
  1250. this.Connect(strMachineName, true);
  1251. this.ex = null;
  1252. }
  1253. function RemoteWrapperConnect(strMachineName, fThrow)
  1254. {
  1255. try
  1256. {
  1257. SPLogMsg("Attempting to connect to " + strMachineName);
  1258. this.obj = new ActiveXObject('MTScript.Remote', strMachineName);
  1259. this.strErrorMessage = "";
  1260. this.VersionCheck();
  1261. return true;
  1262. }
  1263. catch(ex)
  1264. {
  1265. SPLogMsg("CONNECTION TO " + strMachineName + " FAILED " + ex);
  1266. this.strErrorMessage = "" + ex;
  1267. if (fThrow)
  1268. throw ex;
  1269. return false;
  1270. }
  1271. }
  1272. function RemoteWrapperReconnect()
  1273. {
  1274. var Attempts = 1; // COM tries long and hard to make the connection. No need to prolong things.
  1275. var ex;
  1276. SPLogMsg("Attempting to reconnect");
  1277. while(Attempts > 0)
  1278. {
  1279. try
  1280. {
  1281. this.Connect(this.strMachineName, true);
  1282. if (this.fRegistered)
  1283. this.Register();
  1284. this.strErrorMessage = "";
  1285. SPLogMsg("RECONNECTED!");
  1286. return true;
  1287. }
  1288. catch(ex)
  1289. {
  1290. }
  1291. --Attempts;
  1292. if (Attempts)
  1293. {
  1294. SPLogMsg("Wait 1 sec then retry");
  1295. Sleep(1000);
  1296. }
  1297. }
  1298. SPLogMsg("Reconnect failed");
  1299. this.obj = null;
  1300. ResetSync(g_SlaveProxyWaitFor[2]);
  1301. return false;
  1302. }
  1303. function RemoteWrapperVersionCheck()
  1304. {
  1305. var nMajor = this.obj.HostMajorVer;
  1306. var nMinor = this.obj.HostMinorVer;
  1307. if (nMajor != HostMajorVer || nMinor != HostMinorVer)
  1308. {
  1309. throw Error(-1, "Host version does not match remote host. (" + HostMajorVer + "." + HostMinorVer + ") != (" + nMajor + "." + nMinor + ")");
  1310. }
  1311. }
  1312. function RemoteWrapperExec(msg,params)
  1313. {
  1314. return this.RetryCmd('exec', 'this.obj.Exec(' + UnevalString(msg) + ',' + UnevalString(params) + ')');
  1315. }
  1316. function RemoteWrapperStatusValue(nIndex)
  1317. {
  1318. return this.RetryCmd('StatusValue', 'this.obj.StatusValue(' + nIndex + ')');
  1319. }
  1320. function RemoteWrapperRetryCmd(strOp, strCmd)
  1321. {
  1322. var ex = this.ex;
  1323. var vRet;
  1324. var Attempts = 2;
  1325. var ConnectAttempts;
  1326. var objOld;
  1327. var strTmp;
  1328. try
  1329. {
  1330. do
  1331. {
  1332. if (!this.obj)
  1333. {
  1334. if (this.fMachineReset || !this.Reconnect())
  1335. break;
  1336. strTmp = MyEval(this.obj.Exec('getpublic', 'PublicData.strMode'));
  1337. if (strTmp == 'idle')
  1338. {
  1339. this.strErrorMessage = "Remote machine has reset -- ";
  1340. if (g_fOKToRestartLostMachine)
  1341. this.strErrorMessage += "attempting to reconnect";
  1342. else
  1343. this.strErrorMessage += "build failed";
  1344. this.fMachineReset = true;
  1345. ex = new Error(-1, this.strErrorMessage);
  1346. delete this.obj;
  1347. break;
  1348. }
  1349. }
  1350. if (this.obj)
  1351. {
  1352. try
  1353. {
  1354. vRet = eval(strCmd);
  1355. return vRet;
  1356. }
  1357. catch(ex)
  1358. {
  1359. this.strErrorMessage = "" + ex;
  1360. SPLogMsg(strOp + " " + strCmd + " FAILED, " + ex);
  1361. this.obj = null;
  1362. }
  1363. }
  1364. --Attempts;
  1365. }
  1366. while(Attempts > 0);
  1367. SetDisconnectedDepotStatus(this.strErrorMessage);
  1368. SPLogMsg("Unable to reestablish connection");
  1369. }
  1370. catch(ex2)
  1371. {
  1372. SPLogMsg("Unexpected exception " + ex2);
  1373. }
  1374. this.ex = ex;
  1375. throw ex;
  1376. }
  1377. function RemoteWrapperRegister()
  1378. {
  1379. SPLogMsg("Attempting to register");
  1380. RegisterEventSource(this.obj);
  1381. this.fRegistered = true;
  1382. SPLogMsg("Registered");
  1383. }
  1384. function RemoteWrapperUnregister()
  1385. {
  1386. if (this.fRegistered)
  1387. UnregisterEventSource(this.obj);
  1388. this.fRegistered = false;
  1389. }
  1390. function getspdata()
  1391. {
  1392. var pd1;
  1393. var pd2;
  1394. var o1;
  1395. var o2;
  1396. var nTracePoint = 0;
  1397. try
  1398. {
  1399. nTracePoint = 1;
  1400. nTracePoint = 2;
  1401. SPLogMsg("getspdata " + g_strRemoteMachineName);
  1402. nTracePoint = 3;
  1403. pd1 = PrivateData.objUtil.fnUneval(PublicData);
  1404. nTracePoint = 4;
  1405. pd1 = PrivateData.objUtil.fnUneval(PrivateData);
  1406. nTracePoint = 5;
  1407. debugger;
  1408. LogMsg(pd1);
  1409. LogMsg(pd2);
  1410. nTracePoint = 6;
  1411. o1 = MyEval(pd1);
  1412. nTracePoint = 7;
  1413. o2 = MyEval(pd2);
  1414. nTracePoint = 8;
  1415. }
  1416. catch(ex)
  1417. {
  1418. SPLogMsg("Exception at point " + nTracePoint + " thrown processing 'getspdata'" + ex);
  1419. debugger;
  1420. }
  1421. }