Added more ICCC commands

+ Added ICCC command for register a host
+ Added ICCC command for register a command i.e. listener
+ Added ICCC command for getting a number from NumGen
This commit is contained in:
Thorsten Sommer 2015-06-21 21:28:39 +02:00
parent 326eb9ba7a
commit 6e111b7517
15 changed files with 244 additions and 65 deletions

View File

@ -0,0 +1,45 @@
package ICCC
import (
"fmt"
"github.com/SommerEngineering/Ocean/ICCC/SystemMessages"
"github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta"
)
// The receiver function for the ICCC message, that registers a command.
func ICCCRegisterCommand(data map[string][]string) (result map[string][]string) {
// Recover from errors:
defer func() {
if err := recover(); err != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNamePARSE, fmt.Sprintf("Was not able to execute the ICCC register command message. %s", err))
result = make(map[string][]string, 0)
return
}
}()
// Converts the HTTP form data into an object:
_, _, obj := Data2Message(SystemMessages.ICCCRegisterListener{}, data)
// Was it possible to convert the data?
if obj != nil {
// Cast the object to the right type:
messageData := obj.(SystemMessages.ICCCRegisterListener)
// Provide a log entry:
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `ICCC message: Should register another command.`, `channel=`+messageData.Channel, `command=`+messageData.Command, `IPAddressPort=`+messageData.IPAddressPort, fmt.Sprintf(`isActive=%v`, messageData.IsActive))
// Execute the command:
registerCommand2Database(messageData.Channel, messageData.Command, messageData.IPAddressPort, messageData.IsActive)
// An answer is necessary:
return Message2Data(``, ``, SystemMessages.AnswerACK)
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `ICCC message: Was not able to create the message.`)
}
// In any other error case:
result = make(map[string][]string, 0)
return
}

45
ICCC/ICCCRegisterHost.go Normal file
View File

@ -0,0 +1,45 @@
package ICCC
import (
"fmt"
"github.com/SommerEngineering/Ocean/ICCC/SystemMessages"
"github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta"
)
// The receiver function for the ICCC message, that registers a host.
func ICCCRegisterHost(data map[string][]string) (result map[string][]string) {
// Recover from errors:
defer func() {
if err := recover(); err != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNamePARSE, fmt.Sprintf("Was not able to execute the ICCC register host message. %s", err))
result = make(map[string][]string, 0)
return
}
}()
// Converts the HTTP form data into an object:
_, _, obj := Data2Message(SystemMessages.ICCCRegisterHost{}, data)
// Was it possible to convert the data?
if obj != nil {
// Cast the object to the right type:
messageData := obj.(SystemMessages.ICCCRegisterHost)
// Provide a log entry:
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `ICCC message: Should register another host.`, messageData.Hostname, messageData.IPAddressPort)
// Execute the command:
registerHost2Database(messageData.Hostname, messageData.IPAddressPort)
// An answer is necessary:
return Message2Data(``, ``, SystemMessages.AnswerACK)
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `ICCC message: Was not able to create the message.`)
}
// In any other error case:
result = make(map[string][]string, 0)
return
}

View File

@ -25,5 +25,5 @@ func init() {
initDB() initDB()
// Register this server to the listener (if not present): // Register this server to the listener (if not present):
registerHost2Database() registerThisHost2Database()
} }

View File

@ -1,56 +0,0 @@
package ICCC
import (
"github.com/SommerEngineering/Ocean/ICCC/Scheme"
"github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta"
"gopkg.in/mgo.v2/bson"
)
// The internal function to register a command to ICCC.
func register2Database(channel, command string) {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Register this ICCC command in to the database.`, `channel=`+channel, `command=`+command)
//
// Case: Exist and active :)
//
emptyEntry := Scheme.Listener{}
selection := bson.D{{`Channel`, channel}, {`Command`, command}, {`IPAddressPort`, correctAddressWithPort}, {`IsActive`, true}}
count1, _ := collectionListener.Find(selection).Count()
if count1 == 1 {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.SeverityHigh, LM.ImpactHigh, LM.MessageNameSTARTUP, `This ICCC command is already known and active.`, `Please shutdown the system next time!`)
return
}
//
// Case: Exist but not active
//
selection = bson.D{{`Channel`, channel}, {`Command`, command}, {`IPAddressPort`, correctAddressWithPort}, {`IsActive`, false}}
notActiveEntry := Scheme.Listener{}
collectionListener.Find(selection).One(&notActiveEntry)
if notActiveEntry != emptyEntry {
notActiveEntry.IsActive = true
collectionListener.Update(selection, notActiveEntry)
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.SeverityNone, LM.ImpactNone, LM.MessageNameSTARTUP, `This ICCC command is already known but it was not active.`, `The command is active now!`)
return
}
//
// Case: Not exist
//
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactNone, LM.MessageNameCONFIGURATION, `This ICCC command is not known.`, `Create now a new entry!`)
entry := Scheme.Listener{}
entry.Channel = channel
entry.Command = command
entry.IsActive = true
entry.IPAddressPort = correctAddressWithPort
if err := collectionListener.Insert(entry); err != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `It was not possible to add this ICCC command!`, err.Error(), `channel=`+channel, `command=`+command)
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `This ICCC command is now known and active.`)
}
}

View File

@ -0,0 +1,44 @@
package ICCC
import (
"fmt"
"github.com/SommerEngineering/Ocean/ICCC/Scheme"
"github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta"
"gopkg.in/mgo.v2/bson"
)
// The internal function to register a command to ICCC.
func registerCommand2Database(channel, command, ipAddressPort string, isActive bool) {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Register this ICCC command in to the database.`, `channel=`+channel, `command=`+command, `IPAddressPort=`+ipAddressPort, fmt.Sprintf("isActive=%v", isActive))
entry := Scheme.Listener{}
entry.Channel = channel
entry.Command = command
entry.IsActive = isActive
entry.IPAddressPort = ipAddressPort
//
// Case: Exists?
//
selection := bson.D{{`Channel`, channel}, {`Command`, command}, {`IPAddressPort`, ipAddressPort}}
count1, _ := collectionListener.Find(selection).Count()
if count1 == 1 {
//
// Case: Exist but maybe not active
//
collectionListener.Update(selection, entry)
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Updating the existing ICCC command.`, `channel=`+channel, `command=`+command, `IPAddressPort=`+ipAddressPort)
return
}
//
// Case: Not exist
//
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactNone, LM.MessageNameCONFIGURATION, `This ICCC command is not known.`, `Create now a new entry!`, `channel=`+channel, `command=`+command, `IPAddressPort=`+ipAddressPort)
if err := collectionListener.Insert(entry); err != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `It was not possible to add this ICCC command!`, err.Error(), `channel=`+channel, `command=`+command, `IPAddressPort=`+ipAddressPort)
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `This ICCC command is now known and active.`, `channel=`+channel, `command=`+command, `IPAddressPort=`+ipAddressPort)
}
}

View File

@ -4,17 +4,16 @@ import (
"github.com/SommerEngineering/Ocean/ICCC/Scheme" "github.com/SommerEngineering/Ocean/ICCC/Scheme"
"github.com/SommerEngineering/Ocean/Log" "github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta" LM "github.com/SommerEngineering/Ocean/Log/Meta"
"github.com/SommerEngineering/Ocean/Tools"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
) )
// Function to register this server to the ICCC. // Function to register a server to the ICCC.
func registerHost2Database() { func registerHost2Database(hostname, ipAddressPort string) {
// Create the host entry: // Create the host entry:
host := Scheme.Host{} host := Scheme.Host{}
host.Hostname = Tools.ThisHostname() host.Hostname = hostname
host.IPAddressPort = correctAddressWithPort host.IPAddressPort = ipAddressPort
// The query to find already existing entries: // The query to find already existing entries:
selection := bson.D{{`Hostname`, host.Hostname}, {`IPAddressPort`, host.IPAddressPort}} selection := bson.D{{`Hostname`, host.Hostname}, {`IPAddressPort`, host.IPAddressPort}}

View File

@ -0,0 +1,12 @@
package ICCC
// The internal function to register a local command to ICCC.
func registerLocalCommand2Database(channel, command string) {
/*
Cannot use here the ICCC command to register this command.
Because, this host is maybe the first one. In that case,
there would be no server which can execute the ICCC command.
Therefore, every Ocean server registers the own commans directly.
*/
registerCommand2Database(channel, command, correctAddressWithPort, true)
}

View File

@ -0,0 +1,16 @@
package ICCC
import (
"github.com/SommerEngineering/Ocean/Tools"
)
// Function to register this server to the ICCC.
func registerThisHost2Database() {
/*
Cannot use here the ICCC command to register this host.
Because, this host is maybe the first one. In that case,
there would be no server which can execute the ICCC command.
Therefore, every Ocean server registers the own host directly.
*/
registerHost2Database(Tools.ThisHostname(), correctAddressWithPort)
}

View File

@ -12,7 +12,7 @@ func Registrar(channel, command string, callback func(data map[string][]string)
defer listenersLock.Unlock() defer listenersLock.Unlock()
// Write the command to the database: // Write the command to the database:
register2Database(channel, command) registerLocalCommand2Database(channel, command)
// Register the command at the local cache: // Register the command at the local cache:
listeners[fmt.Sprintf(`%s::%s`, channel, command)] = callback listeners[fmt.Sprintf(`%s::%s`, channel, command)] = callback

View File

@ -0,0 +1,10 @@
package SystemMessages
// The message to request a new number from NumGen package.
type ICCCNumGenNext struct {
}
// The response to the Numgen request.
type ICCCAnswerNumGen struct {
Number int64
}

View File

@ -0,0 +1,7 @@
package SystemMessages
// The message to register a host to ICCC.
type ICCCRegisterHost struct {
Hostname string // The hostname for the end-point
IPAddressPort string // The IP address and port for the end-point
}

View File

@ -0,0 +1,9 @@
package SystemMessages
// The message to register a command/listener to ICCC.
type ICCCRegisterListener struct {
Channel string // The channel for the provided command
Command string // The provided command
IsActive bool // Is the command active?
IPAddressPort string // The IP address and port for the end-point
}

View File

@ -2,6 +2,6 @@ package SystemMessages
// Message type for the startup message: // Message type for the startup message:
type ICCCStartUpMessage struct { type ICCCStartUpMessage struct {
PublicIPAddressAndPort string PublicIPAddressAndPort string // The public web server's IP address and port
AdminIPAddressAndPort string AdminIPAddressAndPort string // The private admin server's IP address and port
} }

45
NumGen/ICCCNextNumber.go Normal file
View File

@ -0,0 +1,45 @@
package NumGen
import (
"fmt"
"github.com/SommerEngineering/Ocean/ICCC"
"github.com/SommerEngineering/Ocean/ICCC/SystemMessages"
"github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta"
)
// The receiver function for the ICCC message, that registers a command.
func ICCCNextNumber(data map[string][]string) (result map[string][]string) {
// Recover from errors:
defer func() {
if err := recover(); err != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNamePARSE, fmt.Sprintf("Was not able to execute the ICCC next number command message. %s", err))
result = make(map[string][]string, 0)
return
}
}()
// Converts the HTTP form data into an object:
_, _, obj := ICCC.Data2Message(SystemMessages.ICCCNumGenNext{}, data)
// Was it possible to convert the data?
if obj != nil {
// Cast the object to the right type (just as check):
_ = obj.(SystemMessages.ICCCNumGenNext)
// Execute the command:
nextNumber := GetUniqueID()
// An answer is necessary:
answer := SystemMessages.ICCCAnswerNumGen{}
answer.Number = nextNumber
return ICCC.Message2Data(``, ``, answer)
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `ICCC message: Was not able to create the message.`)
}
// In any other error case:
result = make(map[string][]string, 0)
return
}

View File

@ -98,6 +98,9 @@ func initSystem() {
// Register all system ICCC commands: // Register all system ICCC commands:
ICCC.Registrar(ICCC.ChannelSYSTEM, `System::Start`, icccSystemStart) ICCC.Registrar(ICCC.ChannelSYSTEM, `System::Start`, icccSystemStart)
ICCC.Registrar(ICCC.ChannelICCC, `ICCC::RegisterHost`, ICCC.ICCCRegisterHost)
ICCC.Registrar(ICCC.ChannelICCC, `ICCC::RegisterCommand`, ICCC.ICCCRegisterCommand)
ICCC.Registrar(ICCC.ChannelNUMGEN, `NumGen::Next`, NumGen.ICCCNextNumber)
// Start the ICCC Listener Cache: // Start the ICCC Listener Cache:
ICCC.InitCacheNow() // Blocking, until the job is done ICCC.InitCacheNow() // Blocking, until the job is done