Ignore:
Timestamp:
2017-05-18T20:38:56+12:00 (7 years ago)
Author:
ak19
Message:

Major changes to SafeProcess and classes of the download package, by bringing the final GLI (and final Greenstone) class DownloadJob over to use SafeProcess. Significant changes to SafeProcess: 1. Introduction of cancelRunningProcess as a new method, so that callers don't need to know how cancelling a process is implemented (as an interrupt) nor do they need to know what thread they ought to interrupt (which should be the thread that launched SafeProcess), nor do they need to know of the complexity surrounding the join() blocking call which should not be interrupted. 2. Introduction of the SafeProcess.MainHandler interface that provides methods that allow implementers to write hooks to various stages of the SafeProcess' internal process' life cycle. 3. moved process cleanUp() code into a reusable method within SafeProcess. Significant changes to DownloadJob and its associated DownloadProgressBar and DownloadScrollPane classes: 1. Unused member vars removed or commented out and those that can be declared final are now declared so, as a programming pricinple for thread safety, since DownloadJob and the other download classes will have to interact with multiple threads and could be called by different threads. 2. Replaced existing actionPerformed() and callDownload() of DownloadJob with SafeProcess and implemented the necessary Hooks in the SafeProcess.MainHandler() interface to ensure that perl is still told to terminate wget on a cancel action. 3. Replaced DownloadScrollPane's deleteDownloadJob() with a new version that now more responsively removes its DownloadProgressBar (with controls) for a DownloadJob. It's called by the SafeProcess.MainHandler interface hooks implemented by DownloadJob, so DownloadScrollPane no longer needs to wait() to be notify()ed when a process has cleaned up on premature termination by a cancel action. 4. Made the necessary methods in DownloadProgressBar synchronized for thread safety. 5. GShell now uses SafeProcess' new cancelRunningProcess() method in place of directly calling interrupt on the (GShell) thread that launched SafeProcess.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/gli/src/org/greenstone/gatherer/download/DownloadProgressBar.java

    r22103 r31692  
    128128    JPanel button_pane = new JPanel();
    129129
     130    // our "pause" button never paused before, it always did a process.destroy() on being pressed.
     131    // See http://trac.greenstone.org/browser/trunk/gli/src/org/greenstone/gatherer/download/DownloadJob.java?rev=13594
     132    // However, now we additionally ensure that the wget launched by the perl is stopped before
     133    // process.destroy(), so at least it cleans up better. I'm therefore changing it to a "Stop" button.
    130134    stop_start_button = new GLIButton(Dictionary.get("Mirroring.DownloadJob.Pause"),Dictionary.get("Mirroring.DownloadJob.Pause_Tooltip"));
     135    //stop_start_button = new GLIButton(Dictionary.get("Mirroring.DownloadJob.Stop"),Dictionary.get("Mirroring.DownloadJob.Stop_Tooltip"));
    131136    stop_start_button.addActionListener(this);
    132137    stop_start_button.addActionListener(owner);
     
    166171    // Make the labels, etc update.
    167172    refresh();
     173    }
     174
     175    // internally thread-safe
     176    public void enableCancelJob(boolean isEnabled) {
     177    synchronized(stop_start_button) {
     178        stop_start_button.setEnabled(isEnabled);
     179    }
     180    synchronized(stop_start_button) {
     181        close_button.setEnabled(isEnabled);
     182    }
    168183    }
    169184
     
    212227     * @param url The url String of the file that is being downloaded.
    213228     */
    214     public void addDownload(String url) {
     229    public synchronized void addDownload(String url) {
    215230    current_url = url;
    216231    file_size = 0;
     
    221236     * is called to enlighten the DownloadProgressBar of this fact.
    222237     */
    223     public void downloadComplete() {
     238    public synchronized void downloadComplete() {
    224239    current_url = null;
    225240    file_count++;
     
    232247    }
    233248
    234     public void downloadFailed() {
     249    public synchronized void downloadFailed() {
    235250    err_count++;
    236251    if(total_count < (file_count + err_count + warning_count)) {
     
    240255    }
    241256
    242     public void downloadWarning() {
     257    public synchronized void downloadWarning() {
    243258    warning_count++;
    244259    if(total_count < (file_count + err_count + warning_count)) {
     
    248263    }
    249264
    250     public void setTotalDownload(int total_download) {
     265    // need to make these methods synchronized too, as they modify variables
     266    // that other synchronized methods work with. And if any methods that modify
     267    // such variables were to remain unsynchronized, can end up with race conditions
     268    // http://stackoverflow.com/questions/574240/is-there-an-advantage-to-use-a-synchronized-method-instead-of-a-synchronized-blo
     269    // "Not only do synchronized methods not lock the whole class, but they don't lock the whole instance either. Unsynchronized methods in the class may still proceed on the instance."
     270    // "Only the syncronized methods are locked. If there are fields you use within synced methods that are accessed by unsynced methods, you can run into race conditions."
     271    public synchronized void setTotalDownload(int total_download) {
    251272    total_count = total_download;
    252273    refresh();
     
    257278    }
    258279
    259     public void increaseFileCount() {
     280    public synchronized void increaseFileCount() {
    260281    file_count++;
    261282    refresh();
    262283    }
    263284
    264     public void increaseFileCount(int amount) {
     285    public synchronized void increaseFileCount(int amount) {
    265286    file_count += amount;
    266287    refresh();
    267288    }
    268289
    269     public void resetFileCount() {
     290    public synchronized void resetFileCount() {
    270291    file_count = 0;
    271292    refresh();
     
    278299     * reset to zero.
    279300     */
    280     public void mirrorBegun(boolean reset, boolean simple) {
     301    public synchronized void mirrorBegun(boolean reset, boolean simple) {
    281302    if(reset) {
    282303        this.file_count = 0;
     
    301322     * components.
    302323     */
    303     public void mirrorComplete() {
     324    public synchronized void mirrorComplete() {
    304325    current_action = DownloadJob.COMPLETE;
    305326    current_url = null;
     
    319340     * the amount of the current file downloaded.
    320341     */
    321     public void updateProgress(long current, long expected) {
     342    public synchronized void updateProgress(long current, long expected) {
    322343    file_size = file_size + current;
    323344    if(!progress.isIndeterminate()) {
Note: See TracChangeset for help on using the changeset viewer.