info.voidstar/tbnl.cnc0.1.1-SNAPSHOTC&C controls figureheads through mastermind dependencies
| (this space intentionally left almost blank) | |||||||||||||||
main entry into C&C | (ns cnc.main (:require (core main init)) (:require core.plugin.echo.main core.plugin.nrepl.main cnc.plugin.mastermind.main cnc.plugin.model.figurehead.visualize.main) (:gen-class)) | |||||||||||||||
the main entry | (defn -main [& args] (core.init/require-and-set-default-plugins core.plugin.echo core.plugin.nrepl cnc.plugin.mastermind cnc.plugin.model.figurehead.visualize) (apply core.main/main args)) | |||||||||||||||
connect to Mastermind | (ns cnc.plugin.mastermind.main (:require (core [init :as init] [state :as state] [bus :as bus] [plugin :as plugin])) (:require [clojure.string :as str] [clojure.java.io :as io] [clojure.stacktrace :refer [print-stack-trace]] [clojure.pprint :refer [pprint]] [clojure.core.async :as async :refer [chan thread <!! >!!]]) (:import (java.net Socket SocketTimeoutException))) | |||||||||||||||
(def defaults (atom { :stop-unblock-tag :stop-cnc.plugin.mastermind :mastermind-port 1234 :socket-timeout 15000 :writer-buffer 1000 })) | ||||||||||||||||
(defn populate-parse-opts-vector [current-parse-opts-vector] (init/add-to-parse-opts-vector [ ["-a" "--mastermind-address ADDR" "mastermind address"] (let [option :mastermind-port default (option @defaults)] ["-p" (str "--" (name option) " [PORT]") (str "mastermind port") :default default :parse-fn (get-in @init/parse-opts-vector-helper [:parse-fn :inet-port])]) ])) | ||||||||||||||||
(defn init [options] (when (and (:mastermind-address options) (:mastermind-port options)) true)) | ||||||||||||||||
(defn run [options] (let [verbose (:verbose options) mastermind-address (:mastermind-address options) mastermind-port (:mastermind-port options) instance-id (state/get-state :instance-id)] (let [sock (Socket. ^String mastermind-address ^int mastermind-port)] (plugin/blocking-jail [ ;; timeout nil ;; unblock-tag (:stop-unblock-tag @defaults) ;; finalization (do (.close sock)) ;; verbose verbose ] (.setSoTimeout sock (:socket-timeout @defaults)) ;; reader thread (thread (with-open [^java.io.BufferedReader reader (io/reader sock)] (plugin/looping-jail [ ;; stop condition (plugin/get-state-entry :stop) ;; finalization (do (.close sock)) ;; verbose verbose ] (try (when-let [line (.readLine reader)] (try (let [message (read-string line) topic (bus/get-message-topic message) content (bus/remove-message-topic message)] (when verbose (pprint [:mastermind :reader message])) (case topic :model-update (do (bus/say!! :model-update content)) :information (do (bus/say!! :information content)) :else)) (catch RuntimeException e (when verbose (print-stack-trace e))))) (catch SocketTimeoutException e (when verbose (print-stack-trace e))))))) ;; writer thread (thread (with-open [^java.io.BufferedWriter writer (io/writer sock)] (let [ch (chan (:writer-buffer @defaults))] (bus/register-listener ch) (plugin/looping-jail [ ;; stop condition (plugin/get-state-entry :stop) ;; finalization (do (bus/unregister-listener ch) (.close sock)) ;; verbose verbose ] (let [message (<!! ch) topic (bus/get-message-topic message) content (bus/remove-message-topic message)] (cond ;; do NOT echo these topics back (not (contains? #{:information :model-update} topic)) (let [message (bus/build-message topic (cond (map? content) (merge content {:instance instance-id}) :else {:instance instance-id :content message}))] (when verbose (pprint [:mastermind :writer message])) (.write writer (prn-str message)) (.flush writer)))))))))))) | ||||||||||||||||
(defn stop [] (plugin/set-state-entry :cnc.plugin.mastermind :stop true) (plugin/unblock-thread (:stop-unblock-tag @defaults))) | ||||||||||||||||
the config map | (def config-map {:populate-parse-opts-vector populate-parse-opts-vector :init init :run run :stop stop :param {:priority 90 :auto-restart true}}) | |||||||||||||||
helpers for visualizing figurehead monitor model | (ns cnc.plugin.model.figurehead.visualize.helper (:use [clojure.core.async :as async :only [chan close! go thread >! <! >!! <!! alts! alts!! timeout]] dorothy.core) (:require [clojure.string :as str] [clojure.java.io :as io])) | |||||||||||||||
(defn visualize [model viz-root viz-counter] (let [g (atom []) packages (-> model :packages keys) cur (atom 0)] (doseq [package packages] (let [pkg (get-in model [:packages package])] (swap! cur inc) ;; subgraphs by packages (swap! g conj (subgraph package (apply vector {:label (:name pkg)} (node-attrs {:style :filled :color (str/join " " [(double (* @cur (/ 1 (count packages)))) 1 1])}) (->> (:activities pkg) (map (fn [[id {:keys [name flags]}]] (vector id { :label name :shape (cond (contains? flags :category-home) :house (contains? flags :category-launcher) :box :other :ellipse) }))))))))) ;; edges (let [edges (get model :edges)] (doseq [from (keys edges) to (-> edges (get-in [from :to]) keys)] (apply swap! g conj (repeat (get-in edges [from :to to]) [from to])))) ;; draw the whole graph (let [d (dot (digraph @g)) fname-root (str viz-root "_" viz-counter)] (spit (str fname-root ".dot") d) (save! d (str fname-root ".pdf") {:format :pdf}) (save! d (str fname-root ".png") {:format :png})))) | ||||||||||||||||
visualize figurehead monitor model | (ns cnc.plugin.model.figurehead.visualize.main (:require (core [init :as init] [state :as state] [bus :as bus] [plugin :as plugin])) (:require (cnc.plugin.model.figurehead.visualize [helper :as helper])) (:require [clojure.core.async :as async :refer [chan close! go <! >! alts!]] [clojure.java.io :as io])) | |||||||||||||||
(def defaults (atom { :stop-unblock-tag :stop-cnc.plugin.model.figurehead.visualization })) | ||||||||||||||||
(defn populate-parse-opts-vector [current-parse-opts-vector] (init/add-to-parse-opts-vector [ [nil "--viz" "visualize figurehead model"] [nil "--viz-root [ROOT]" "visualization root file name" :default "viz" ] ])) | ||||||||||||||||
(defn init [options] (let [visualize (:visualize options) viz-root (:viz-root options)] (when (and viz-root) true))) | ||||||||||||||||
(defn run [options] (let [verbose (:verbose options) viz-root (:viz-root options) ch (chan) viz-counter (atom 0)] (plugin/blocking-jail [ ;; timeout nil ;; unblock-tag (:stop-unblock-tag @defaults) ;; finalization (do (bus/unsub-topic ch :model-update)) ;; verbose verbose ] (bus/sub-topic ch :model-update) ;; get the initial model (bus/say!! :command {:topic :get-model :what {}}) ;; listen for model update (go (loop [said (<! ch)] (let [topic (bus/get-message-topic said) content (bus/remove-message-topic said)] (case topic :model-update (do (let [type (:type content) model (:model content)] (case type :figurehead (do (swap! viz-counter inc) (helper/visualize model viz-root @viz-counter)) :else))) :else)) (recur (<! ch))))))) | ||||||||||||||||
(defn stop [] (plugin/set-state-entry :cnc.plugin.model.figurehead.visualization :stop true) (plugin/unblock-thread (:stop-unblock-tag @defaults))) | ||||||||||||||||
the config map | (def config-map { :populate-parse-opts-vector populate-parse-opts-vector :init init :run run :stop stop :param { :priority 1 :auto-restart true }}) | |||||||||||||||