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
}}) | |||||||||||||||