Changeset 29947 for main


Ignore:
Timestamp:
2015-06-05T20:58:20+12:00 (9 years ago)
Author:
ak19
Message:

First of two commits to fix rebuilding a collection using the online editor on Windows. Resolves the file lock problem. The java code works with changes in activate.pl. activate.pl is passed a flag so that it no longer de-activates and re-activates the collection itself, but just concerns itself with moving building to index. The GS2Construct java code now de-activates the collection prior to calling activate.pl and then re-activates it afterward. In the way it was done before, activate.pl used to handle de- and re-activating the collection. But when it was launched from the server java code, the java VM would exit having left a copy of the file handles to the perl process when forking the process for activate.pl. The perl code could not move building to index since the file handles had locks (6 of them) on the index/text/collection.gdb. Changes have been made to GS2PerlConstructor too, so that it more cleanly closes all the pipes of a process, that the process itself may thereby exit cleanly. Not yet able to move this properly into its own classes since the StreamGobbler classes in GLI are not quite suited but were customised for FormatConverter.

Location:
main/trunk/greenstone3/src/java/org/greenstone/gsdl3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/build/GS2PerlConstructor.java

    r29869 r29947  
    1313import java.io.BufferedReader;
    1414import java.io.BufferedWriter;
     15import java.io.Closeable;
    1516import java.io.FileWriter;
    1617import java.io.InputStreamReader;
    1718import java.io.File;
     19import java.io.IOException;
    1820import java.util.ArrayList;
    1921import java.util.Vector;
     
    278280        command.add(GSFile.collectDir(this.site_home));
    279281        command.add("-removeold"); // saves some seconds processing time when this flag's added in explicitly
     282        command.add("-skipactivation"); // gsdl3/util/GS2Construct does the activation and reactivation
    280283        command.addAll(extractParameters(this.process_params));
    281284        command.add(this.collection_name);
     
    365368    return runPerlCommand(command, null, null);
    366369    }
    367 
    368     protected boolean runPerlCommand(String[] command, String[] envvars, File dir)
    369     {
     370   
     371    protected boolean runPerlCommand(String[] command, String[] envvars, File dir)
     372    {
     373        boolean success = true;
     374   
    370375        int sepIndex = this.gsdl3home.lastIndexOf(File.separator);
    371376        String srcHome = this.gsdl3home.substring(0, sepIndex);
     
    397402
    398403        sendMessage(new ConstructionEvent(this, GSStatus.INFO, "command = " + command_str));
     404        Process prcs = null;
     405        BufferedReader ebr = null;
     406        BufferedReader stdinbr = null;
    399407        try
    400408        {
    401409            Runtime rt = Runtime.getRuntime();
    402410            sendProcessBegun(new ConstructionEvent(this, GSStatus.ACCEPTED, "starting"));
    403             Process prcs = (dir == null)
     411            prcs = (dir == null)
    404412                ? rt.exec(command, args.toArray(new String[args.size()]))
    405413                : rt.exec(command, args.toArray(new String[args.size()]), dir);
     
    407415            InputStreamReader eisr = new InputStreamReader(prcs.getErrorStream());
    408416            InputStreamReader stdinisr = new InputStreamReader(prcs.getInputStream());
    409             BufferedReader ebr = new BufferedReader(eisr);
    410             BufferedReader stdinbr = new BufferedReader(stdinisr);
     417            ebr = new BufferedReader(eisr);
     418            stdinbr = new BufferedReader(stdinisr);
    411419            // Captures the std err of a program and pipes it into
    412420            // std in of java
     
    440448                }
    441449            }
    442             bw.close();
    443 
     450            closeResource(bw);
     451           
    444452            if (!this.cancel)
    445453            {
     
    448456
    449457                if (prcs.exitValue() == 0)
    450                 {
     458                {   
    451459                    //status = OK;
    452460                    sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, "Success"));
    453 
     461                   
     462                    success = true;
    454463                }
    455464                else
     
    458467                    sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Failure"));
    459468
    460                     return false;
     469                    //return false;
     470                    success = false;
    461471
    462472                }
     
    466476                // I need to somehow kill the child process. Unfortunately Thread.stop() and Process.destroy() both fail to do this. But now, thankx to the magic of Michaels 'close the stream suggestion', it works fine.
    467477                sendProcessStatus(new ConstructionEvent(this, GSStatus.HALTED, "killing the process"));
    468                 prcs.getOutputStream().close();
    469                 prcs.destroy();
    470                 //status = ERROR;
    471                 return false;
     478                //prcs.getOutputStream().close();
     479                //prcs.destroy();
     480                ////status = ERROR;
     481               
     482                //return false;
     483                success = false;
    472484            }
    473485        }
     
    476488            e.printStackTrace();
    477489            sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Exception occurred " + e.toString()));
    478         }
    479 
    480         // we're done, but we dont send a process complete message here cos there ight be stuff to do after this has finished.
    481         return true;
    482 
    483     }
    484 
     490        } finally {
     491            // http://steveliles.github.io/invoking_processes_from_java.html
     492            // http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2
     493            // http://mark.koli.ch/leaky-pipes-remember-to-close-your-streams-when-using-javas-runtimegetruntimeexec
     494       
     495             if( prcs != null ) {
     496                closeResource(prcs.getErrorStream());
     497                closeResource(prcs.getOutputStream());
     498                closeResource(prcs.getInputStream());
     499                prcs.destroy();
     500            }
     501       
     502            closeResource(ebr);
     503            closeResource(stdinbr);
     504        }
     505
     506        // we're done, but we don't send a process complete message here cos there might be stuff to do after this has finished.
     507        //return true;     
     508        return success;
     509    }
     510   
     511    public static void closeResource(Closeable resourceHandle) {
     512        try {
     513            if(resourceHandle != null) {
     514                resourceHandle.close();
     515                resourceHandle = null;
     516            }
     517        } catch(Exception e) {
     518            System.err.println("Exception closing resource: " + e.getMessage());
     519            e.printStackTrace();
     520        }
     521    }
    485522}
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Construct.java

    r29869 r29947  
    330330        String lang = request.getAttribute(GSXML.LANG_ATT);
    331331
    332         Element response = runCommand(request, GS2PerlConstructor.ACTIVATE);
     332        UserContext userContext = new UserContext(request);
     333        String request_type = request.getAttribute(GSXML.TYPE_ATT);
     334       
     335        // now we de-activate the collection before running activate.pl, and then re-activate at end
     336        // So activate.pl only does the moving, no activation. This way will prevent java from launching
     337        // perl, exiting and then leaving dangling file handles (on index/text/col.gdb) in perl.
     338        if (!request_type.equals(GSXML.REQUEST_TYPE_STATUS)) {         
     339            systemRequest("delete", coll_name, null, userContext); // deactivate collection
     340        }   
     341
     342        Element response = runCommand(request, GS2PerlConstructor.ACTIVATE); // if request is for STATUS, then this won't run activate.pl
     343
    333344        Element status = (Element) GSXML.getChildByTagName(response, GSXML.STATUS_ELEM);
    334 
    335         String request_type = request.getAttribute(GSXML.TYPE_ATT);
    336         if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
    337         {
    338             return response;
    339         }
    340 
    341         UserContext userContext = new UserContext(request);
    342         systemRequest("delete", coll_name, null, userContext);
    343345
    344346        // check for finished
     
    384386        status.appendChild(t);
    385387        // once have got here, we assume
    386         // the first bit proceeded successfully, now reload the collection
     388        // the first bit proceeded successfully, now reload the collection (sends a collection reactivation request)
    387389        systemRequest("reload", coll_name, status, userContext); // this will append more messages to the status, and overwrite the error code att
    388390        return response;
Note: See TracChangeset for help on using the changeset viewer.