Changeset 18359 for gli/branches/rtl-gli
- Timestamp:
- 2009-01-12T11:18:36+13:00 (15 years ago)
- Location:
- gli/branches/rtl-gli/src/org/greenstone/gatherer/download
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
gli/branches/rtl-gli/src/org/greenstone/gatherer/download/DownloadJob.java
r13594 r18359 76 76 77 77 private String download_url = ""; 78 78 79 79 // private String current_url; 80 80 // private String destination; … … 96 96 public static int DEFINED_MAX = 1; 97 97 public static int UNDEFINED_MAX = 2; 98 98 99 // To prematurely terminate wget, we will need to use sockets and find a free port. 100 // We will look at a limited range of ports. This range will be reused (circular buffer) 101 private static final int PORT_BASE = 50000; 102 private static final int PORT_BLOCK_SIZE = 100; 103 private static int nextFreePort = PORT_BASE; // Keep track what port numbers we have checked for availability 104 int port; // package access. The socket port number this instance of DownloadJob will use 105 99 106 private String mode = null; 100 107 101 108 private String proxy_url; 102 109 103 110 /** 104 111 */ … … 169 176 // The stop_start_button is used to alternately start or stop the 170 177 // job. If the current state of the job is paused then this 171 // restart is logically equiv elent to a resume.178 // restart is logically equivalent to a resume. 172 179 if(event.getSource() == progress.stop_start_button) { 173 180 previous_state = state; … … 189 196 } 190 197 198 /** Given a portnumber to check, returns true if it is available 199 * (if nothing's listening there already). */ 200 public static boolean isPortAvailable(int portnum) { 201 Socket tmpSocket = null; 202 try { 203 tmpSocket = new Socket("localhost", portnum); 204 tmpSocket.close(); 205 return false; 206 207 } catch(ConnectException ex){ 208 // "Signals that an error occurred while attempting to connect a socket 209 // to a remote address and port. Typically, the connection was refused 210 // remotely (e.g., no process is listening on the remote address/port)." 211 System.err.println("Port " + portnum + " not yet in use."); 212 tmpSocket = null; 213 return true; 214 215 } catch(Exception ex) { 216 // includes BindException "Signals that an error occurred while attempting 217 // to bind a socket to a local address and port. Typically, the port is in 218 // use, or the requested local address could not be assigned." 219 tmpSocket = null; 220 return false; 221 } 222 } 223 224 /** Circular buffer. Modifies the value of nextFreePort (the buffer index). */ 225 private void incrementNextFreePort() { 226 int offset = nextFreePort - PORT_BASE; 227 offset = (offset + 1) % PORT_BLOCK_SIZE; 228 nextFreePort = PORT_BASE + offset; 229 } 191 230 192 231 public void callDownload() { 193 232 194 233 ArrayList command_list = new ArrayList(); 195 234 if (Utility.isWindows()) { … … 202 241 command_list.add("-cache_dir"); 203 242 command_list.add(Gatherer.getGLIUserCacheDirectoryPath()); 243 // For the purposes of prematurely terminating wget from GLI (which creates a socket 244 // as a communication channel between GLI and Perl), it is important to tell the script 245 // that we're running as GLI. Because when running from the command prompt, it should 246 // not create this socket and do the related processing. 247 command_list.add("-gli"); 204 248 205 249 ArrayList all_arg = download.getArguments(true,false); … … 252 296 } 253 297 } 254 255 298 //System.out.println(newcmd); 256 299 257 InputStreamReader isr = new InputStreamReader(prcs.getErrorStream()); 258 BufferedReader br = new BufferedReader(isr); 259 // Capture the standard error stream and seach for two particular occurances. 300 // Can use the following if debugging WgetDownload.pm - Reads debug stmts from the perl process' STDIN stream 301 //(new PerlReaderThread(prcs)).start(); 302 303 InputStream is = prcs.getInputStream(); 304 BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 305 306 // To be able to stop Wget, we use sockets to communicate with the perl process that launched wget 307 if (mode.equals("Web") || mode.equals("MediaWiki")) { // wget download modes other than OAI 308 309 // Need to find an available (unused) port within the range we're looking for to pass it 310 // the Perl child process, so that it may set up a listening ServerSocket at that port number 311 try { 312 boolean foundFreePort = false; 313 for(int i = 0; i < PORT_BLOCK_SIZE; i++) { 314 315 if(isPortAvailable(nextFreePort)) { 316 foundFreePort = true; 317 break; 318 319 } else { 320 incrementNextFreePort(); 321 } 322 } 323 324 if(foundFreePort) { 325 // Free port number currently found becomes the port number of the socket that this 326 // DownloadJob instance will be connecting to when the user wants to prematurely stop Wget. 327 this.port = nextFreePort; 328 incrementNextFreePort(); 329 330 } else { 331 throw new Exception("Cannot find an available port in the range " 332 + PORT_BASE + "-" + (PORT_BASE+PORT_BLOCK_SIZE) 333 + "\nwhich is necessary for forcibly terminating wget."); 334 } 335 336 // Communicate the chosen port for this DownloadJob instance to the perl process, so 337 // that it can set up a ServerSocket at that port to listen for any signal to terminate wget 338 OutputStream os = prcs.getOutputStream(); 339 String p = ""+this.port+"\n"; 340 System.err.println("Portnumber found: " + p); 341 342 os.write(p.getBytes()); 343 os.close(); 344 345 } catch(Exception ex) { 346 System.err.println("Sent available portnumber " + this.port + " to process' outputstream.\nBut got exception: " + ex); 347 } 348 } 349 350 BufferedReader br = new BufferedReader(new InputStreamReader(prcs.getErrorStream())); 351 // Capture the standard error stream and search for two particular occurrences. 260 352 String line=""; 261 353 boolean ignore_for_robots = false; 262 354 int max_download = DownloadJob.UNKNOWN_MAX; 263 264 355 265 356 while ((line = br.readLine()) != null && !line.trim().equals("<<Finished>>") && state != STOPPED) { 266 267 357 if ( max_download == DownloadJob.UNKNOWN_MAX) { 268 358 if(line.lastIndexOf("<<Defined Maximum>>") != -1) { … … 355 445 } 356 446 } 447 357 448 if(state == STOPPED) { 358 isr.close(); 359 prcs.destroy(); // This doesn't always work, but it's worth a try 449 boolean terminatePerlScript = true; 450 451 // When GLI is working with wget-based download modes other than OAI (MediaWiki and Web 452 // download) and the STOP button has been pressed, wget needs to be prematurely terminated. 453 // Only wget download modes Web and MediaWiki require the use of sockets to communicate 454 // with the perl script in order to get wget to terminate. Other download modes, including 455 // wgetdownload mode OAI, can terminate in the traditional manner: close process inputstream 456 // and kill perl process. OAI launches many wgets. So that when the perl process is terminated, 457 // the currently running wget will finish off but other wgets are no longer launched. 458 if(prcs != null && (mode.equals("Web") || mode.equals("MediaWiki"))) { 459 460 // create a socket to the perl child process and communicate the STOP message 461 Socket clientSocket = null; 462 if(clientSocket == null) { 463 try { 464 clientSocket = new Socket("localhost", this.port); // connect to the port chosen for this DownloadJob instance 465 466 BufferedReader clientReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 467 String response = clientReader.readLine(); // see if we've been connected 468 System.err.println("Communicating with perl download script on port " + this.port 469 + "\nGot response from perl: " + response); 470 471 // Send the STOP signal 472 OutputStream os = clientSocket.getOutputStream(); 473 String message = "<<STOP>>\n"; 474 os.write(message.getBytes()); 475 response = clientReader.readLine(); // see whether the stop signal has been received 476 System.err.println("GLI sent STOP signal to perl to terminate wget." 477 + "\nGot response from perl: " + response); 478 479 response = clientReader.readLine(); // see whether the perl script is ready to be terminated 480 System.err.println("Got another response from perl: " + response); 481 os.close(); 482 483 clientReader.close(); 484 clientSocket.close(); // close the clientSocket (the Perl end will close the server socket that Perl opened) 485 clientReader = null; 486 clientSocket = null; 487 488 if(response == null) { 489 terminatePerlScript = false; 490 } 491 } catch(IOException ex) { 492 System.err.println("Tried to communicate through client socket - port " + this.port + ", but got exception: " + ex); 493 } catch(Exception ex) { 494 System.err.println("Tried to open client socket, but got exception: " + ex); 495 } 496 } 497 } 498 499 //prcs.getInputStream().close(); 500 prcs.getErrorStream().close(); 501 br.close(); 502 br = null; 503 if(terminatePerlScript) { 504 prcs.destroy(); // This doesn't always work, but it's worth a try 505 prcs = null; 506 } 507 508 // Notify the DownloadScrollPane which is waiting on this job to complete that we are ready 509 synchronized(this) { 510 this.notify(); 511 } 360 512 } 361 362 513 } 363 514 catch (Exception ioe) { … … 372 523 previous_state = state; 373 524 state = DownloadJob.COMPLETE; 374 375 525 } 376 526 // refresh the workspace tree 377 527 Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.DOWNLOADED_FILES_CHANGED); 378 379 528 } 380 529 … … 464 613 progress.updateProgress(current, expected); 465 614 } 615 616 617 // Inner thread class that reads from process downloadfrom.pl's errorstream 618 private class PerlReaderThread extends Thread { 619 Process prcs = null; 620 621 public PerlReaderThread(Process proc) { 622 this.prcs = proc; 623 } 624 625 public void run() { 626 try { 627 if(prcs != null) { 628 String message = null; 629 BufferedReader eReader = new BufferedReader(new InputStreamReader(prcs.getInputStream())); 630 while(prcs != null && (message = eReader.readLine()) != null) { 631 if(!message.equals("\n")) { 632 System.err.println("**** Perl STDOUT: " + message); 633 } 634 } 635 636 if(prcs != null && eReader != null) { 637 eReader.close(); 638 eReader = null; 639 System.err.println("**** Perl ENDed."); 640 } 641 } 642 } catch(Exception e) { 643 System.err.println("Thread - caught exception: " + e); 644 } 645 } 646 } 466 647 } -
gli/branches/rtl-gli/src/org/greenstone/gatherer/download/DownloadScrollPane.java
r12529 r18359 52 52 extends Thread { 53 53 54 /** <i>true</i> if there is a task currently being carried out, <i>false</i> otherwise. */55 private boolean busy = false;56 54 /** <i>true</i> if verbose debug messages should be displayed, <i>false</i> otherwise. */ 57 55 private boolean debug = false; … … 69 67 private Vector job_queue; 70 68 static final private boolean simple = true; 71 69 70 72 71 public DownloadScrollPane() { 73 72 job = null; … … 81 80 public void deleteDownloadJob(DownloadJob delete_me) { 82 81 if (delete_me == job) { 83 while(busy) { 84 } 85 job = null; 86 } 82 try { 83 // Wait for the job to finish cleaning up, before we can continue cleaning up here. 84 // But sometimes the job has completed (terminated naturally) and in that case there's 85 // nothing to wait for. 86 synchronized(delete_me) { 87 if (!delete_me.hasSignalledStop()) { // don't wait if DownloadJob.COMPLETED 88 delete_me.wait(); 89 } 90 } 91 } catch (Exception e) { 92 e.printStackTrace(); 93 } 94 } 95 // Close button pressed, get rid of this download's dedicated pane 96 finishedDownloadJob(delete_me, true); 97 } 98 99 /** To be called when a download job has terminated naturally or was prematurely stopped 100 * via the close button. 101 * Gets rid of this download's pane with buttons and progress bar if prematurely stopped. */ 102 protected void finishedDownloadJob(DownloadJob delete_me, boolean removeDisplay) { 87 103 if (delete_me.hasSignalledStop()) { 88 list_pane.remove(delete_me.getProgressBar()); 104 if(removeDisplay) { 105 list_pane.remove(delete_me.getProgressBar()); 106 list_pane.remove(filler_pane); 107 } 89 108 job_queue.remove(delete_me); 90 list_pane.remove(filler_pane);91 109 if(job_queue.size() > 0) { 92 110 Dimension progress_bar_size = delete_me.getProgressBar().getPreferredSize(); … … 131 149 132 150 DebugStream.println("About to create a new job"); 133 134 151 135 152 DownloadJob new_job = new DownloadJob(download, Configuration.proxy_pass, Configuration.proxy_user, this, mode, proxy_url); 136 153 // Tell it to run as soon as possible 137 138 139 154 140 155 new_job.setState(DownloadJob.RUNNING); … … 165 180 //list_pane.setAlignmentX(Component.LEFT_ALIGNMENT); 166 181 list_pane.updateUI(); 167 new_job = null; 182 new_job = null; //job = (DownloadJob) job_queue.get(index); 183 168 184 synchronized(this) { 169 185 notify(); // Just incase its sleeping. … … 189 205 while(true) { 190 206 if(job_queue.size() > 0) { 191 int index = 0;192 while(job_queue.size() > 0 && index < job_queue.size()) {193 job = (DownloadJob) job_queue.get(index);207 while(!job_queue.isEmpty()) { 208 job = (DownloadJob) job_queue.firstElement(); 209 194 210 if(job.getState() == DownloadJob.RUNNING) { 195 DebugStream.println("DownloadJob " + job.toString() + " Begun."); 196 busy = true; 211 DownloadJob delete_me = job; 212 String jobDisplayString = job.toString(); 213 DebugStream.println("DownloadJob " + jobDisplayString + " Begun."); 214 System.err.println("DownloadJob " + job.port + " " + job.toString() + " Begun."); 197 215 job.callDownload(); 198 busy = false; 199 DebugStream.println("DownloadJob " + job.toString() + " complete."); 216 // Job is done. Ended naturally, don't get rid of this download's separate display panel 217 finishedDownloadJob(delete_me, false); 218 System.err.println("DownloadJob " + jobDisplayString + " complete."); 219 DebugStream.println("DownloadJob " + jobDisplayString + " complete."); // by this point job is null! 200 220 job = null; 201 }202 index++;221 delete_me = null; 222 } 203 223 } 204 224 try {
Note:
See TracChangeset
for help on using the changeset viewer.