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:
Thorsten Sommer 2014-06-08 11:35:01 +02:00
parent 7120a729bd
commit a007db1b79
16 changed files with 145 additions and 26 deletions

View File

@ -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`)

View File

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

View File

@ -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]

View File

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

View File

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

View File

@ -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

View File

@ -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 = ``
)

View File

@ -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
View File

@ -0,0 +1,5 @@
package System
type ICCCStartUpMessage struct {
IPAddressAndPort string
}

View File

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

View File

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

View File

@ -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
View 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
}

View File

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

View File

@ -0,0 +1,6 @@
package Tools
func LocalIPAddressAndPort() (address string) {
address = localIPAddressAndPort
return
}

View File

@ -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 = ``
)