Bug fixes and improvements
+ Add a function to the Tools package to provide the local IP address and port + Add a function to the Tools package to provide a time as formated string as yyyyMMdd hhmmss.fff + Improved the ICCC startup message: Now, the message contains the IP address and port of the stared server + Add a new configuration to specific the necessary Ocean servers' port (internally, not the public port) + The template package reports now which version out of the grid FS is used. + The Ocean server is now bound to the correct IP address and port (rule: the local IP address!) + The order of the system shutdown handlers were wrong! + The early ICCC messages problem is now fixed! + Fixed an ICCC bug for the case, that a message does not have any payload! + Also the configuration database uses now the correct mgo MongoDB rules (SetSafe & SetMode)
This commit is contained in:
parent
7120a729bd
commit
a007db1b79
@ -30,6 +30,7 @@ func checkConfiguration() {
|
||||
CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenGetHandler`, `http://localhost:80/next/number`)
|
||||
CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenBufferSize`, `12`)
|
||||
CheckSingleConfigurationPresentsAndAddIfMissing(`OceanHostnameAndPort`, `:60000`)
|
||||
CheckSingleConfigurationPresentsAndAddIfMissing(`OceanServerPort`, `60000`)
|
||||
CheckSingleConfigurationPresentsAndAddIfMissing(`OceanUtilizeCPUs`, `2`)
|
||||
CheckSingleConfigurationPresentsAndAddIfMissing(`FilenameWebResources`, `web.zip`)
|
||||
CheckSingleConfigurationPresentsAndAddIfMissing(`MapStaticFiles2Root`, `false`)
|
||||
|
@ -26,6 +26,12 @@ func init() {
|
||||
return
|
||||
}
|
||||
|
||||
// In case of write operations, wait for the majority of servers to be done:
|
||||
session.SetSafe(&mgo.Safe{WMode: "majority"})
|
||||
|
||||
// Set the consistency mode to read from any secondary server and write to the primary.
|
||||
session.SetMode(mgo.Eventual, true)
|
||||
|
||||
// Get the collection:
|
||||
collection = db.C(config.ConfigDBConfigurationCollection)
|
||||
|
||||
|
@ -14,6 +14,13 @@ func ICCCHandler(response http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
messageData := map[string][]string(request.PostForm)
|
||||
|
||||
if len(messageData) < 3 {
|
||||
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameNETWORK, `The ICCC message contains not enough data: At least the channel, command and password is required!`)
|
||||
http.NotFound(response, request)
|
||||
return
|
||||
}
|
||||
|
||||
channel := messageData[`channel`][0]
|
||||
command := messageData[`command`][0]
|
||||
password := messageData[`InternalCommPassword`][0]
|
||||
|
10
ICCC/Init.go
10
ICCC/Init.go
@ -1,9 +1,7 @@
|
||||
package ICCC
|
||||
|
||||
import "strings"
|
||||
import "container/list"
|
||||
import "github.com/SommerEngineering/Ocean/Tools"
|
||||
import "github.com/SommerEngineering/Ocean/ConfigurationDB"
|
||||
import "github.com/SommerEngineering/Ocean/Log"
|
||||
import LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
|
||||
@ -14,13 +12,9 @@ func init() {
|
||||
cacheListenerDatabase = list.New()
|
||||
listeners = make(map[string]func(data map[string][]string))
|
||||
|
||||
allHostsIPAddresses := Tools.ReadAllIPAddresses4ThisHost()
|
||||
oceanHostnameAndPort := ConfigurationDB.Read(`OceanHostnameAndPort`)
|
||||
port := oceanHostnameAndPort[strings.Index(oceanHostnameAndPort, `:`):]
|
||||
correctAddressWithPort = allHostsIPAddresses[0] + port
|
||||
// Using the local IP address and NOT the configuration "OceanHostnameAndPort":
|
||||
correctAddressWithPort = Tools.LocalIPAddressAndPort()
|
||||
|
||||
initDB()
|
||||
registerHost2Database()
|
||||
cacheTimerLogic(false)
|
||||
initCacheTimer()
|
||||
}
|
||||
|
@ -8,7 +8,31 @@ import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
|
||||
import "github.com/SommerEngineering/Ocean/Log"
|
||||
import LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
|
||||
func InitCacheNow() {
|
||||
startCacheTimerLock.Lock()
|
||||
defer startCacheTimerLock.Unlock()
|
||||
|
||||
if cacheTimerRunning {
|
||||
return
|
||||
}
|
||||
|
||||
cacheTimerLogic(false)
|
||||
}
|
||||
|
||||
func StartCacheTimer() {
|
||||
initCacheTimer()
|
||||
}
|
||||
|
||||
func initCacheTimer() {
|
||||
startCacheTimerLock.Lock()
|
||||
defer startCacheTimerLock.Unlock()
|
||||
|
||||
if cacheTimerRunning {
|
||||
return
|
||||
} else {
|
||||
cacheTimerRunning = true
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
cacheTimerLogic(true)
|
||||
|
@ -5,18 +5,17 @@ import "reflect"
|
||||
import "strconv"
|
||||
|
||||
func message2Data(channel, command string, message interface{}) (data map[string][]string) {
|
||||
data = make(map[string][]string)
|
||||
data[`command`] = []string{command}
|
||||
data[`channel`] = []string{channel}
|
||||
|
||||
if message == nil {
|
||||
data = make(map[string][]string)
|
||||
return
|
||||
}
|
||||
|
||||
element := reflect.ValueOf(message)
|
||||
elementType := element.Type()
|
||||
|
||||
data = make(map[string][]string)
|
||||
data[`command`] = []string{command}
|
||||
data[`channel`] = []string{channel}
|
||||
|
||||
for i := 0; i < element.NumField(); i++ {
|
||||
field := element.Field(i)
|
||||
keyName := elementType.Field(i).Name
|
||||
|
@ -24,5 +24,7 @@ var (
|
||||
listenersLock sync.RWMutex = sync.RWMutex{}
|
||||
cacheListenerDatabase *list.List = nil
|
||||
cacheListenerDatabaseLock sync.RWMutex = sync.RWMutex{}
|
||||
startCacheTimerLock sync.Mutex = sync.Mutex{}
|
||||
cacheTimerRunning bool = false
|
||||
correctAddressWithPort string = ``
|
||||
)
|
||||
|
@ -1,8 +1,11 @@
|
||||
package System
|
||||
|
||||
import "github.com/SommerEngineering/Ocean/ICCC"
|
||||
import "github.com/SommerEngineering/Ocean/Log"
|
||||
import LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
|
||||
func icccSystemStart(data map[string][]string) {
|
||||
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The system is now up and ready.`)
|
||||
_, _, obj := ICCC.Data2Message(&ICCCStartUpMessage{}, data)
|
||||
messageData := obj.(*ICCCStartUpMessage)
|
||||
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `ICCC message: The server is now up and ready.`, messageData.IPAddressAndPort)
|
||||
}
|
||||
|
5
System/ICCCStartUp.go
Normal file
5
System/ICCCStartUp.go
Normal file
@ -0,0 +1,5 @@
|
||||
package System
|
||||
|
||||
type ICCCStartUpMessage struct {
|
||||
IPAddressAndPort string
|
||||
}
|
@ -84,13 +84,17 @@ func initSystem() {
|
||||
// * then, these system handlers are called (order: last comed, first served)
|
||||
// * and finally, the logging device / system gets closed
|
||||
Shutdown.InitShutdown()
|
||||
Shutdown.AddShutdownHandler(ICCC.ShutdownFunction{})
|
||||
Shutdown.AddShutdownHandler(NumGen.ShutdownFunction{})
|
||||
Shutdown.AddShutdownHandler(ConfigurationDB.ShutdownFunction{})
|
||||
Shutdown.AddShutdownHandler(CustomerDB.ShutdownFunction{})
|
||||
Shutdown.AddShutdownHandler(ICCC.ShutdownFunction{})
|
||||
Shutdown.AddShutdownHandler(NumGen.ShutdownFunction{})
|
||||
|
||||
// The logging subsystem is not registered here, because it will be automated called at the end
|
||||
|
||||
// Register all system ICCC commands:
|
||||
ICCC.Registrar(ICCC.ChannelSYSTEM, `System::Start`, icccSystemStart)
|
||||
|
||||
// Start the ICCC Listener Cache:
|
||||
ICCC.InitCacheNow() // Blocking, until the job is done
|
||||
ICCC.StartCacheTimer()
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
package System
|
||||
|
||||
import "net/http"
|
||||
import "github.com/SommerEngineering/Ocean/ConfigurationDB"
|
||||
import "github.com/SommerEngineering/Ocean/Tools"
|
||||
import "github.com/SommerEngineering/Ocean/ICCC"
|
||||
import "github.com/SommerEngineering/Ocean/Log"
|
||||
import LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
|
||||
func StartAndBlockForever() {
|
||||
oceanHostnameAndPort := ConfigurationDB.Read(`OceanHostnameAndPort`)
|
||||
ipAddressPort := Tools.LocalIPAddressAndPort()
|
||||
|
||||
// Init ICCC:
|
||||
ICCC.WriteMessage2All(ICCC.ChannelSYSTEM, `System::Start`, nil)
|
||||
// Tell the whole cluster, that we are up and ready:
|
||||
data := ICCCStartUpMessage{}
|
||||
data.IPAddressAndPort = ipAddressPort
|
||||
ICCC.WriteMessage2All(ICCC.ChannelSYSTEM, `System::Start`, data)
|
||||
|
||||
// Start and block:
|
||||
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Web server is now listening.`, `Configuration for hostname and port.`, oceanHostnameAndPort)
|
||||
http.ListenAndServe(oceanHostnameAndPort, nil)
|
||||
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Web server is now listening.`, `Configuration for hostname and port.`, ipAddressPort)
|
||||
http.ListenAndServe(ipAddressPort, nil)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import "html/template"
|
||||
import "io/ioutil"
|
||||
import "archive/zip"
|
||||
import "github.com/SommerEngineering/Ocean/CustomerDB"
|
||||
import "github.com/SommerEngineering/Ocean/Tools"
|
||||
import "github.com/SommerEngineering/Ocean/Log"
|
||||
import LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
|
||||
@ -21,6 +22,7 @@ func init() {
|
||||
return
|
||||
} else {
|
||||
defer gridFile.Close()
|
||||
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Read the templates.zip file from the grid file system.`, `Upload time UTC: `+Tools.FormatTime(gridFile.UploadDate().UTC()))
|
||||
if data, ioError := ioutil.ReadAll(gridFile); ioError != nil {
|
||||
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to read the templates.`, ioError.Error())
|
||||
return
|
||||
|
58
Tools/FormatTime.go
Normal file
58
Tools/FormatTime.go
Normal file
@ -0,0 +1,58 @@
|
||||
package Tools
|
||||
|
||||
import "time"
|
||||
import "fmt"
|
||||
import "strconv"
|
||||
|
||||
func FormatTime(t1 time.Time) (result string) {
|
||||
var year int = t1.Year()
|
||||
var month int = int(t1.Month())
|
||||
var day int = int(t1.Day())
|
||||
var minutes int = int(t1.Minute())
|
||||
var hours int = int(t1.Hour())
|
||||
var seconds int = int(t1.Second())
|
||||
var milliseconds int = int(float64(t1.Nanosecond()) / 1000000.0)
|
||||
|
||||
var monthText, dayText, minutesText, hoursText, secondsText, millisecondsText string
|
||||
|
||||
if month >= 1 && month <= 9 {
|
||||
monthText = fmt.Sprintf(`0%d`, month)
|
||||
} else {
|
||||
monthText = strconv.Itoa(month)
|
||||
}
|
||||
|
||||
if day >= 1 && day <= 9 {
|
||||
dayText = fmt.Sprintf(`0%d`, day)
|
||||
} else {
|
||||
dayText = strconv.Itoa(day)
|
||||
}
|
||||
|
||||
if minutes >= 0 && minutes <= 9 {
|
||||
minutesText = fmt.Sprintf(`0%d`, minutes)
|
||||
} else {
|
||||
minutesText = strconv.Itoa(minutes)
|
||||
}
|
||||
|
||||
if hours >= 0 && hours <= 9 {
|
||||
hoursText = fmt.Sprintf(`0%d`, hours)
|
||||
} else {
|
||||
hoursText = strconv.Itoa(hours)
|
||||
}
|
||||
|
||||
if seconds >= 0 && seconds <= 9 {
|
||||
secondsText = fmt.Sprintf(`0%d`, seconds)
|
||||
} else {
|
||||
secondsText = strconv.Itoa(seconds)
|
||||
}
|
||||
|
||||
if milliseconds >= 0 && milliseconds <= 9 {
|
||||
millisecondsText = fmt.Sprintf(`00%d`, milliseconds)
|
||||
} else if milliseconds >= 10 && milliseconds <= 99 {
|
||||
millisecondsText = fmt.Sprintf(`0%d`, milliseconds)
|
||||
} else {
|
||||
millisecondsText = strconv.Itoa(milliseconds)
|
||||
}
|
||||
|
||||
result = fmt.Sprintf(`%d%s%s %s%s%s.%s`, year, monthText, dayText, hoursText, minutesText, secondsText, millisecondsText)
|
||||
return
|
||||
}
|
@ -24,4 +24,9 @@ func init() {
|
||||
|
||||
// Set the seed for random:
|
||||
rand.Seed(time.Now().Unix())
|
||||
|
||||
// Build the local IP address and port:
|
||||
allHostsIPAddresses := ReadAllIPAddresses4ThisHost()
|
||||
port := ConfigurationDB.Read(`OceanServerPort`)
|
||||
localIPAddressAndPort = allHostsIPAddresses[0] + `:` + port
|
||||
}
|
||||
|
6
Tools/LocalIPAddressAndPort.go
Normal file
6
Tools/LocalIPAddressAndPort.go
Normal file
@ -0,0 +1,6 @@
|
||||
package Tools
|
||||
|
||||
func LocalIPAddressAndPort() (address string) {
|
||||
address = localIPAddressAndPort
|
||||
return
|
||||
}
|
@ -3,8 +3,9 @@ package Tools
|
||||
import LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
|
||||
var (
|
||||
senderName LM.Sender = `System::Tools`
|
||||
hostname string = `unknown`
|
||||
ipAddresses []string = nil
|
||||
internalCommPassword string = ``
|
||||
senderName LM.Sender = `System::Tools`
|
||||
hostname string = `unknown`
|
||||
localIPAddressAndPort string = `127.0.0.1:60000`
|
||||
ipAddresses []string = nil
|
||||
internalCommPassword string = ``
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user