From 3348e552cc7e7a8031d044e6630070d6e1a4dbdf Mon Sep 17 00:00:00 2001 From: Thorsten Date: Fri, 7 Nov 2014 13:00:55 +0100 Subject: [PATCH] Misc. + Removed the fixed shutdown time + Added the configuration for the public web server + Refactored the old web server settings + Improved the handling of shutdown handlers. It is not save! + Bugfix: The server start was no longer blocking --- ConfigurationDB/CheckConfiguration.go | 6 +++-- ICCC/Init.go | 2 +- Log/Flush.go | 9 ++----- Log/Init.go | 1 + Log/Scheduler.go | 1 + Log/Variables.go | 1 + Shutdown/Shutdown.go | 20 ++++++++++++--- System/Start.go | 4 +++ Tools/Init.go | 2 +- WebServer/Init.go | 37 +++++++++++++++++++++++---- 10 files changed, 63 insertions(+), 20 deletions(-) diff --git a/ConfigurationDB/CheckConfiguration.go b/ConfigurationDB/CheckConfiguration.go index 755d0e5..a102c4f 100644 --- a/ConfigurationDB/CheckConfiguration.go +++ b/ConfigurationDB/CheckConfiguration.go @@ -15,6 +15,10 @@ func checkConfiguration() { CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerReadTimeoutSeconds`, `10`) CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerWriteTimeoutSeconds`, `10`) CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerMaxHeaderLenBytes`, `1048576`) + CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerPort`, `60000`) + CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerReadTimeoutSeconds`, `10`) + CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerWriteTimeoutSeconds`, `10`) + CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerMaxHeaderLenBytes`, `1048576`) CheckSingleConfigurationPresentsAndAddIfMissing(`InternalCommPassword`, `please replace this with e.g. a random GUID, etc.`) CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBHost`, `localhost:27017`) CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBDatabase`, `Ocean`) @@ -36,8 +40,6 @@ func checkConfiguration() { CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenActiveHosts`, `please replace this with the correct hostname of the host which is the master number generator`) 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`) diff --git a/ICCC/Init.go b/ICCC/Init.go index 13fcc80..f911866 100644 --- a/ICCC/Init.go +++ b/ICCC/Init.go @@ -14,7 +14,7 @@ func init() { cacheListenerDatabase = list.New() listeners = make(map[string]func(data map[string][]string)) - // Using the local IP address and NOT the configuration "OceanHostnameAndPort": + // Using the local IP address: correctAddressWithPort = Tools.LocalIPAddressAndPort() initDB() diff --git a/Log/Flush.go b/Log/Flush.go index b75dfa9..f4f1aaa 100644 --- a/Log/Flush.go +++ b/Log/Flush.go @@ -2,7 +2,6 @@ package Log import ( "github.com/SommerEngineering/Ocean/Log/Device" - "time" ) /* @@ -14,8 +13,7 @@ func Flush() { close(entriesBuffer) mutexChannel.Unlock() - // This is a bad design, but the scheduler need some time to write the last messages. - time.Sleep(15 * time.Second) + <-schedulerExitSignal mutexDeviceDelays.Lock() dataArray := logEntryListToArray(deviceDelayBuffer) @@ -26,10 +24,7 @@ func Flush() { for entry := devices.Front(); entry != nil; entry = entry.Next() { dev := entry.Value.(Device.Device) dev.Log(dataArray) // Want to wait to complete, therefore no new thread here - go dev.Flush() + dev.Flush() } mutexDevices.RUnlock() - - // This is a bad design, but the devices need (may) some time to write the last messages: - time.Sleep(15 * time.Second) } diff --git a/Log/Init.go b/Log/Init.go index 0b2b59b..34a9287 100644 --- a/Log/Init.go +++ b/Log/Init.go @@ -41,6 +41,7 @@ func init() { preChannelBuffer = list.New() deviceDelayBuffer = list.New() devices = list.New() + schedulerExitSignal = make(chan bool) initTimer() initCode() diff --git a/Log/Scheduler.go b/Log/Scheduler.go index 1f91546..fcf2efb 100644 --- a/Log/Scheduler.go +++ b/Log/Scheduler.go @@ -37,4 +37,5 @@ func scheduler(logBuffer chan Meta.Entry) { } LogFull(senderName, Meta.CategorySYSTEM, Meta.LevelWARN, Meta.SeverityCritical, Meta.ImpactNone, Meta.MessageNameSHUTDOWN, `The scheduler is down now.`) + schedulerExitSignal <- true } diff --git a/Log/Variables.go b/Log/Variables.go index 1fc5d3e..018697f 100644 --- a/Log/Variables.go +++ b/Log/Variables.go @@ -8,6 +8,7 @@ import ( var ( entriesBuffer chan Meta.Entry = nil + schedulerExitSignal chan bool = nil logBufferSize int = 500 logBufferTimeoutSeconds int = 4 logDeviceDelayNumberEvents int = 600 diff --git a/Shutdown/Shutdown.go b/Shutdown/Shutdown.go index c8f30bb..7f321a2 100644 --- a/Shutdown/Shutdown.go +++ b/Shutdown/Shutdown.go @@ -1,6 +1,8 @@ package Shutdown import ( + "container/list" + "fmt" "github.com/SommerEngineering/Ocean/Log" LM "github.com/SommerEngineering/Ocean/Log/Meta" "os" @@ -20,12 +22,22 @@ func executeShutdown() { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSHUTDOWN, `The system was called to shutting down.`, sig.String(), `Call now all shutdown handlers.`) for handler := shutdownHandlers.Front(); handler != nil; handler = handler.Next() { - h := handler.Value.(ShutdownHandler) - h.Shutdown() + safeCall(handler) } Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSHUTDOWN, `The system is shutting down now.`) Log.Flush() - - os.Exit(6) + os.Exit(0) +} + +func safeCall(handler *list.Element) { + defer func() { + if err := recover(); err != nil { + errObj := fmt.Errorf("%v", err) + Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.SeverityNone, LM.ImpactNone, LM.MessageNameSHUTDOWN, `An error occurs for a shutdown handler.`, errObj.Error()) + } + }() + + h := handler.Value.(ShutdownHandler) + h.Shutdown() } diff --git a/System/Start.go b/System/Start.go index 0840b66..83737b8 100644 --- a/System/Start.go +++ b/System/Start.go @@ -2,8 +2,12 @@ package System import ( "github.com/SommerEngineering/Ocean/WebServer" + "time" ) func StartAndBlockForever() { WebServer.Start() + for { + time.Sleep(1 * time.Second) + } } diff --git a/Tools/Init.go b/Tools/Init.go index a0059b2..40cde30 100644 --- a/Tools/Init.go +++ b/Tools/Init.go @@ -29,6 +29,6 @@ func init() { // Build the local IP address and port: allHostsIPAddresses := ReadAllIPAddresses4ThisHost() - port := ConfigurationDB.Read(`OceanServerPort`) + port := ConfigurationDB.Read(`PublicWebServerPort`) localIPAddressAndPort = allHostsIPAddresses[0] + `:` + port } diff --git a/WebServer/Init.go b/WebServer/Init.go index 5a38993..cf7fd41 100644 --- a/WebServer/Init.go +++ b/WebServer/Init.go @@ -26,9 +26,32 @@ func init() { serverPublic.Handler = Handlers.GetPublicMux() serverPublic.SetKeepAlivesEnabled(true) - serverPublic.ReadTimeout = 10 * time.Second - serverPublic.WriteTimeout = 10 * time.Second - serverPublic.MaxHeaderBytes = 1024 + // Public Web Server: Read Timeout + if readTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`PublicWebServerReadTimeoutSeconds`)); errTimeout != nil { + Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the public server's read timeout value. Use the default of 10 seconds instead.`, errTimeout.Error()) + serverPublic.ReadTimeout = 10 * time.Second + } else { + Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The public web server's read timeout was set to %d seconds.", readTimeoutSeconds)) + serverPublic.ReadTimeout = time.Duration(readTimeoutSeconds) * time.Second + } + + // Public Web Server: Write Timeout + if writeTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`PublicWebServerWriteTimeoutSeconds`)); errTimeout != nil { + Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the public server's write timeout value. Use the default of 10 seconds instead.`, errTimeout.Error()) + serverPublic.WriteTimeout = 10 * time.Second + } else { + Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The public web server's write timeout was set to %d seconds.", writeTimeoutSeconds)) + serverPublic.WriteTimeout = time.Duration(writeTimeoutSeconds) * time.Second + } + + // Public Web Server: Max. Header Size + if maxHeaderBytes, errHeaderBytes := strconv.Atoi(ConfigurationDB.Read(`PublicWebServerMaxHeaderLenBytes`)); errHeaderBytes != nil { + Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the public server's max. header size. Use the default of 1048576 bytes instead.`, errHeaderBytes.Error()) + serverPublic.MaxHeaderBytes = 1048576 + } else { + Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The public web server's max. header size was set to %d bytes.", maxHeaderBytes)) + serverPublic.MaxHeaderBytes = maxHeaderBytes + } if strings.ToLower(ConfigurationDB.Read(`AdminWebServerEnabled`)) == `true` { serverAdmin = &http.Server{} @@ -36,6 +59,7 @@ func init() { serverAdmin.Handler = Handlers.GetAdminMux() serverAdmin.SetKeepAlivesEnabled(true) + // Admin Web Server: Read Timeout if readTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerReadTimeoutSeconds`)); errTimeout != nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's read timeout value. Use the default of 10 seconds instead.`, errTimeout.Error()) serverAdmin.ReadTimeout = 10 * time.Second @@ -44,6 +68,7 @@ func init() { serverAdmin.ReadTimeout = time.Duration(readTimeoutSeconds) * time.Second } + // Admin Web Server: Write Timeout if writeTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerWriteTimeoutSeconds`)); errTimeout != nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's write timeout value. Use the default of 10 seconds instead.`, errTimeout.Error()) serverAdmin.WriteTimeout = 10 * time.Second @@ -52,14 +77,16 @@ func init() { serverAdmin.WriteTimeout = time.Duration(writeTimeoutSeconds) * time.Second } + // Admin Web Server: Max. Header Size if maxHeaderBytes, errHeaderBytes := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerMaxHeaderLenBytes`)); errHeaderBytes != nil { - Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's maximum count of bytes for the headers. Use the default of 1048576 bytes instead.`, errHeaderBytes.Error()) + Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's max. header size. Use the default of 1048576 bytes instead.`, errHeaderBytes.Error()) serverAdmin.MaxHeaderBytes = 1048576 } else { - Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The admin web server's count of maximal bytes for the headers was set to %d bytes.", maxHeaderBytes)) + Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The admin web server's max. header size was set to %d bytes.", maxHeaderBytes)) serverAdmin.MaxHeaderBytes = maxHeaderBytes } } else { + // Admin Web Server is disabled Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The admin web server is disabled.`) } }