001/* 002 * #%L 003 * Netarchivesuite - heritrix 3 monitor 004 * %% 005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023 024package dk.netarkivet.heritrix3.monitor.resources; 025 026import java.io.File; 027import java.io.IOException; 028import java.net.URL; 029import java.text.NumberFormat; 030import java.util.List; 031import java.util.Locale; 032 033import javax.servlet.ServletContext; 034import javax.servlet.ServletOutputStream; 035import javax.servlet.http.HttpServletRequest; 036import javax.servlet.http.HttpServletResponse; 037 038import org.netarchivesuite.heritrix3wrapper.jaxb.Job; 039 040import com.antiaction.common.filter.Caching; 041import com.antiaction.common.templateengine.TemplateBuilderFactory; 042 043import dk.netarkivet.common.utils.Settings; 044import dk.netarkivet.harvester.HarvesterSettings; 045import dk.netarkivet.harvester.datamodel.HarvestDefinitionDAO; 046import dk.netarkivet.harvester.datamodel.JobStatus; 047import dk.netarkivet.heritrix3.monitor.Heritrix3JobMonitor; 048import dk.netarkivet.heritrix3.monitor.Heritrix3JobMonitorThread; 049import dk.netarkivet.heritrix3.monitor.NASEnvironment; 050import dk.netarkivet.heritrix3.monitor.NASUser; 051import dk.netarkivet.heritrix3.monitor.ResourceAbstract; 052import dk.netarkivet.heritrix3.monitor.ResourceManagerAbstract; 053import dk.netarkivet.heritrix3.monitor.HttpLocaleHandler.HttpLocale; 054 055public class H3JobResource implements ResourceAbstract { 056 057 private NASEnvironment environment; 058 059 protected int R_JOB = -1; 060 061 @Override 062 public void resources_init(NASEnvironment environment) { 063 this.environment = environment; 064 } 065 066 @Override 067 public void resources_add(ResourceManagerAbstract resourceManager) { 068 R_JOB = resourceManager.resource_add(this, "/job/<numeric>/", false); 069 } 070 071 @Override 072 public void resource_service(ServletContext servletContext, NASUser nas_user, HttpServletRequest req, HttpServletResponse resp, HttpLocale httpLocale, int resource_id, List<Integer> numerics, String pathInfo) throws IOException { 073 if (NASEnvironment.contextPath == null) { 074 NASEnvironment.contextPath = req.getContextPath(); 075 } 076 if (NASEnvironment.servicePath == null) { 077 NASEnvironment.servicePath = req.getContextPath() + req.getServletPath() + "/"; 078 } 079 String method = req.getMethod().toUpperCase(); 080 if (resource_id == R_JOB) { 081 if ("GET".equals(method)) { 082 job(req, resp, httpLocale, numerics); 083 } 084 } 085 } 086 087 public void job(HttpServletRequest req, HttpServletResponse resp, HttpLocale httpLocale, List<Integer> numerics) throws IOException { 088 Locale locale = httpLocale.locale; 089 NumberFormat numberFormat = NumberFormat.getInstance(locale); 090 resp.setContentType("text/html; charset=UTF-8"); 091 ServletOutputStream out = resp.getOutputStream(); 092 Caching.caching_disable_headers(resp); 093 094 TemplateBuilderFactory<MasterTemplateBuilder> masterTplBuilderFactory = TemplateBuilderFactory.getInstance(environment.templateMaster, "master.tpl", "UTF-8", MasterTemplateBuilder.class); 095 MasterTemplateBuilder masterTplBuilder = masterTplBuilderFactory.getTemplateBuilder(); 096 097 StringBuilder sb = new StringBuilder(); 098 099 long jobId = numerics.get(0); 100 Heritrix3JobMonitor h3Job = environment.h3JobMonitorThread.getRunningH3Job(jobId); 101 Job job; 102 103 HarvestDefinitionDAO dao = HarvestDefinitionDAO.getInstance(); 104 105 if (h3Job != null && !h3Job.bInitialized) { 106 h3Job.init(); 107 } 108 109 dk.netarkivet.harvester.datamodel.Job nasJob = Heritrix3JobMonitorThread.jobDAO.read(jobId); 110 111 String action = req.getParameter("action"); 112 if (action != null && action.length() > 0) { 113 if ("failed".equalsIgnoreCase(action)) { 114 if (nasJob != null && (h3Job == null || !h3Job.isReady())) { 115 nasJob.setStatus(JobStatus.FAILED); 116 Heritrix3JobMonitorThread.jobDAO.update(nasJob); 117 } 118 } 119 } 120 121 if (nasJob == null || nasJob.getStatus() == JobStatus.DONE || nasJob.getStatus() == JobStatus.FAILED || nasJob.getStatus() == JobStatus.FAILED_REJECTED) { 122 sb.append("NAS Job "); 123 sb.append(jobId); 124 sb.append(" is in state "); 125 sb.append(nasJob.getStatus().toString()); 126 sb.append("."); 127 } else { 128 if (h3Job == null || !h3Job.isReady()) { 129 sb.append("Job "); 130 sb.append(jobId); 131 sb.append(" is not currently monitored. Maybe Heritrix 3 is not running at this point in time."); 132 if (nasJob != null && nasJob.getStatus() == JobStatus.STARTED && (h3Job == null || !h3Job.isReady())) { 133 sb.append("<br />\n"); 134 sb.append("<a href=\"?action="); 135 sb.append("failed"); 136 sb.append("\""); 137 sb.append(" onclick=\"return confirm('Are you sure you wish to fail the job currently being crawled ?')\""); 138 sb.append(" class=\"btn btn-danger\">"); 139 sb.append("<i class=\\\"icon-white icon-trash\\\"></i>"); 140 sb.append("Set job status to failed!"); 141 sb.append("</a>"); 142 } 143 } else { 144 if (action != null && action.length() > 0) { 145 if ("build".equalsIgnoreCase(action)) { 146 h3Job.h3wrapper.buildJobConfiguration(h3Job.jobname); 147 } 148 if ("launch".equalsIgnoreCase(action)) { 149 h3Job.h3wrapper.launchJob(h3Job.jobname); 150 } 151 if ("pause".equalsIgnoreCase(action)) { 152 h3Job.h3wrapper.pauseJob(h3Job.jobname); 153 } 154 if ("unpause".equalsIgnoreCase(action)) { 155 h3Job.h3wrapper.unpauseJob(h3Job.jobname); 156 } 157 if ("checkpoint".equalsIgnoreCase(action)) { 158 h3Job.h3wrapper.checkpointJob(h3Job.jobname); 159 } 160 if ("terminate".equalsIgnoreCase(action)) { 161 h3Job.h3wrapper.terminateJob(h3Job.jobname); 162 } 163 if ("teardown".equalsIgnoreCase(action)) { 164 h3Job.h3wrapper.teardownJob(h3Job.jobname); 165 } 166 } 167 168 //job.setStatus(JobStatus.FAILED); 169 170 h3Job.update(); 171 172 sb.append("<div>\n"); 173 174 sb.append("<div style=\"float:left;min-width: 300px;\">\n"); 175 176 sb.append("JobId: <a href=\"/History/Harveststatus-jobdetails.jsp?jobID="+h3Job.jobId+"\">"); 177 sb.append(h3Job.jobId); 178 sb.append("</a><br />\n"); 179 if (h3Job.jobResult != null && h3Job.jobResult.job != null) { 180 sb.append("JobState: "); 181 sb.append(h3Job.jobResult.job.crawlControllerState); 182 sb.append("<br />\n"); 183 } 184 String harvestName = dao.getHarvestName(h3Job.job.getOrigHarvestDefinitionID()); 185 sb.append("OrigHarvestDefinitionName: <a href=\"/HarvestDefinition/Definitions-edit-selective-harvest.jsp?harvestname="+harvestName.replace(' ', '+')+"\">"); 186 sb.append(harvestName); 187 sb.append("</a><br />\n"); 188 sb.append("HarvestNum: "); 189 sb.append(h3Job.job.getHarvestNum()); 190 sb.append("<br />\n"); 191 sb.append("Snapshot: "); 192 sb.append(h3Job.job.isSnapshot()); 193 sb.append("<br />\n"); 194 sb.append("Channel: "); 195 sb.append(h3Job.job.getChannel()); 196 sb.append("<br />\n"); 197 sb.append("TemplateName: <a href=\""); 198 sb.append("/History/Harveststatus-download-job-harvest-template.jsp?JobID="); 199 sb.append(h3Job.jobId); 200 sb.append("\">"); 201 sb.append(h3Job.job.getOrderXMLName()); 202 sb.append("</a><br />\n"); 203 sb.append("CountDomains: "); 204 sb.append(h3Job.job.getCountDomains()); 205 sb.append("<br />\n"); 206 sb.append("MaxBytesPerDomain: "); 207 sb.append(numberFormat.format(h3Job.job.getMaxBytesPerDomain())); 208 sb.append("<br />\n"); 209 sb.append("MaxObjectsPerDomain: "); 210 sb.append(numberFormat.format(h3Job.job.getMaxObjectsPerDomain())); 211 sb.append("<br />\n"); 212 sb.append("MaxJobRunningTime: "); 213 sb.append(h3Job.job.getMaxJobRunningTime()); 214 sb.append(" ms.<br />\n"); 215 216 sb.append("</div>\n"); 217 218 /* Heritrix3 WebUI */ 219 sb.append("<div style=\"float:left;position: absolute;left:600px;\">\n"); 220 sb.append("<a href=\""); 221 sb.append(h3Job.hostUrl); 222 sb.append("\" class=\"btn btn-default\">"); 223 sb.append("Heritrix3 WebUI"); 224 sb.append("</a>"); 225 226 sb.append("</div>\n"); 227 228 sb.append("<div style=\"clear:both;\"></div>"); 229 sb.append("</div>"); 230 231 /* line 1 */ 232 233 sb.append("<h4>Job details</h4>\n"); 234 sb.append("<div>\n"); 235 236 /* Progression/Queues */ 237 sb.append("<a href=\""); 238 sb.append("/History/Harveststatus-running-jobdetails.jsp?jobID="); 239 sb.append(h3Job.jobId); 240 sb.append("\" class=\"btn btn-default\">"); 241 sb.append("Progression/Queues"); 242 sb.append("</a>"); 243 244 sb.append(" "); 245 246 /* Show Crawllog on H3 GUI*/ 247 URL url1 = new URL(h3Job.hostUrl); 248 sb.append("<a href=\""); 249 sb.append("https://"+url1.getHost()+":"+url1.getPort()+"/engine/anypath/"); 250 sb.append(h3Job.crawlLogFilePath); 251 sb.append("?format=paged&pos=-1&lines=-1000&reverse=y"); 252 sb.append("\" class=\"btn btn-default\">"); 253 sb.append("Remote H3 Crawllog viewer"); 254 sb.append("</a>"); 255 256 sb.append(" "); 257 258 /* Crawllog */ 259 sb.append("<a href=\""); 260 sb.append(NASEnvironment.servicePath); 261 sb.append("job/"); 262 sb.append(h3Job.jobId); 263 sb.append("/crawllog/"); 264 sb.append("\" class=\"btn btn-default\">"); 265 sb.append("View/Search in cached Crawllog"); 266 sb.append("</a>"); 267 268 sb.append(" "); 269 270 /* Reports */ 271 sb.append("<a href=\""); 272 sb.append(NASEnvironment.servicePath); 273 sb.append("job/"); 274 sb.append(h3Job.jobId); 275 sb.append("/report/"); 276 sb.append("\" class=\"btn btn-default\">"); 277 sb.append("Reports"); 278 sb.append("</a>"); 279 280 sb.append(" "); 281 282 sb.append("</div>\n"); 283 284 /* line 2 */ 285 286 sb.append("<h4>Queue actions</h4>\n"); 287 sb.append("<div>\n"); 288 289 /* Show/delete Frontier */ 290 sb.append("<a href=\""); 291 sb.append(NASEnvironment.servicePath); 292 sb.append("job/"); 293 sb.append(h3Job.jobId); 294 sb.append("/frontier/"); 295 sb.append("\" class=\"btn btn-default\">"); 296 sb.append("Browse/delete Frontier"); 297 sb.append("</a>"); 298 299 sb.append(" "); 300 301 /* Delete from Frontier */ 302 sb.append("<a href=\""); 303 sb.append(NASEnvironment.servicePath); 304 sb.append("job/"); 305 sb.append(h3Job.jobId); 306 sb.append("/frontier-delete/"); 307 sb.append("\" class=\"btn btn-default\">"); 308 sb.append("Delete from Frontier"); 309 sb.append("</a>"); 310 311 sb.append(" "); 312 313 /* Add RejectRules */ 314 sb.append("<a href=\""); 315 sb.append(NASEnvironment.servicePath); 316 sb.append("job/"); 317 sb.append(h3Job.jobId); 318 sb.append("/filter/"); 319 sb.append("\" class=\"btn btn-default\">"); 320 sb.append("Add RejectRules"); 321 sb.append("</a>"); 322 323 sb.append(" "); 324 325 /* Modify Budget */ 326 sb.append("<a href=\""); 327 sb.append(NASEnvironment.servicePath); 328 sb.append("job/"); 329 sb.append(h3Job.jobId); 330 sb.append("/budget/"); 331 sb.append("\" class=\"btn btn-default\">"); 332 sb.append("Modify budget"); 333 sb.append("</a>"); 334 335 sb.append(" "); 336 337 sb.append("</div>\n"); 338 339 if (h3Job.jobResult != null && h3Job.jobResult.job != null) { 340 341 /* line 3 */ 342 343 sb.append("<h4>Job actions</h4>\n"); 344 sb.append("<div style=\"margin-bottom:30px;\">\n"); 345 346 job = h3Job.jobResult.job; 347 348 for (int i=0; i<job.availableActions.size(); ++i) { 349 if (i > 0) { 350 sb.append(" "); 351 } 352 // disabled="disabled" 353 sb.append("<a href=\"?action="); 354 String thisAction = job.availableActions.get(i); 355 sb.append(thisAction); 356 sb.append("\""); 357 if("terminate".equals(thisAction) || "teardown".equals(thisAction)) { 358 sb.append(" onclick=\"return confirm('Are you sure you wish to "); 359 sb.append(thisAction); 360 sb.append(" the job currently being crawled ?')\""); 361 sb.append(" class=\"btn btn-danger\">"); 362 sb.append("<i class=\\\"icon-white icon-trash\\\"></i>"); 363 } else { 364 sb.append(" class=\"btn btn-default\">"); 365 } 366 sb.append(job.availableActions.get(i).substring(0, 1).toUpperCase()+job.availableActions.get(i).substring(1)); 367 sb.append("</a>"); 368 } 369 370 sb.append(" "); 371 372 /* Open Scripting Console */ 373 sb.append("<a href=\""); 374 sb.append(NASEnvironment.servicePath); 375 sb.append("job/"); 376 sb.append(h3Job.jobId); 377 sb.append("/script/"); 378 sb.append("\" class=\"btn btn-default\">"); 379 sb.append("Open Scripting Console"); 380 sb.append("</a>"); 381 382 sb.append(" "); 383 384 /* View scripting_events.log */ 385 File logDir = new File(h3Job.crawlLogFilePath); 386 387 sb.append("<a href=\""); 388 URL url = new URL(h3Job.hostUrl); 389 sb.append("https://"+url.getHost()+":"+url.getPort()+"/engine/anypath"+logDir.getParentFile().getAbsolutePath()+"/scripting_events.log"); 390 sb.append("\" class=\"btn btn-default\">"); 391 sb.append("View scripting_events.log"); 392 sb.append("</a>"); 393 394 sb.append("</div>\n"); 395 396 sb.append("shortName: "); 397 sb.append(job.shortName); 398 sb.append("<br />\n"); 399 sb.append("crawlControllerState: "); 400 sb.append(job.crawlControllerState); 401 sb.append("<br />\n"); 402 sb.append("crawlExitStatus: "); 403 sb.append(job.crawlExitStatus); 404 sb.append("<br />\n"); 405 sb.append("statusDescription: "); 406 sb.append(job.statusDescription); 407 sb.append("<br />\n"); 408 sb.append("url: "); 409 sb.append("<a href=\""); 410 sb.append(h3Job.hostUrl+"/job/"+h3Job.jobname); 411 sb.append("/"); 412 sb.append("\">"); 413 sb.append(h3Job.hostUrl+"/job/"+h3Job.jobname); 414 sb.append("</a>"); 415 sb.append("<br />\n"); 416 if (job.jobLogTail != null) { 417 for (int i =0; i<job.jobLogTail.size(); ++i) { 418 sb.append("jobLogTail["); 419 sb.append(i); 420 sb.append("]: "); 421 sb.append(job.jobLogTail.get(i)); 422 sb.append("<br />\n"); 423 } 424 } 425 if (job.uriTotalsReport != null) { 426 sb.append("uriTotalsReport.downloadedUriCount: "); 427 sb.append(job.uriTotalsReport.downloadedUriCount); 428 sb.append("<br />\n"); 429 sb.append("uriTotalsReport.queuedUriCount: "); 430 sb.append(job.uriTotalsReport.queuedUriCount); 431 sb.append("<br />\n"); 432 sb.append("uriTotalsReport.totalUriCount: "); 433 sb.append(job.uriTotalsReport.totalUriCount); 434 sb.append("<br />\n"); 435 sb.append("uriTotalsReport.futureUriCount: "); 436 sb.append(job.uriTotalsReport.futureUriCount); 437 sb.append("<br />\n"); 438 } 439 if (job.sizeTotalsReport != null) { 440 sb.append("sizeTotalsReport.dupByHash: "); 441 sb.append(job.sizeTotalsReport.dupByHash); 442 sb.append("<br />\n"); 443 sb.append("sizeTotalsReport.dupByHashCount: "); 444 sb.append(job.sizeTotalsReport.dupByHashCount); 445 sb.append("<br />\n"); 446 sb.append("sizeTotalsReport.novel: "); 447 sb.append(job.sizeTotalsReport.novel); 448 sb.append("<br />\n"); 449 sb.append("sizeTotalsReport.novelCount: "); 450 sb.append(job.sizeTotalsReport.novelCount); 451 sb.append("<br />\n"); 452 sb.append("sizeTotalsReport.notModified: "); 453 sb.append(job.sizeTotalsReport.notModified); 454 sb.append("<br />\n"); 455 sb.append("sizeTotalsReport.notModifiedCount: "); 456 sb.append(job.sizeTotalsReport.notModifiedCount); 457 sb.append("<br />\n"); 458 sb.append("sizeTotalsReport.total: "); 459 sb.append(job.sizeTotalsReport.total); 460 sb.append("<br />\n"); 461 sb.append("sizeTotalsReport.totalCount: "); 462 sb.append(job.sizeTotalsReport.totalCount); 463 sb.append("<br />\n"); 464 } 465 if (job.rateReport != null) { 466 sb.append("rateReport.currentDocsPerSecond: "); 467 sb.append(job.rateReport.currentDocsPerSecond); 468 sb.append("<br />\n"); 469 sb.append("rateReport.averageDocsPerSecond: "); 470 sb.append(job.rateReport.averageDocsPerSecond); 471 sb.append("<br />\n"); 472 sb.append("rateReport.currentKiBPerSec: "); 473 sb.append(job.rateReport.currentKiBPerSec); 474 sb.append("<br />\n"); 475 sb.append("rateReport.averageKiBPerSec: "); 476 sb.append(job.rateReport.averageKiBPerSec); 477 sb.append("<br />\n"); 478 } 479 if (job.loadReport != null) { 480 sb.append("loadReport.busyThreads: "); 481 sb.append(job.loadReport.busyThreads); 482 sb.append("<br />\n"); 483 sb.append("loadReport.totalThreads: "); 484 sb.append(job.loadReport.totalThreads); 485 sb.append("<br />\n"); 486 sb.append("loadReport.congestionRatio: "); 487 sb.append(job.loadReport.congestionRatio); 488 sb.append("<br />\n"); 489 sb.append("loadReport.averageQueueDepth: "); 490 sb.append(job.loadReport.averageQueueDepth); 491 sb.append("<br />\n"); 492 sb.append("loadReport.deepestQueueDepth: "); 493 sb.append(job.loadReport.deepestQueueDepth); 494 sb.append("<br />\n"); 495 } 496 if (job.elapsedReport != null) { 497 sb.append("elapsedReport.elapsed: "); 498 sb.append(job.elapsedReport.elapsedPretty); 499 sb.append(" ("); 500 sb.append(job.elapsedReport.elapsedMilliseconds); 501 sb.append("ms)"); 502 sb.append("<br />\n"); 503 } 504 if (job.threadReport != null) { 505 sb.append("threadReport.toeCount: "); 506 sb.append(job.threadReport.toeCount); 507 sb.append("<br />\n"); 508 if (job.threadReport.steps != null) { 509 for (int i =0; i<job.threadReport.steps.size(); ++i) { 510 sb.append("threadReport.steps["); 511 sb.append(i); 512 sb.append("]: "); 513 sb.append(job.threadReport.steps.get(i)); 514 sb.append("<br />\n"); 515 } 516 } 517 if (job.threadReport.processors != null) { 518 for (int i =0; i<job.threadReport.processors.size(); ++i) { 519 sb.append("threadReport.processors["); 520 sb.append(i); 521 sb.append("]: "); 522 sb.append(job.threadReport.processors.get(i)); 523 sb.append("<br />\n"); 524 } 525 } 526 } 527 if (job.frontierReport != null) { 528 sb.append("frontierReport.totalQueues: "); 529 sb.append(job.frontierReport.totalQueues); 530 sb.append("<br />\n"); 531 sb.append("frontierReport.inProcessQueues: "); 532 sb.append(job.frontierReport.inProcessQueues); 533 sb.append("<br />\n"); 534 sb.append("frontierReport.readyQueues: "); 535 sb.append(job.frontierReport.readyQueues); 536 sb.append("<br />\n"); 537 sb.append("frontierReport.snoozedQueues: "); 538 sb.append(job.frontierReport.snoozedQueues); 539 sb.append("<br />\n"); 540 sb.append("frontierReport.activeQueues: "); 541 sb.append(job.frontierReport.activeQueues); 542 sb.append("<br />\n"); 543 sb.append("frontierReport.inactiveQueues: "); 544 sb.append(job.frontierReport.inactiveQueues); 545 sb.append("<br />\n"); 546 sb.append("frontierReport.ineligibleQueues: "); 547 sb.append(job.frontierReport.ineligibleQueues); 548 sb.append("<br />\n"); 549 sb.append("frontierReport.retiredQueues: "); 550 sb.append(job.frontierReport.retiredQueues); 551 sb.append("<br />\n"); 552 sb.append("frontierReport.exhaustedQueues: "); 553 sb.append(job.frontierReport.exhaustedQueues); 554 sb.append("<br />\n"); 555 sb.append("frontierReport.lastReachedState: "); 556 sb.append(job.frontierReport.lastReachedState); 557 sb.append("<br />\n"); 558 } 559 if (job.crawlLogTail != null) { 560 for (int i =0; i<job.crawlLogTail.size(); ++i) { 561 sb.append("crawlLogTail["); 562 sb.append(i); 563 sb.append("]: "); 564 sb.append(job.crawlLogTail.get(i)); 565 sb.append("<br />\n"); 566 } 567 } 568 sb.append("isRunning: "); 569 sb.append(job.isRunning); 570 sb.append("<br />\n"); 571 sb.append("isLaunchable: "); 572 sb.append(job.isLaunchable); 573 sb.append("<br />\n"); 574 sb.append("alertCount: "); 575 sb.append(job.alertCount); 576 sb.append("<br />\n"); 577 sb.append("alertLogFilePath: "); 578 sb.append(job.alertLogFilePath); 579 sb.append("<br />\n"); 580 sb.append("crawlLogFilePath: "); 581 sb.append(job.crawlLogFilePath); 582 sb.append("<br />\n"); 583 if (job.heapReport != null) { 584 sb.append("heapReport.usedBytes: "); 585 sb.append(job.heapReport.usedBytes); 586 sb.append("<br />\n"); 587 sb.append("heapReport.totalBytes: "); 588 sb.append(job.heapReport.totalBytes); 589 sb.append("<br />\n"); 590 sb.append("heapReport.maxBytes: "); 591 sb.append(job.heapReport.maxBytes); 592 sb.append("<br />\n"); 593 } 594 } 595 } 596 } 597 598 StringBuilder menuSb = masterTplBuilder.buildMenu(new StringBuilder(), req, locale, h3Job); 599 600 masterTplBuilder.insertContent("Details and Actions on Running Job " + jobId, menuSb.toString(), httpLocale.generateLanguageLinks(), 601 "Details and Actions on Running Job " + jobId, sb.toString(), 602 "<link rel=\"shortcut icon\" type=\"image/png\" href=\"/transparent_menu_logo.png\"/>" 603 + 604 "<meta http-equiv=\"refresh\" content=\""+Settings.get(HarvesterSettings.HARVEST_MONITOR_REFRESH_INTERVAL)+"\"/>\n").write(out); 605 606 out.flush(); 607 out.close(); 608 } 609 610}