All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.grizzly.jruby.RubyObjectPool Maven / Gradle / Ivy

/*
 * 
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 */
package com.sun.grizzly.jruby;

import com.sun.grizzly.http.SelectorThread;
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.LoadService;
import org.jruby.util.ClassCache;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.logging.Level;

/**
 * An object pool for ruby runtimes.
 *
 * TODO: Make the pool auto increase and provide more config flexibility
 *
 * @author TAKAI Naoto
 * @author Pramod Gopinath
 * @author Vivek Pandey
 * @author Jacob Kessler
 */
public class RubyObjectPool {

    /**
     * How long to wait before giving up.
     */
    public static final long DEFAULT_TIMEOUT = 360L;
    /**
     * JRUBY_LIB directory
     */
    private final String jrubyLib;
    /**
     * The number of runtimes.
     */
    private final int defaultNumberOfRuntime = 5;
    /**
     * Runtime queue
     */
    private final BlockingQueue queue = new LinkedBlockingQueue();
    /**
     * Is Grizzly ARP enabled.
     */
    private final boolean asyncEnabled;
    private final int numberOfRuntime;
    private final String railsRoot;
    // We use this so much, we might as well cache it
    private final int procs = Runtime.getRuntime().availableProcessors();
    // CachedThreadPool size limited by currentlyGeneratingRuntimes: We want to avoid overloading the system
    // during times of high load by trying to generate lots of new runtimes. However, we may want to
    // generate multiple runtimes at the same time on a large machine
    private ExecutorService runtimeGenerator = Executors.newCachedThreadPool();

    private final int maxGeneratingRuntimes;
    private final int maxGeneratingRuntimes_def = 1;

    /**
     * The maximum runtimes that we want sitting in the queue (idle) at a time)
     */
    private int maximumIdleRuntimes;

    /*
     * currentlyActiveRuntimes keeps track of how many runtimes the pool "knows" about, either lent out
     * or sitting in the queue. It uses that knowledge, along with the limits on the number of runtimes,
     * to prevent itself from making excessive runtimes, even under heavy load, since at some point making
     * a new runtime won't actualy help the load conditions
     *
     * currentlyGeneratingRuntimes keeps track of how many runtimes are scheduled for creation but have not
     * yet been added to the queue. Because runtime creation takes a long time relative to the request
     * service time, requests on a capacity pool have a tendency to impatiently request 3 or 4 runtimes
     * while waiting for a new runtime to initialize, which would otherwise cause 3 or 4 too many runtimes
     * to be created, costing both memory while the runtime lives (bad) and CPU time to create and remove
     * the runtime (really bad, since runtime creation should be while under load). CurrentlyGeneratingRuntimes
     * allows the runtime creator to refuse both runtime creation requests and runtime creation ticks while
     * it already has runtimes queued to be created.
     *
     */
    private volatile int currentlyActiveRuntimes = 0;

    private volatile int currentlyGeneratingRuntimes = 0;

    // Soft limit on the number of runtimes we will create
    // Will adjust based on load
    private int maximumActiveRuntimes = procs + 2;
    // Hard minimum and Maximum values for number of runtimes. The dynamic resizer will not exceed these limits
    private int hardMaxActiveRuntimes = maximumActiveRuntimes * 2; // more runtimes than processors doesn't really help much
    private int hardMinActiveRuntimes = procs;


    /*
     * The "Tick" variables are the variables that keep track of how close to the various thresholds
     * the pool is. Despite being read and modified all over the place by different threads, they have been
     * maintained as normal variables, since they have wide margins of error and tend to be self-correcting
     * Furthermore, the consequences of them being off by a read or two aren't very severe: To trigger the
     * threashold, they would need to have been reasonably close anyway. As such, it seems like labling them
     * as volatile would be an unneeded performance hit. I'm happy to accept criticism from someone more experianced
     * than me, though.
     */
    private int downTicks = 0; // Manages increasing the number of runtimes
    private int upTicks = 0; // Manages decreasing the number of runtimes
    private int queueTicks = 0; // Manages the queue length
    private int newTicks = 0; // Manages new Runtime creation

    /*
     * Threasholds control how many ticks are required to change their associated property. Decreasing
     * these values will make the pool change size more rapidly in response to changing traffice, but
     * also makes it more likely to create or delete runtimes in response to brief spikes or dips in
     * incoming requests. A constructor has been provided to allow users to set their own values.
     */
    private final int upThreashold_def = 10;
    private final int downThreashold_def = 10;
    private final int queueThreashold_def = 10;
    private final int newThreashold_def = 10;

    private final int upThreashold;
    private final int downThreashold;
    private final int queueThreashold;
    private final int newThreashold = newThreashold_def;

    private final long baseTime;

    private final boolean dynamic;



    /**
     * Create a pool of Ruby runtimes. This can be created for the whole container and each of the runtime can be used
     * from the pool to setup Rails instance that serves the request.
     *
     * @param railsRoot    the root directory of the rails project
     * @param jrubyLib     non-null, location to the directory where jruby libraries can be found
     * @param numRunTime   number of runtime to be created.
     * @param asyncEnabled whether grizzly ARP needs to be enabled
     */
    public RubyObjectPool(String railsRoot, String jrubyLib, int numRunTime, boolean asyncEnabled) {
        this.railsRoot = railsRoot;

        this.jrubyLib = jrubyLib;
        this.asyncEnabled = asyncEnabled;
        if (numRunTime > 0) {
            this.numberOfRuntime = numRunTime;
        } else {
            this.numberOfRuntime = defaultNumberOfRuntime;
        }

        maximumIdleRuntimes = numberOfRuntime;
        baseTime = System.currentTimeMillis();

        upThreashold = upThreashold_def;
        downThreashold = downThreashold_def;
        queueThreashold = queueThreashold_def;

        maxGeneratingRuntimes = maxGeneratingRuntimes_def;
        dynamic = true;
    }
    /**
     * Create a pool of Ruby runtimes. This can be created for the whole container and each of the runtime can be used
     * from the pool to setup Rails instance that serves the request. This constructor allows the dynamic adjustment of pool bounds to be disabled
     *
     * @param railsRoot    the root directory of the rails project
     * @param jrubyLib     non-null, location to the directory where jruby libraries can be found
     * @param numRunTime   number of runtime to be created.
     * @param asyncEnabled whether grizzly ARP needs to be enabled
     * @param dynamicEnabled should the object pool attempt to dynamically adjust its bounds? This will NOT affect the pool auto-growing and auto-shrinking, only the automagic discovery of the limits that it should be auto-growing and auto-shrinking in
     */

    public RubyObjectPool(String railsRoot, String jrubyLib, int numRunTime, boolean asyncEnabled, boolean dynamicEnabled) {
        this.railsRoot = railsRoot;

        this.jrubyLib = jrubyLib;
        this.asyncEnabled = asyncEnabled;
        if (numRunTime > 0) {
            this.numberOfRuntime = numRunTime;
        } else {
            this.numberOfRuntime = defaultNumberOfRuntime;
        }

        maximumIdleRuntimes = numberOfRuntime;
        baseTime = System.currentTimeMillis();

        upThreashold = upThreashold_def;
        downThreashold = downThreashold_def;
        queueThreashold = queueThreashold_def;

        dynamic = dynamicEnabled;
        maxGeneratingRuntimes = maxGeneratingRuntimes_def;
    }

    /**
     * Create a pool of Ruby runtimes. This can be created for the whole container and each of the runtime can be used
     * from the pool to setup Rails instance that serves the request. This constructor allows finer control over some of the
     * dynamic bounds and runtime pool resizing logic. If
     *
     * @param railsRoot    the root directory of the rails project
     * @param jrubyLib     non-null, location to the directory where jruby libraries can be found
     * @param numRunTime   number of runtime to be created.
     * @param asyncEnabled whether grizzly ARP needs to be enabled
     * @param responsiveness How quickly the pool adjusts its bounds. Higher values will react more quickly to changes in load. Suggested values are between 5 and 15, 10 is default.
     * @param minRuntimes   Minimal number of runtimes to keep active at all times, regardless of load. If minRuntimes is larger than numRunTime, runtimes will increase as needed until minRuntimes is reached
     * @param maxRuntimes   Maximal number of runtimes to keep active at all times, regardless of load.
     * @param maxInProg     Maximum number of runtimes to schedule for creation at once. Defaults to one, but performance may be increased in situations where there are lots of processors and highly variable load by increasing it.
     */
    public RubyObjectPool (String railsRoot, String jrubyLib, int numRunTime, boolean asyncEnabled,
                           int responsiveness, int minRuntimes, int maxRuntimes, int maxInProg) {
        this.railsRoot = railsRoot;

        this.jrubyLib = jrubyLib;
        this.asyncEnabled = asyncEnabled;
        if (numRunTime > 0) {
            this.numberOfRuntime = numRunTime;
        } else {
            this.numberOfRuntime = defaultNumberOfRuntime;
        }

        maximumIdleRuntimes = numberOfRuntime;
        baseTime = System.currentTimeMillis();

        if (responsiveness > 19) {
            responsiveness = 19;
        }

        upThreashold = 20-responsiveness;
        downThreashold = 20-responsiveness;
        queueThreashold = 20-responsiveness;

        if (maxRuntimes > 0) {
            hardMaxActiveRuntimes = maxRuntimes;
        } else {
            hardMaxActiveRuntimes = maximumActiveRuntimes * 2;
        }
        if (minRuntimes > 0 && minRuntimes <= hardMaxActiveRuntimes) {
            hardMinActiveRuntimes = minRuntimes;
        } else {
            hardMinActiveRuntimes = procs;
        }


        dynamic = true;
        if (maxInProg > 0) {
            maxGeneratingRuntimes = maxInProg;
        } else {
            maxGeneratingRuntimes = maxGeneratingRuntimes_def;
        }
    }

    public long getBaseTime() {
        return baseTime;
    }
    /**
     * Retrives ruby runtime from the object pool.
     *
     * @return JRuby runtime.
     */
    public Ruby borrowRuntime() {
        if (isAsyncEnabled()) {
            // check to see if we can get one right now
            try {
                Ruby gotten = queue.poll(50, TimeUnit.MILLISECONDS); // Wait, but only briefly
                if (gotten != null) {
                    if (queue.size() == 0) {
                        if (dynamic) {
                            queueTicks++;
                            if (queueTicks > queueThreashold) {
                                queueTicks = 0;
                                maximumIdleRuntimes++;
                                if (maximumIdleRuntimes > currentlyActiveRuntimes) {
                                    maximumIdleRuntimes = currentlyActiveRuntimes;
                                }
                            }
                        }
                    } else {
                        if (dynamic) {
                            if (newTicks > 0) {
                                newTicks--;
                                //System.out.println("New Ticks: " + newTicks);
                            }
                            queueTicks--; // start thinking about reducing the queue size
                            if (queueTicks < -queueThreashold) {
                                queueTicks = 0;
                                // Reduce size of queue;
                                maximumIdleRuntimes--;
                                if (maximumIdleRuntimes < procs) {
                                    maximumIdleRuntimes = procs;
                                }
                            }
                        }
                    }
                    SelectorThread.logger().log(Level.FINE,
                            "Recieved new runtime from the queue. " + currentlyActiveRuntimes + "/" + maximumActiveRuntimes +
                                    " active runtimes (" +  queue.size() + " idle, " + (currentlyActiveRuntimes - queue.size()) + " active");
                    return gotten;
                } else {
                    // create a new runtime to handle the request, since none are in the queue
                    if (dynamic) {
                        upTicks ++;
                        queueTicks ++;
                        if (upTicks > upThreashold) {
                            upTicks = 0;
                            queueTicks = 0;
                            maximumIdleRuntimes ++;
                            maximumActiveRuntimes ++;
                            if (maximumActiveRuntimes > hardMaxActiveRuntimes) {
                                maximumActiveRuntimes = hardMaxActiveRuntimes;
                            }
                        }
                        if (queueTicks > queueThreashold) {
                            queueTicks = 0;
                            maximumIdleRuntimes++;
                            if (maximumIdleRuntimes > currentlyActiveRuntimes) {
                                maximumIdleRuntimes = currentlyActiveRuntimes;
                            }
                        }
                    }
                    makeNewRuntime();
                    // It's been stuck in the queue, so we should be able to get it out
                    // Timeout is very long to block rather than returning a null
                    gotten = queue.poll(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
                    //System.out.println("Wait time (pool miss):							" + (System.currentTimeMillis() - time));
                    SelectorThread.logger().log(Level.FINE,
                            "Recieved new runtime from the queue. " + currentlyActiveRuntimes + "/" + maximumActiveRuntimes +
                                    " active runtimes (" +  queue.size() + " idle, " + (currentlyActiveRuntimes - queue.size()) + " active");
                    return gotten;
                }
            } catch (InterruptedException e) {
                // Following old InterruptedException behavior
                throw new RuntimeException(e);
            }
        } else {
            // old non-async behavior
            return queue.poll();
        }
    }

    /**
     * Returns runtime to the object pool.
     *
     * @param runtime - JRuby Rails runtime
     */
    public void returnRuntime(Ruby runtime) {
        // check to see if we should bother returning this runtime to the queue
        if (queue.size() < maximumIdleRuntimes) {
            queue.offer(runtime);
            if (dynamic) {
                downTicks --;
                SelectorThread.logger().log(Level.FINE,
                        "Returned runtime to the queue. " + currentlyActiveRuntimes + "/" + maximumActiveRuntimes +
                                " active runtimes (" +  queue.size() + " idle, " + (currentlyActiveRuntimes - queue.size()) + " active");
            }
        } else {
            SelectorThread.logger().log(Level.FINE,
                    "Excessive idle Ruby runtimes: returned runtime not re-added to the queue. " + currentlyActiveRuntimes + "/" + maximumActiveRuntimes +
                            " active runtimes (" +  queue.size() + " idle, " + (currentlyActiveRuntimes - queue.size()) + " active");
            if (dynamic) {
                downTicks++;
                upTicks --;
                if (downTicks > downThreashold) {
                    downTicks = 0;
                    if (currentlyActiveRuntimes > hardMinActiveRuntimes) {
                        currentlyActiveRuntimes--;
                        // Otherwise, we just allow it to fall on the floor and be cleaned up by the GC
                        runtime.tearDown();
                    } else {
                        queue.offer(runtime);
                    }
                } else {
                    queue.offer(runtime);
                } if (upTicks < -upThreashold && maximumIdleRuntimes > numberOfRuntime) {
                upTicks = 0;
                maximumIdleRuntimes--;
                maximumActiveRuntimes--;
                if (maximumIdleRuntimes < numberOfRuntime) {
                    maximumIdleRuntimes = numberOfRuntime;
                } if (maximumActiveRuntimes < hardMinActiveRuntimes) {
                maximumActiveRuntimes = hardMinActiveRuntimes;
            }
            }
            } else {
                currentlyActiveRuntimes--;
                runtime.tearDown();
            }
        }


    }

    /**
     * Starts the object pool.
     */
    public void start() {
        try {
            if (jrubyLib == null) {
                throw new IllegalStateException("jrubyLib or railsRoot can not be null.");
            }
            int pnum = procs;
            ExecutorService exec = Executors.newFixedThreadPool(pnum + 1);

            for (int i = 0; i < numberOfRuntime; i++) {
                currentlyActiveRuntimes++;
                exec.execute(new Runnable() {

                    public void run() {
                        long startTime = System.currentTimeMillis();
                        Ruby runtime = initializeRubyRuntime();
                        /*                       SelectorThread.logger().log(Level.INFO,
                                                        "JRuby and Rails instance instantiation took: " +
                                                                (System.currentTimeMillis() - startTime) + " ms");
                        */                      SelectorThread.logger().log(Level.INFO,
                            " 	" + (System.currentTimeMillis() - baseTime) + " 	New Ruby instance created	 	 " + (System.currentTimeMillis() - startTime)/1000);
                        queue.offer(runtime);
                    }
                });
            }
            exec.shutdown();
            exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * Creates a new Ruby Runtime, to be called when the last runtime is removed from the queue
     */
    private void makeNewRuntime() {
        if ((currentlyActiveRuntimes < maximumActiveRuntimes) && (currentlyGeneratingRuntimes < maxGeneratingRuntimes)) {
            newTicks += 2;
            //System.out.println("New Ticks: " + newTicks);
            if (newTicks > newThreashold) {
                currentlyActiveRuntimes++;
                currentlyGeneratingRuntimes++;
                newTicks = 0;
                runtimeGenerator.submit(new Runnable() {

                    public void run() {
                        long startTime = System.currentTimeMillis();
                        Ruby runtime = initializeRubyRuntime();
/*                    SelectorThread.logger().log(Level.INFO,
                                "JRuby and Rails instance instantiation took: " +
                                        (System.currentTimeMillis() - startTime) + " ms");
*/                  SelectorThread.logger().log(Level.INFO,
                            " 	" + (System.currentTimeMillis() - baseTime) + " 	New Ruby instance created	 	 " + (System.currentTimeMillis() - startTime)/1000);

                        queue.offer(runtime);
                        currentlyGeneratingRuntimes--;
                    }
                });
            }
        }
    }

    /**
     * Shutdowns the object pool.
     */
    public void stop() {
        for (Ruby ruby : queue) {
            ruby.tearDown();
        }
        queue.clear();
        // Stop our runtime-creation thread
        try {
            runtimeGenerator.shutdown();
            runtimeGenerator.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            SelectorThread.logger().log(Level.WARNING,
                    "Object Pool interrupted on shutdown!");
        }

    }

    private Ruby setupRails(Ruby runtime, File rdebugScript) {
//        long startTime = System.currentTimeMillis();
        LoadService loadService = runtime.getLoadService();

        if (rdebugScript != null) {
            // synchronize io is optional
            String iosynch = System.getProperty("glassfish.rdebug.iosynch");
            if (iosynch != null && iosynch.length() > 0 && new File(iosynch).exists()) {
                SelectorThread.logger().log(Level.FINEST,
                        "rdebug io synchronized by " + new File(iosynch).getAbsolutePath());
                loadService.require(iosynch);
            }

            try {
                SelectorThread.logger().log(Level.FINEST, "Initializing rdebug...");
                runtime.runFromMain(
                        new java.io.BufferedInputStream(new FileInputStream(rdebugScript)),
                        rdebugScript.getAbsolutePath());
                SelectorThread.logger().log(Level.FINE, "rdebug started for " + railsRoot);
            } catch (Exception ex) {
                SelectorThread.logger().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
            }
        } else {
            // load rails
            loadService.require(railsRoot + "/config/environment");
            loadService.require("cgi/force_nph");
            loadService.require("dispatcher");
        }

//        SelectorThread.logger().log(Level.INFO,
//                "loadRailsLibraries took: " +
//                        (System.currentTimeMillis() - startTime) + "ms");
        IRubyObject responder = (JavaEmbedUtils.newRuntimeAdapter()).eval(runtime, getDispatcherString());
        runtime.defineReadonlyVariable("$responder", responder);
//        SelectorThread.logger().log(Level.INFO,
//                "Rails Application: " + railsRoot + " instance instantiation took : " +
//                        (System.currentTimeMillis() - startTime) + "ms");
        return runtime;
    }

    private Ruby initializeRubyRuntime() {
        ArrayList libs = new ArrayList();
        libs.add("META-INF/jruby.home/lib/ruby/site_ruby/1.8");
        ClassCache cache = new ClassCache(RubyObjectPool.class.getClassLoader());
        RubyInstanceConfig config = new RubyInstanceConfig();
        File rdebugScript = configureRDebug(config);
        config.setLoader(RubyObjectPool.class.getClassLoader());
        config.setClassCache(cache);
        Ruby runtime = JavaEmbedUtils.initialize(libs, config);
        return setupRails(runtime, rdebugScript);
    }

    /**
     * Rails debugging for the ruby runtime via rdebug is enabled by setting
     * the following runtime properties.
     *
     *  -Dglassfish.rdebug=
     *  -Dglassfish.rdebug.port= (mandatory)
     *  -Dglassfish.rdebug.version= (optional)
     *  -Dglassfish.rdebug.iosynch= (optional)
     *  -Dglassfish.rdebug.verbose=true enables rdebug diagnostics
     *
     * @param config Ruby runtime configuration object (manages argv for rdebug)
     * @return File reference to rdebug script for execution.
     */
    private File configureRDebug(RubyInstanceConfig config) {
        String rdebug = System.getProperty("glassfish.rdebug");
        File rdebugScript = null;
        if(rdebug != null && rdebug.length() > 0) {
            SelectorThread.logger().log(Level.FINER, "Enabling rdebug-ide for Grizzly/Rails.");
            rdebugScript = new File(rdebug);
            if(rdebugScript.exists()) {
                List args = new ArrayList();

                // version is optional
                String rdebugVersion = System.getProperty("glassfish.rdebug.version");
                if(rdebugVersion != null && rdebugVersion.length() > 0) {
                    args.add(rdebugVersion);
                }

                // port spec is required
                String debugPort = System.getProperty("glassfish.rdebug.port");
                if(debugPort != null && debugPort.length() > 0) {
                    args.add("-p");
                    args.add(debugPort);
                    if("true".equals(System.getProperty("glassfish.rdebug.verbose"))) {
                        args.add("-d");
                    }
                    args.add("--");

                    File script = null;
                    Writer writer = null;
                    try {
                        script = File.createTempFile("grizzly_jruby_debug_", ".rb");
                        script.deleteOnExit();
                        writer = new FileWriter(script);
                        writer.write(
                                "#!/usr/bin/env jruby\n" +
                                        "#\n" +
                                        "# Launch script for Grizzly/JRuby connector when debugging Rails apps\n" +
                                        "# on GlassFish V3.\n" +
                                        "#\n" +
                                        "require \"" + railsRoot.replace("\\", "/") + "/config/environment\"\n" +
                                        "require \"cgi/force_nph\"\n" +
                                        "require \"dispatcher\"\n"
                        );
                        writer.flush();
                        args.add(script.getAbsolutePath());
                        config.setArgv(args.toArray(new String [args.size()]));
                    } catch(IOException ex) {
                        SelectorThread.logger().log(Level.SEVERE,
                                "Error writing Rails launch script for rdebug.", ex);
                        rdebugScript = null;
                    } finally {
                        if(writer != null) {
                            try {
                                writer.close();
                            } catch(IOException ex) {
                                SelectorThread.logger().log(Level.SEVERE,
                                        "Exception closing " + script.getAbsolutePath(), ex);
                            }
                        }
                    }
                } else {
                    SelectorThread.logger().log(Level.SEVERE,
                            "glassfish.rdebug.port undefined.  Disabling rdebug.");
                    rdebugScript = null;
                }
            } else {
                SelectorThread.logger().log(Level.SEVERE,
                        "rdebug-ide script " + rdebugScript.getAbsolutePath() +
                                " does not exist.  Disabling rdebug");
                rdebugScript = null;
            }
        }

        return rdebugScript;
    }


    /**
     * Gets JRUBY_LIB directory.
     *
     * @return JRUBY_LIB directory.
     */
    public String getJrubyLib() {
        return jrubyLib;
    }

    /**
     * Gets the number of directory.
     *
     * @return the number of directory;
     */
    public int getNumberOfRuntime() {
        return numberOfRuntime;
    }

    protected BlockingQueue getRubyRuntimeQueue() {
        return queue;
    }

    public boolean isAsyncEnabled() {
        return asyncEnabled;
    }

    private String getDispatcherString() {
        String str;
        StringBuffer completeText = new StringBuffer();
        try {
            InputStream is = getClass().getResourceAsStream("/dispatch.rb");
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            str = br.readLine();
            while (str != null) {
                completeText.append(str);
                completeText.append("\n");
                str = br.readLine();
            }
        } catch (Exception e) {
            SelectorThread.logger().log(Level.WARNING, "Exception when trying to read the dispatch.rb script", e);
        }

        return completeText.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy