Skip to content
Snippets Groups Projects
Unverified Commit a996497e authored by Wolfgang Welz's avatar Wolfgang Welz Committed by GitHub
Browse files

Merge pull request #67 from iotaledger/feat/plugin-status

Manually enable/disable plugins
parents 8044edd0 3593d7d2
No related branches found
No related tags found
No related merge requests found
Showing
with 155 additions and 67 deletions
package node
import (
"strings"
"sync"
"github.com/iotaledger/goshimmer/packages/daemon"
......@@ -14,8 +13,9 @@ type Node struct {
}
var DisabledPlugins = make(map[string]bool)
var EnabledPlugins = make(map[string]bool)
func Load(plugins ...*Plugin) *Node {
func New(plugins ...*Plugin) *Node {
node := &Node{
loggers: make([]*Logger, 0),
wg: &sync.WaitGroup{},
......@@ -23,20 +23,22 @@ func Load(plugins ...*Plugin) *Node {
}
node.AddLogger(DEFAULT_LOGGER)
node.Load(plugins...)
// configure the enabled plugins
node.configure(plugins...)
return node
}
func Start(plugins ...*Plugin) *Node {
node := Load(plugins...)
node := New(plugins...)
node.Start()
return node
}
func Run(plugins ...*Plugin) *Node {
node := Load(plugins...)
node := New(plugins...)
node.Run()
return node
......@@ -100,19 +102,33 @@ func (node *Node) LogFailure(pluginName string, message string) {
}
}
func (node *Node) Load(plugins ...*Plugin) {
if len(plugins) >= 1 {
for _, plugin := range plugins {
if _, exists := DisabledPlugins[strings.ToLower(strings.Replace(plugin.Name, " ", "", -1))]; !exists {
plugin.wg = node.wg
plugin.Node = node
func isDisabled(plugin *Plugin) bool {
_, exists := DisabledPlugins[GetPluginIdentifier(plugin.Name)]
plugin.Events.Configure.Trigger(plugin)
return exists
}
node.LogInfo("Node", "Loading Plugin: "+plugin.Name+" ... done")
func isEnabled(plugin *Plugin) bool {
_, exists := EnabledPlugins[GetPluginIdentifier(plugin.Name)]
node.loadedPlugins = append(node.loadedPlugins, plugin)
}
return exists
}
func (node *Node) configure(plugins ...*Plugin) {
for _, plugin := range plugins {
status := plugin.Status
if (status == Enabled && !isDisabled(plugin)) ||
(status == Disabled && isEnabled(plugin)) {
plugin.wg = node.wg
plugin.Node = node
plugin.Events.Configure.Trigger(plugin)
node.loadedPlugins = append(node.loadedPlugins, plugin)
node.LogInfo("Node", "Loading Plugin: "+plugin.Name+" ... done")
} else {
node.LogInfo("Node", "Skipping Plugin: "+plugin.Name)
}
}
}
......@@ -120,12 +136,10 @@ func (node *Node) Load(plugins ...*Plugin) {
func (node *Node) Start() {
node.LogInfo("Node", "Executing plugins ...")
if len(node.loadedPlugins) >= 1 {
for _, plugin := range node.loadedPlugins {
plugin.Events.Run.Trigger(plugin)
for _, plugin := range node.loadedPlugins {
plugin.Events.Run.Trigger(plugin)
node.LogSuccess("Node", "Starting Plugin: "+plugin.Name+" ... done")
}
node.LogSuccess("Node", "Starting Plugin: "+plugin.Name+" ... done")
}
node.LogSuccess("Node", "Starting background workers ...")
......@@ -136,12 +150,10 @@ func (node *Node) Start() {
func (node *Node) Run() {
node.LogInfo("Node", "Executing plugins ...")
if len(node.loadedPlugins) >= 1 {
for _, plugin := range node.loadedPlugins {
plugin.Events.Run.Trigger(plugin)
for _, plugin := range node.loadedPlugins {
plugin.Events.Run.Trigger(plugin)
node.LogSuccess("Node", "Starting Plugin: "+plugin.Name+" ... done")
}
node.LogSuccess("Node", "Starting Plugin: "+plugin.Name+" ... done")
}
node.LogSuccess("Node", "Starting background workers ...")
......
......@@ -3,6 +3,8 @@ package node
import "github.com/iotaledger/goshimmer/packages/parameter"
var (
LOG_LEVEL = parameter.AddInt("NODE/LOG_LEVEL", LOG_LEVEL_INFO, "controls the log types that are shown")
LOG_LEVEL = parameter.AddInt("NODE/LOG_LEVEL", LOG_LEVEL_INFO, "controls the log types that are shown")
DISABLE_PLUGINS = parameter.AddString("NODE/DISABLE_PLUGINS", "", "a list of plugins that shall be disabled")
ENABLE_PLUGINS = parameter.AddString("NODE/ENABLE_PLUGINS", "", "a list of plugins that shall be enabled")
)
package node
import (
"strings"
"sync"
"github.com/iotaledger/goshimmer/packages/events"
"github.com/iotaledger/goshimmer/packages/parameter"
)
const (
Disabled = iota
Enabled
)
type Plugin struct {
Node *Node
Name string
Status int
Events pluginEvents
wg *sync.WaitGroup
}
func NewPlugin(name string, callback Callback, callbacks ...Callback) *Plugin {
// Creates a new plugin with the given name, default status and callbacks.
// The last specified callback is the mandatory run callback, while all other callbacks are configure callbacks.
func NewPlugin(name string, status int, callback Callback, callbacks ...Callback) *Plugin {
plugin := &Plugin{
Name: name,
Name: name,
Status: status,
Events: pluginEvents{
Configure: events.NewEvent(pluginCaller),
Run: events.NewEvent(pluginCaller),
},
}
// make the plugin known to the parameters
parameter.AddPlugin(name, status)
if len(callbacks) >= 1 {
plugin.Events.Configure.Attach(events.NewClosure(callback))
for _, callback = range callbacks[:len(callbacks)-1] {
......@@ -36,6 +50,10 @@ func NewPlugin(name string, callback Callback, callbacks ...Callback) *Plugin {
return plugin
}
func GetPluginIdentifier(name string) string {
return strings.ToLower(strings.Replace(name, " ", "", -1))
}
func (plugin *Plugin) LogSuccess(message string) {
plugin.Node.LogSuccess(plugin.Name, message)
}
......
......@@ -8,10 +8,12 @@ var Events = struct {
AddBool *events.Event
AddInt *events.Event
AddString *events.Event
AddPlugin *events.Event
}{
AddBool: events.NewEvent(boolParameterCaller),
AddInt: events.NewEvent(intParameterCaller),
AddString: events.NewEvent(stringParameterCaller),
AddPlugin: events.NewEvent(pluginParameterCaller),
}
func boolParameterCaller(handler interface{}, params ...interface{}) {
......@@ -25,3 +27,7 @@ func intParameterCaller(handler interface{}, params ...interface{}) {
func stringParameterCaller(handler interface{}, params ...interface{}) {
handler.(func(*StringParameter))(params[0].(*StringParameter))
}
func pluginParameterCaller(handler interface{}, params ...interface{}) {
handler.(func(string, int))(params[0].(string), params[1].(int))
}
......@@ -32,7 +32,7 @@ func GetBools() map[string]*BoolParameter {
var intParameters = make(map[string]*IntParameter)
func AddInt(name string, defaultValue int, description string) *IntParameter {
if intParameters[name] != nil {
if _, exists := intParameters[name]; exists {
panic("duplicate parameter - \"" + name + "\" was defined already")
}
......@@ -61,7 +61,7 @@ func GetInts() map[string]*IntParameter {
var stringParameters = make(map[string]*StringParameter)
func AddString(name string, defaultValue string, description string) *StringParameter {
if stringParameters[name] != nil {
if _, exists := stringParameters[name]; exists {
panic("duplicate parameter - \"" + name + "\" was defined already")
}
......@@ -86,3 +86,19 @@ func GetString(name string) *StringParameter {
func GetStrings() map[string]*StringParameter {
return stringParameters
}
var plugins = make(map[string]int)
func AddPlugin(name string, status int) {
if _, exists := plugins[name]; exists {
panic("duplicate plugin - \"" + name + "\" was defined already")
}
plugins[name] = status
Events.AddPlugin.Trigger(name, status)
}
func GetPlugins() map[string]int {
return plugins
}
......@@ -9,7 +9,7 @@ import (
"github.com/iotaledger/goshimmer/plugins/analysis/webinterface"
)
var PLUGIN = node.NewPlugin("Analysis", configure, run)
var PLUGIN = node.NewPlugin("Analysis", node.Enabled, configure, run)
func configure(plugin *node.Plugin) {
if *server.SERVER_PORT.Value != 0 {
......
......@@ -16,7 +16,7 @@ import (
"github.com/iotaledger/goshimmer/plugins/gossip"
)
var PLUGIN = node.NewPlugin("Auto Peering", configure, run)
var PLUGIN = node.NewPlugin("Auto Peering", node.Enabled, configure, run)
func configure(plugin *node.Plugin) {
saltmanager.Configure(plugin)
......
......@@ -9,7 +9,7 @@ import (
"github.com/iotaledger/goshimmer/plugins/tangle"
)
var PLUGIN = node.NewPlugin("Bundle Processor", configure, run)
var PLUGIN = node.NewPlugin("Bundle Processor", node.Enabled, configure, run)
func configure(plugin *node.Plugin) {
tangle.Events.TransactionSolid.Attach(events.NewClosure(func(tx *value_transaction.ValueTransaction) {
......
......@@ -5,6 +5,10 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"github.com/iotaledger/goshimmer/packages/node"
)
func AddBoolParameter(p *bool, name string, usage string) {
......@@ -19,20 +23,36 @@ func AddStringParameter(p *string, name string, usage string) {
flag.StringVar(p, name, *p, usage)
}
var enabledPlugins []string
var disabledPlugins []string
func AddPluginStatus(name string, status int) {
switch status {
case node.Enabled:
enabledPlugins = append(enabledPlugins, name)
case node.Disabled:
disabledPlugins = append(disabledPlugins, name)
}
}
func getList(a []string) string {
sort.Strings(a)
return strings.Join(a, " ")
}
func printUsage() {
_, err := fmt.Fprintf(
fmt.Fprintf(
os.Stderr,
"\n"+
"SHIMMER 1.0\n\n"+
"SHIMMER\n\n"+
" A lightweight modular IOTA node.\n\n"+
"Usage:\n\n"+
" %s [OPTIONS]\n\n"+
"Options:\n\n",
"Options:\n",
filepath.Base(os.Args[0]),
)
if err != nil {
panic(err)
}
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nThe following plugins are enabled by default and can be disabled with -%s:\n %s\n", getFlagName(node.DISABLE_PLUGINS.Name), getList(enabledPlugins))
fmt.Fprintf(os.Stderr, "The following plugins are disabled by default and can be enabled with -%s:\n %s\n\n", getFlagName(node.ENABLE_PLUGINS.Name), getList(disabledPlugins))
}
......@@ -10,50 +10,61 @@ import (
"github.com/iotaledger/goshimmer/packages/parameter"
)
func onAddBoolParameter(param *parameter.BoolParameter) {
flagName := strings.Replace(strings.Replace(strings.ToLower(param.Name), "/", "-", 1), "_", "-", -1)
func getFlagName(paramName string) string {
return strings.Replace(strings.Replace(strings.ToLower(paramName), "/", "-", 1), "_", "-", -1)
}
AddBoolParameter(param.Value, flagName, param.Description)
func onAddBoolParameter(param *parameter.BoolParameter) {
AddBoolParameter(param.Value, getFlagName(param.Name), param.Description)
}
func onAddIntParameter(param *parameter.IntParameter) {
flagName := strings.Replace(strings.Replace(strings.ToLower(param.Name), "/", "-", 1), "_", "-", -1)
AddIntParameter(param.Value, flagName, param.Description)
AddIntParameter(param.Value, getFlagName(param.Name), param.Description)
}
func onAddStringParameter(param *parameter.StringParameter) {
flagName := strings.Replace(strings.Replace(strings.ToLower(param.Name), "/", "-", 1), "_", "-", -1)
AddStringParameter(param.Value, getFlagName(param.Name), param.Description)
}
AddStringParameter(param.Value, flagName, param.Description)
func onAddPlugin(name string, status int) {
AddPluginStatus(node.GetPluginIdentifier(name), status)
}
func init() {
for _, param := range parameter.GetBools() {
onAddBoolParameter(param)
}
for _, param := range parameter.GetInts() {
onAddIntParameter(param)
}
for _, param := range parameter.GetStrings() {
onAddStringParameter(param)
}
for name, status := range parameter.GetPlugins() {
onAddPlugin(name, status)
}
parameter.Events.AddBool.Attach(events.NewClosure(onAddBoolParameter))
parameter.Events.AddInt.Attach(events.NewClosure(onAddIntParameter))
parameter.Events.AddString.Attach(events.NewClosure(onAddStringParameter))
parameter.Events.AddPlugin.Attach(events.NewClosure(onAddPlugin))
flag.Usage = printUsage
}
func parseParameters() {
for _, pluginName := range strings.Fields(*node.DISABLE_PLUGINS.Value) {
node.DisabledPlugins[strings.ToLower(pluginName)] = true
}
for _, pluginName := range strings.Fields(*node.ENABLE_PLUGINS.Value) {
node.EnabledPlugins[strings.ToLower(pluginName)] = true
}
}
func configure(ctx *node.Plugin) {
flag.Parse()
for _, disabledPlugin := range strings.Fields(*node.DISABLE_PLUGINS.Value) {
node.DisabledPlugins[strings.ToLower(disabledPlugin)] = true
}
parseParameters()
fmt.Println(" _____ _ _ ________ ______ ___ ___________ ")
fmt.Println(" / ___| | | |_ _| \\/ || \\/ || ___| ___ \\")
......@@ -66,6 +77,8 @@ func configure(ctx *node.Plugin) {
ctx.Node.LogInfo("Node", "Loading plugins ...")
}
var PLUGIN = node.NewPlugin("CLI", configure, func(plugin *node.Plugin) {
func run(ctx *node.Plugin) {
// do nothing; everything is handled in the configure step
}
})
var PLUGIN = node.NewPlugin("CLI", node.Enabled, configure, run)
package dashboard
import (
"golang.org/x/net/context"
"net/http"
"time"
"golang.org/x/net/context"
"github.com/iotaledger/goshimmer/packages/daemon"
"github.com/iotaledger/goshimmer/packages/events"
"github.com/iotaledger/goshimmer/packages/node"
......@@ -13,9 +14,9 @@ import (
var server *http.Server
var router *http.ServeMux
var router *http.ServeMux
var PLUGIN = node.NewPlugin("Dashboard", configure, run)
var PLUGIN = node.NewPlugin("Dashboard", node.Disabled, configure, run)
func configure(plugin *node.Plugin) {
router = http.NewServeMux()
......
......@@ -8,7 +8,7 @@ import (
"github.com/iotaledger/goshimmer/plugins/tangle"
)
var PLUGIN = node.NewPlugin("Gossip On Solidification", func(plugin *node.Plugin) {
var PLUGIN = node.NewPlugin("Gossip On Solidification", node.Enabled, func(plugin *node.Plugin) {
tangle.Events.TransactionSolid.Attach(events.NewClosure(func(tx *value_transaction.ValueTransaction) {
gossip.SendTransaction(tx.MetaTransaction)
}))
......
......@@ -4,7 +4,7 @@ import (
"github.com/iotaledger/goshimmer/packages/node"
)
var PLUGIN = node.NewPlugin("Gossip", configure, run)
var PLUGIN = node.NewPlugin("Gossip", node.Enabled, configure, run)
func configure(plugin *node.Plugin) {
configureNeighbors(plugin)
......
......@@ -15,7 +15,7 @@ import (
// maximum amount of time to wait for background processes to terminate. After that the process is killed.
const WAIT_TO_KILL_TIME_IN_SECONDS = 10
var PLUGIN = node.NewPlugin("Graceful Shutdown", func(plugin *node.Plugin) {
var PLUGIN = node.NewPlugin("Graceful Shutdown", node.Enabled, func(plugin *node.Plugin) {
gracefulStop := make(chan os.Signal)
signal.Notify(gracefulStop, syscall.SIGTERM)
......
......@@ -11,7 +11,7 @@ import (
"github.com/iotaledger/goshimmer/plugins/gossip"
)
var PLUGIN = node.NewPlugin("Metrics", configure, run)
var PLUGIN = node.NewPlugin("Metrics", node.Enabled, configure, run)
func configure(plugin *node.Plugin) {
// increase received TPS counter whenever we receive a new transaction
......
......@@ -23,7 +23,7 @@ var receivedTps uint64
var solidTps uint64
var PLUGIN = node.NewPlugin("Statusscreen TPS", func(plugin *node.Plugin) {
var PLUGIN = node.NewPlugin("Statusscreen TPS", node.Enabled, func(plugin *node.Plugin) {
gossip.Events.ReceiveTransaction.Attach(events.NewClosure(func(_ *meta_transaction.MetaTransaction) {
atomic.AddUint64(&receivedTpsCounter, 1)
}))
......
......@@ -142,4 +142,4 @@ func run(plugin *node.Plugin) {
})
}
var PLUGIN = node.NewPlugin("Status Screen", configure, run)
var PLUGIN = node.NewPlugin("Status Screen", node.Enabled, configure, run)
......@@ -6,7 +6,7 @@ import (
// region plugin module setup //////////////////////////////////////////////////////////////////////////////////////////
var PLUGIN = node.NewPlugin("Tangle", configure, run)
var PLUGIN = node.NewPlugin("Tangle", node.Enabled, configure, run)
func configure(plugin *node.Plugin) {
configureTransactionDatabase(plugin)
......
......@@ -7,7 +7,7 @@ import (
"github.com/iotaledger/goshimmer/plugins/tangle"
)
var PLUGIN = node.NewPlugin("Tipselection", configure, run)
var PLUGIN = node.NewPlugin("Tipselection", node.Enabled, configure, run)
func configure(node *node.Plugin) {
tangle.Events.TransactionSolid.Attach(events.NewClosure(func(transaction *value_transaction.ValueTransaction) {
......
......@@ -13,7 +13,7 @@ import (
. "github.com/iotaledger/iota.go/trinary"
)
var PLUGIN = node.NewPlugin("Validator", configure, run)
var PLUGIN = node.NewPlugin("Validator", node.Enabled, configure, run)
// Creates bundle signature fragments and the corresponding address to validate against.
// Each signature fragment after the first must go into its own meta transaction with value = 0.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment