                         (if loading
                           (embedded/load-persistent db-path)
                           (embedded/init-persistent db-path)))]
-    (printf "FleetDB serving '%s' protocol on port %d\n" (name protocol) port)
+    (printf "FleetDB is ready on port %d\n" port)
     (flush)
     (loop []
       (let [socket (doto (.accept server-socket))]

      (recur))))

(defn- print-help []
  (println "FleetDB Server                                                               ")
  (println "-f <path>   Path to database log file                                        ")
  (println "-e          Ephemeral: do not log changes to disk                            ")
  (println "-p <port>   TCP port to listen on (default: 3400)                            ")
  (println "-a <addr>   Local address to listen on (default: 127.0.0.1)                  ")
  (println "-t <num>    Maximum number of worker threads (default: 100)                  ")
  (println "-i <name>   Client/server protocol: one of {text,binary,bert,bert-rpc} (default: bert)")
  (println "-h          Print this help and exit.                                        "))

(defn- parse-int [s]
  (and s (Integer/decode s)))

(defn -main [& args]
  (let [args-array  (into-array String args)
        opt-parser (OptionParser. "f:ep:a:t:i:h")
        opt-set    (.parse opt-parser args-array)]
    (cond
      (not-any? #(.has opt-set #^String %) ["f" "e" "p" "a" "t" "i" "h"])
        (print-help)
      (.has opt-set "h")
        (print-help)

(ns fleetdb.server
  (:use     (fleetdb util))
  (:require (fleetdb [embedded :as embedded] [io :as io]
                     [file :as file] [thread-pool :as thread-pool])
            (clj-stacktrace [repl :as stacktrace])
            (clojure.contrib [str-utils :as str-utils]))
  (:import  (java.net ServerSocket Socket InetAddress)
            (joptsimple OptionParser OptionSet OptionException))
  (:gen-class))

(defn- server-query [dba q]
  (let [[q-type q-opt] q]
    (condp = q-type
      "ping"     "pong"
      "compact"  (embedded/compact dba)
      "snapshot" (embedded/snapshot dba q-opt)
      nil)))

(defn- process-query [dba q]
  (or (server-query dba q)
      (embedded/query dba q)))

(defn handler [dba #^Socket socket]
  (try
    (with-open [socket    socket
                generator (io/os->generator (.getOutputStream socket))
                parser    (io/in->parser    (.getInputStream socket))]
      (.setKeepAlive socket true)
      (loop []
        (if (try
              (let [query (io/parse parser io/eof)]
                (if (= query io/eof)
                  false
                  (let [result (process-query dba query)]
                    (io/generate generator [0 result])
                    true)))
              (catch Exception e
                (io/generate out
                  (if (raised? e)
                    [1 (str e)]
                    [2 (pst-str e)]))
                true))
            (recur))))
    (catch Exception e
      (stacktrace/pst-on System/err false e)
      (.println System/err))))

(defn run [db-path ephemeral port addr threads]
  (let [inet          (InetAddress/getByName addr)
        server-socket (ServerSocket. port 10000 inet)
        pool          (thread-pool/init threads)
        loading       (and db-path (file/exist? db-path))
        dba           (if ephemeral
                        (if loading
