Example usage for java.nio.channels FileLock release

List of usage examples for java.nio.channels FileLock release

Introduction

In this page you can find the example usage for java.nio.channels FileLock release.

Prototype

public abstract void release() throws IOException;

Source Link

Document

Releases this lock.

Usage

From source file:MyZone.Settings.java

private boolean saveXML(String filename, Document dom) {
    File file = null;/*ww  w .ja  v  a 2  s  .c om*/
    FileChannel channel = null;
    FileLock lock = null;
    FileOutputStream toWrite = null;
    try {
        if (!new File(filename).exists()) {
            String dirName = filename.substring(0, filename.lastIndexOf("/"));
            boolean success = (new File(dirName)).mkdirs();
            if (!success && !(new File(dirName)).exists()) {
                return false;
            }
            OutputFormat format = new OutputFormat(dom);
            format.setIndenting(true);
            file = new File(filename);
            toWrite = new FileOutputStream(file, false);
            XMLSerializer serializer = new XMLSerializer(toWrite, format);
            serializer.serialize(dom);
        } else {
            file = new File(filename);
            toWrite = new FileOutputStream(file, false);
            channel = toWrite.getChannel();
            while ((lock = channel.tryLock()) == null) {
                Thread.yield();
            }
            OutputFormat format = new OutputFormat(dom);
            format.setIndenting(true);
            XMLSerializer serializer = new XMLSerializer(toWrite, format);
            serializer.serialize(dom);
            return true;
        }
    } catch (Exception e) {
        if (DEBUG) {
            e.printStackTrace();
        }
        return false;
    } finally {
        try {
            if (lock != null) {
                lock.release();
            }
            if (channel != null) {
                channel.close();
            }
            if (toWrite != null) {
                toWrite.flush();
                toWrite.close();
            }
        } catch (Exception e) {
            if (DEBUG) {
                e.printStackTrace();
            }
            return false;
        }
    }
    return false;
}

From source file:JNLPAppletLauncher.java

private void validateCache(URLConnection conn, File nativeFile, File indexFile) throws IOException {

    // Lock the cache directory
    final String lckFileName = "cache.lck";
    File lckFile = new File(cacheDir, lckFileName);
    lckFile.createNewFile();//ww  w.  j  av  a 2s . co m
    final FileOutputStream lckOut = new FileOutputStream(lckFile);
    final FileChannel lckChannel = lckOut.getChannel();
    final FileLock lckLock = lckChannel.lock();

    try {
        // Check to see whether the cached jar file exists and is valid
        boolean valid = false;
        long cachedTimeStamp = readTimeStamp(indexFile);
        long urlTimeStamp = conn.getLastModified();

        if (nativeFile.exists() && urlTimeStamp > 0 && urlTimeStamp == readTimeStamp(indexFile)) {

            valid = true;
        }

        // Validate the cache, download the jar if needed
        if (!valid) {
            if (VERBOSE) {
                System.err.println("processNativeJar: downloading " + nativeFile.getAbsolutePath());
            }
            indexFile.delete();
            nativeFile.delete();

            // Copy from URL to File
            int len = conn.getContentLength();
            if (VERBOSE) {
                System.err.println("Content length = " + len + " bytes");
            }

            int totalNumBytes = copyURLToFile(conn, nativeFile);
            if (DEBUG) {
                System.err.println("processNativeJar: " + conn.getURL().toString() + " --> "
                        + nativeFile.getAbsolutePath() + " : " + totalNumBytes + " bytes written");
            }

            // Write timestamp to index file.
            writeTimeStamp(indexFile, urlTimeStamp);

        } else {
            if (DEBUG) {
                System.err
                        .println("processNativeJar: using previously cached: " + nativeFile.getAbsolutePath());
            }
        }
    } finally {
        // Unlock the cache directory
        lckLock.release();
    }
}

From source file:com.MainFiles.Functions.java

public int createStan() {
    int x = 0;/*from   w  w w  .j a  v a  2 s.  c o m*/

    String filename = COUNT_FILE;
    File inwrite = new File(filename);

    // Get a file channel for the file
    try {
        FileChannel channel = new RandomAccessFile(inwrite, "rw").getChannel();
        // Use the file channel to create a lock on the file.
        // This method blocks until it can retrieve the lock.
        FileLock lock = channel.lock();
        //  if(!inwrite.exists()) {
        String s = "";
        try {
            int fileSize = (int) channel.size();
            //    System.out.println("int is" + fileSize);
            ByteBuffer bafa = ByteBuffer.allocate(fileSize);
            int numRead = 0;
            while (numRead >= 0) {
                numRead = channel.read(bafa);
                bafa.rewind();
                for (int i = 0; i < numRead; i++) {
                    int b = (int) bafa.get();
                    char c = (char) b;
                    s = s + c;
                }
            }

            x = Integer.parseInt(s);
            if (x > 999999) {
                x = 100000;
            } else if (x < 100000) {
                x = 100000;
            }
            x = ++x;
            String xx = String.valueOf(x);
            byte[] yy = xx.getBytes();
            channel.truncate(0);
            channel.write(ByteBuffer.wrap(yy));
            // channel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        lock.release();
        // Close the file
        channel.close();
    } catch (FileNotFoundException e) {
        String message = "The file " + inwrite.getName() + " does not exist. So no input can be written on it";
        System.out.println(message);
        e.printStackTrace();
        //log to error file
    } catch (IOException e) {
        System.out.println("Problem writing to the logfile " + inwrite.getName());

    }

    filename = "";
    return x;
}

From source file:JNLPAppletLauncher.java

/**
 * Called by the Reaper thread to delete old temp directories
 * Only one of these threads will run per JVM invocation.
 *///www  .j  a  v  a2  s.c  o  m
private static void deleteOldTempDirs() {
    if (VERBOSE) {
        System.err.println("*** Reaper: deleteOldTempDirs in " + tmpBaseDir.getAbsolutePath());
    }

    // enumerate list of jnl*.lck files, ignore our own jlnNNNN file
    final String ourLockFile = tmpRootPropValue + ".lck";
    FilenameFilter lckFilter = new FilenameFilter() {
        /* @Override */
        public boolean accept(File dir, String name) {
            return name.endsWith(".lck") && !name.equals(ourLockFile);
        }
    };

    // For each file <file>.lck in the list we will first try to lock
    // <file>.tmp if that succeeds then we will try to lock <file>.lck
    // (which should always succeed unless there is a problem). If we can
    // get the lock on both files, then it must be an old installation, and
    // we will delete it.
    String[] fileNames = tmpBaseDir.list(lckFilter);
    if (fileNames != null) {
        for (int i = 0; i < fileNames.length; i++) {
            String lckFileName = fileNames[i];
            String tmpDirName = lckFileName.substring(0, lckFileName.lastIndexOf(".lck"));
            String tmpFileName = tmpDirName + ".tmp";

            File lckFile = new File(tmpBaseDir, lckFileName);
            File tmpFile = new File(tmpBaseDir, tmpFileName);
            File tmpDir = new File(tmpBaseDir, tmpDirName);

            if (lckFile.exists() && tmpFile.exists() && tmpDir.isDirectory()) {
                FileOutputStream tmpOut = null;
                FileChannel tmpChannel = null;
                FileLock tmpLock = null;

                try {
                    tmpOut = new FileOutputStream(tmpFile);
                    tmpChannel = tmpOut.getChannel();
                    tmpLock = tmpChannel.tryLock();
                } catch (Exception ex) {
                    // Ignore exceptions
                    if (DEBUG) {
                        ex.printStackTrace();
                    }
                }

                if (tmpLock != null) {
                    FileOutputStream lckOut = null;
                    FileChannel lckChannel = null;
                    FileLock lckLock = null;

                    try {
                        lckOut = new FileOutputStream(lckFile);
                        lckChannel = lckOut.getChannel();
                        lckLock = lckChannel.tryLock();
                    } catch (Exception ex) {
                        if (DEBUG) {
                            ex.printStackTrace();
                        }
                    }

                    if (lckLock != null) {
                        // Recursively remove the old tmpDir and all of
                        // its contents
                        removeAll(tmpDir);

                        // Close the streams and delete the .lck and .tmp
                        // files. Note that there is a slight race condition
                        // in that another process could open a stream at
                        // the same time we are trying to delete it, which will
                        // prevent deletion, but we won't worry about it, since
                        // the worst that will happen is we might have an
                        // occasional 0-byte .lck or .tmp file left around
                        try {
                            lckOut.close();
                        } catch (IOException ex) {
                        }
                        lckFile.delete();
                        try {
                            tmpOut.close();
                        } catch (IOException ex) {
                        }
                        tmpFile.delete();
                    } else {
                        try {
                            // Close the file and channel for the *.lck file
                            if (lckOut != null) {
                                lckOut.close();
                            }
                            // Close the file/channel and release the lock
                            // on the *.tmp file
                            tmpOut.close();
                            tmpLock.release();
                        } catch (IOException ex) {
                            if (DEBUG) {
                                ex.printStackTrace();
                            }
                        }
                    }
                }
            } else {
                if (VERBOSE) {
                    System.err.println("    Skipping: " + tmpDir.getAbsolutePath());
                }
            }
        }
    }
}

From source file:org.alfresco.repo.search.impl.lucene.index.IndexInfo.java

/**
 * An iterative method that retries the operation in the event of the channel being closed.
 * /*from   w ww.j  a  v a  2  s.  co  m*/
 * @param retriesRemaining
 *            the number of retries remaining
 * @return Returns the lock work result
 */
private <R> R doWithFileLock(LockWork<R> lockWork, int retriesRemaining) throws Throwable {
    FileLock fileLock = null;
    R result = null;
    long start = 0L;
    try {
        // Check that the channel is open
        if (!indexInfoChannel.isOpen()) {
            if (lockWork.canRetry()) {
                throw new IndexInfoChannelException("Channel is closed.  Manually triggering reopen attempts");
            } else {
                reopenChannels();
            }
        }

        if (indexIsShared) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug(" ... waiting for file lock");
                start = System.nanoTime();
            }
            fileLock = indexInfoChannel.lock();
            if (s_logger.isDebugEnabled()) {
                long end = System.nanoTime();
                s_logger.debug(" ... got file lock in " + ((end - start) / 10e6f) + " ms");
            }
            if (!checkVersion()) {
                setStatusFromFile();
            }
        }
        result = lockWork.doWork();
        return result;
    } catch (IOException e) {
        if (!lockWork.canRetry()) {
            // We've done our best
            s_logger.warn(
                    "This operation can not retry upon an IOException - it has to roll back to its previous state");
            throw e;
        }
        if (retriesRemaining == 0) {
            // We've done our best
            s_logger.warn("No more channel open retries remaining");
            throw e;
        } else {
            // Attempt to reopen the channel
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("\n" + "Channel is closed.  Will attempt to open it. \n"
                        + "   Retries remaining: " + retriesRemaining);
            }
            try {
                reopenChannels();
                // Loop around and try again
                return doWithFileLock(lockWork, --retriesRemaining);
            } catch (Throwable ee) {
                // Report this error, but throw the original
                s_logger.error("Channel reopen failed on index info files in: " + this.indexDirectory, ee);
                throw e;
            }
        }
    } finally {
        if (fileLock != null) {
            try {
                fileLock.release();
                long end = System.nanoTime();
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug(" ... released file lock after " + ((end - start) / 10e6f) + " ms");
                }
            } catch (IOException e) {
                s_logger.warn("Failed to release file lock: " + e.getMessage(), e);
            }
        }
    }
}

From source file:net.yacy.yacy.java

/**
* Starts up the whole application. Sets up all datastructures and starts
* the main threads.//from   w  w  w .j  a v  a  2s  . co  m
*
* @param homePath Root-path where all information is to be found.
* @param startupFree free memory at startup time, to be used later for statistics
*/
private static void startup(final File dataHome, final File appHome, final long startupMemFree,
        final long startupMemTotal, final boolean gui) {
    String tmpdir = null;
    try {
        // start up
        System.out.println(copyright);
        System.out.println(hline);

        // ensure that there is a DATA directory, if not, create one and if that fails warn and die
        mkdirsIfNeseccary(dataHome);
        mkdirsIfNeseccary(appHome);
        File f = new File(dataHome, "DATA/");
        mkdirsIfNeseccary(f);
        if (!(f.exists())) {
            System.err.println("Error creating DATA-directory in " + dataHome.toString()
                    + " . Please check your write-permission for this folder. YaCy will now terminate.");
            System.exit(-1);
        }

        // set jvm tmpdir to a subdir for easy cleanup (as extensive use file.deleteonexit waists memory during long runs, as todelete files names are collected and never cleaned up during runtime)
        // keep this as earlier as possible, as any other class can use the "java.io.tmpdir" property, even the log manager, when the log file pattern uses "%t" as an alias for the tmp directory 
        try {
            tmpdir = java.nio.file.Files.createTempDirectory("yacy-tmp-").toString(); // creates sub dir in jvm's temp (see System.property "java.io.tempdir")
            System.setProperty("java.io.tmpdir", tmpdir);
        } catch (IOException ex) {
        }

        // setting up logging
        f = new File(dataHome, "DATA/LOG/");
        mkdirsIfNeseccary(f);
        f = new File(dataHome, "DATA/LOG/yacy.logging");
        final File f0 = new File(appHome, "defaults/yacy.logging");
        if (!f.exists() || f0.lastModified() > f.lastModified())
            try {
                Files.copy(f0, f);
            } catch (final IOException e) {
                System.out.println("could not copy yacy.logging");
            }
        try {
            ConcurrentLog.configureLogging(dataHome, new File(dataHome, "DATA/LOG/yacy.logging"));
        } catch (final IOException e) {
            System.out.println("could not find logging properties in homePath=" + dataHome);
            ConcurrentLog.logException(e);
        }
        ConcurrentLog.config("STARTUP", "YaCy version: " + yacyBuildProperties.getVersion() + "/"
                + yacyBuildProperties.getSVNRevision());
        ConcurrentLog.config("STARTUP",
                "Java version: " + System.getProperty("java.version", "no-java-version"));
        ConcurrentLog.config("STARTUP", "Operation system: " + System.getProperty("os.name", "unknown"));
        ConcurrentLog.config("STARTUP", "Application root-path: " + appHome);
        ConcurrentLog.config("STARTUP", "Data root-path: " + dataHome);
        ConcurrentLog.config("STARTUP", "Time zone: UTC" + GenericFormatter.UTCDiffString() + "; UTC+0000 is "
                + System.currentTimeMillis());
        ConcurrentLog.config("STARTUP", "Maximum file system path length: " + OS.maxPathLength);

        f = new File(dataHome, "DATA/yacy.running");
        final String conf = "DATA/SETTINGS/yacy.conf".replace("/", File.separator);
        if (!f.createNewFile())
            ConcurrentLog.severe("STARTUP", "WARNING: the file " + f + " can not be created!");
        try {
            new FileOutputStream(f).write(Integer.toString(OS.getPID()).getBytes());
        } catch (final Exception e) {
        } // write PID
        f.deleteOnExit();
        FileChannel channel = null;
        FileLock lock = null;
        try {
            channel = new RandomAccessFile(f, "rw").getChannel();
            lock = channel.tryLock(); // lock yacy.running
        } catch (final Exception e) {
        }

        try {
            sb = new Switchboard(dataHome, appHome, "defaults/yacy.init".replace("/", File.separator), conf);
        } catch (final RuntimeException e) {
            ConcurrentLog.severe("STARTUP", "YaCy cannot start: " + e.getMessage(), e);
            System.exit(-1);
        }
        //sbSync.V(); // signal that the sb reference was set

        // switch the memory strategy
        MemoryControl.setStandardStrategy(sb.getConfigBool("memory.standardStrategy", true));

        // save information about available memory at startup time
        sb.setConfig("memoryFreeAfterStartup", startupMemFree);
        sb.setConfig("memoryTotalAfterStartup", startupMemTotal);

        // start gui if wanted
        if (gui)
            YaCyApp.start("localhost", sb.getLocalPort());

        // hardcoded, forced, temporary value-migration
        sb.setConfig("htTemplatePath", "htroot/env/templates");

        double oldVer;
        try {
            String tmpversion = sb.getConfig(Seed.VERSION, "");
            if (tmpversion.isEmpty()) { // before 1.83009737 only the svnRevision nr was in config (like 9737)
                tmpversion = yacyBuildProperties.getVersion();
                int oldRev = Integer.parseInt(sb.getConfig("svnRevision", "0"));
                if (oldRev > 1) {
                    oldVer = Double.parseDouble(tmpversion) + oldRev / 100000000.0;
                } else {
                    oldVer = Double.parseDouble(yacyBuildProperties.getLongVersion()); // failsafe (assume current version = no migration)
                }
            } else {
                oldVer = Double.parseDouble(tmpversion);
            }
        } catch (final NumberFormatException e) {
            oldVer = 0.0d;
        }
        final double newRev = Double.parseDouble(yacyBuildProperties.getLongVersion());
        sb.setConfig(Seed.VERSION, yacyBuildProperties.getLongVersion());
        sb.setConfig("applicationRoot", appHome.toString());
        sb.setConfig("dataRoot", dataHome.toString());

        // create some directories
        final File htRootPath = new File(appHome,
                sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT));
        mkdirIfNeseccary(htRootPath);
        htDocsPath = sb.getDataPath(SwitchboardConstants.HTDOCS_PATH, SwitchboardConstants.HTDOCS_PATH_DEFAULT);
        mkdirIfNeseccary(htDocsPath);
        //final File htTemplatePath = new File(homePath, sb.getConfig("htTemplatePath","htdocs"));

        // copy the donate iframe (better to copy this once here instead of doing this in an actual iframe in the search result)
        importDonationIFrame(sb, htDocsPath);

        // create default notifier picture
        File notifierFile = new File(htDocsPath, "notifier.gif");
        if (!notifierFile.exists())
            try {
                Files.copy(new File(htRootPath, "env/grafics/empty.gif"), notifierFile);
            } catch (final IOException e) {
            }

        final File htdocsReadme = new File(htDocsPath, "readme.txt");
        if (!(htdocsReadme.exists()))
            try {
                FileUtils.copy(("This is your root directory for individual Web Content\r\n" + "\r\n"
                        + "Please place your html files into the www subdirectory.\r\n"
                        + "The URL of that path is either\r\n" + "http://www.<your-peer-name>.yacy    or\r\n"
                        + "http://<your-ip>:<your-port>/www\r\n" + "\r\n"
                        + "Other subdirectories may be created; they map to corresponding sub-domains.\r\n"
                        + "This directory shares it's content with the applications htroot path, so you\r\n"
                        + "may access your yacy search page with\r\n" + "http://<your-peer-name>.yacy/\r\n"
                        + "\r\n").getBytes(), htdocsReadme);
            } catch (final IOException e) {
                System.out.println("Error creating htdocs readme: " + e.getMessage());
            }

        shareDefaultPath = new File(htDocsPath, "share");
        mkdirIfNeseccary(shareDefaultPath);
        shareDumpDefaultPath = new File(shareDefaultPath, "dump");
        mkdirIfNeseccary(shareDumpDefaultPath);

        migration.migrate(sb, oldVer, newRev);

        // delete old release files
        final int deleteOldDownloadsAfterDays = (int) sb.getConfigLong("update.deleteOld", 30);
        yacyRelease.deleteOldDownloads(sb.releasePath, deleteOldDownloadsAfterDays);

        // set user-agent
        HTTPClient.setDefaultUserAgent(ClientIdentification.yacyInternetCrawlerAgent.userAgent);

        // start main threads
        final int port = sb.getLocalPort();
        try {
            // start http server
            YaCyHttpServer httpServer;
            httpServer = new Jetty9HttpServerImpl(port);
            httpServer.startupServer();
            sb.setHttpServer(httpServer);
            // TODO: this has no effect on Jetty (but needed to reflect configured value and limit is still used)
            ConnectionInfo.setServerMaxcount(sb.getConfigInt("connectionsMax", ConnectionInfo.getMaxcount()));

            ConcurrentLog.info("STARTUP", httpServer.getVersion());

            // open the browser window
            final boolean browserPopUpTrigger = sb
                    .getConfig(SwitchboardConstants.BROWSER_POP_UP_TRIGGER, "true").equals("true");
            if (browserPopUpTrigger)
                try {
                    final String browserPopUpPage = sb.getConfig(SwitchboardConstants.BROWSER_POP_UP_PAGE,
                            "ConfigBasic.html");
                    //boolean properPW = (sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT, "").isEmpty()) && (sb.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, "").length() > 0);
                    //if (!properPW) browserPopUpPage = "ConfigBasic.html";
                    /* YaCy main startup process must not hang because browser opening is long or fails. 
                     * Let's open try opening the browser in a separate thread */
                    new Thread("Browser opening") {
                        @Override
                        public void run() {
                            Browser.openBrowser(("http://localhost:" + port) + "/" + browserPopUpPage);
                        }
                    }.start();
                    // Browser.openBrowser((server.withSSL()?"https":"http") + "://localhost:" + serverCore.getPortNr(port) + "/" + browserPopUpPage);
                } catch (final Throwable e) {
                    // cannot open browser. This may be normal in headless environments
                    //Log.logException(e);
                }

            // enable browser popup, http server is ready now
            sb.tray.setReady();

            //regenerate Locales from Translationlist, if needed
            final File locale_source = sb.getAppPath("locale.source", "locales");
            final String lang = sb.getConfig("locale.language", "");
            // on lang=browser all active translation should be checked (because any could be requested by client)
            List<String> langlist;
            if (lang.endsWith("browser"))
                langlist = Translator.activeTranslations(); // get all translated languages
            else {
                langlist = new ArrayList<String>();
                langlist.add(lang);
            }
            for (String tmplang : langlist) {
                if (!tmplang.equals("") && !tmplang.equals("default") && !tmplang.equals("browser")) { //locale is used
                    String currentRev = null;
                    BufferedReader br = null;
                    try {
                        br = new BufferedReader(new InputStreamReader(new FileInputStream(
                                new File(sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"),
                                        tmplang + "/version"))));
                        currentRev = br.readLine(); // may return null
                    } catch (final IOException e) {
                        //Error
                    } finally {
                        try {
                            br.close();
                        } catch (IOException ioe) {
                            ConcurrentLog.warn("STARTUP", "Could not close " + tmplang + " version file");
                        }
                    }

                    if (currentRev == null || !currentRev.equals(sb.getConfig(Seed.VERSION, ""))) {
                        try { //is this another version?!
                            final File sourceDir = new File(sb.getConfig(SwitchboardConstants.HTROOT_PATH,
                                    SwitchboardConstants.HTROOT_PATH_DEFAULT));
                            final File destDir = new File(
                                    sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"), tmplang);
                            if (new TranslatorXliff().translateFilesRecursive(sourceDir, destDir,
                                    new File(locale_source, tmplang + ".lng"), "html,template,inc", "locale")) { //translate it
                                //write the new Versionnumber
                                final BufferedWriter bw = new BufferedWriter(
                                        new PrintWriter(new FileWriter(new File(destDir, "version"))));
                                bw.write(sb.getConfig(Seed.VERSION, "Error getting Version"));
                                bw.close();
                            }
                        } catch (final IOException e) {
                        }
                    }
                }
            }
            // initialize number formatter with this locale
            if (!lang.equals("browser")) // "default" is handled by .setLocale()
                Formatter.setLocale(lang);

            // registering shutdown hook
            ConcurrentLog.config("STARTUP", "Registering Shutdown Hook");
            final Runtime run = Runtime.getRuntime();
            run.addShutdownHook(new shutdownHookThread(sb, shutdownSemaphore));

            // save information about available memory after all initializations
            //try {
            sb.setConfig("memoryFreeAfterInitBGC", MemoryControl.free());
            sb.setConfig("memoryTotalAfterInitBGC", MemoryControl.total());
            System.gc();
            sb.setConfig("memoryFreeAfterInitAGC", MemoryControl.free());
            sb.setConfig("memoryTotalAfterInitAGC", MemoryControl.total());
            //} catch (final ConcurrentModificationException e) {}

            // wait for server shutdown
            try {
                sb.waitForShutdown();
            } catch (final Exception e) {
                ConcurrentLog.severe("MAIN CONTROL LOOP", "PANIC: " + e.getMessage(), e);
            }
            // shut down
            Array.terminate();
            ConcurrentLog.config("SHUTDOWN", "caught termination signal");
            httpServer.stop();

            ConcurrentLog.config("SHUTDOWN", "server has terminated");
            sb.close();
        } catch (final Exception e) {
            ConcurrentLog.severe("STARTUP", "Unexpected Error: " + e.getClass().getName(), e);
            //System.exit(1);
        }
        if (lock != null)
            lock.release();
        if (channel != null)
            channel.close();
    } catch (final Exception ee) {
        ConcurrentLog.severe("STARTUP", "FATAL ERROR: " + ee.getMessage(), ee);
    } finally {
    }

    if (tmpdir != null)
        FileUtils.deletedelete(new File(tmpdir)); // clean up temp dir (set at startup as subdir of system.propery "java.io.tmpdir")

    ConcurrentLog.config("SHUTDOWN", "goodbye. (this is the last line)");
    ConcurrentLog.shutdown();
    shutdownSemaphore.release(1000);
    try {
        System.exit(0);
    } catch (final Exception e) {
    } // was once stopped by de.anomic.net.ftpc$sm.checkExit(ftpc.java:1790)
}