diff --git a/CustomerDB/AccessDB.go b/CustomerDB/AccessDB.go index 5db44aa..fb4e825 100644 --- a/CustomerDB/AccessDB.go +++ b/CustomerDB/AccessDB.go @@ -5,15 +5,22 @@ import "labix.org/v2/mgo" /* Get the database instance of the MGo Mongo driver. */ -func DB() (result *mgo.Database) { - result = db +func DB() (session *mgo.Session, database *mgo.Database) { + session = mainSession.Copy() + database = session.DB(databaseDB) + database.Login(databaseUsername, databasePassword) + return } /* Get directly the GridFS instance of the Mgo Mongo driver. */ -func GridFS() (result *mgo.GridFS) { - result = gridFS +func GridFS() (session *mgo.Session, filesystem *mgo.GridFS) { + session = mainSession.Copy() + database := session.DB(databaseDB) + database.Login(databaseUsername, databasePassword) + filesystem = database.GridFS(`fs`) + return } diff --git a/CustomerDB/Init.go b/CustomerDB/Init.go index e3df9df..9748dcc 100644 --- a/CustomerDB/Init.go +++ b/CustomerDB/Init.go @@ -10,20 +10,20 @@ func init() { Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameDATABASE, `Init the customer database.`) databaseHost := ConfigurationDB.Read(`CustomerDBHost`) - databaseDB := ConfigurationDB.Read(`CustomerDBDatabase`) - databaseUsername := ConfigurationDB.Read(`CustomerDBUsername`) - databasePassword := ConfigurationDB.Read(`CustomerDBPassword`) + databaseDB = ConfigurationDB.Read(`CustomerDBDatabase`) + databaseUsername = ConfigurationDB.Read(`CustomerDBUsername`) + databasePassword = ConfigurationDB.Read(`CustomerDBPassword`) // Connect to MongoDB: if newSession, errDial := mgo.Dial(databaseHost); errDial != nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNameDATABASE, `It was not possible to connect to the MongoDB host `+databaseHost, errDial.Error()) return } else { - session = newSession + mainSession = newSession } // Use the correct database: - db = session.DB(databaseDB) + db := mainSession.DB(databaseDB) if db == nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to get the customer database.`) return @@ -35,8 +35,15 @@ func init() { return } + // In case of write operations, wait for the majority of servers to be done: + mainSession.SetSafe(&mgo.Safe{WMode: "majority"}) + + // Set the consistency mode to read from any secondary server and write to the primary. + // Copied sessions can overwrite this setting of necessary. + mainSession.SetMode(mgo.Eventual, true) + // Get the GridFS: - gridFS = db.GridFS(`fs`) + gridFS := db.GridFS(`fs`) if gridFS == nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to get the GridFS from the database.`) return diff --git a/CustomerDB/Shutdown.go b/CustomerDB/Shutdown.go index 9ed25b8..51c6a12 100644 --- a/CustomerDB/Shutdown.go +++ b/CustomerDB/Shutdown.go @@ -14,6 +14,4 @@ This function is called if the Ocean server is shutting down. */ func (a ShutdownFunction) Shutdown() { Log.LogShort(senderName, LM.CategoryAPP, LM.LevelWARN, LM.MessageNameSHUTDOWN, `Close now the customer database connection.`) - db.Logout() - session.Close() } diff --git a/CustomerDB/Variables.go b/CustomerDB/Variables.go index 73a713a..2e3891f 100644 --- a/CustomerDB/Variables.go +++ b/CustomerDB/Variables.go @@ -4,8 +4,9 @@ import "labix.org/v2/mgo" import LM "github.com/SommerEngineering/Ocean/Log/Meta" var ( - session *mgo.Session = nil - db *mgo.Database = nil - gridFS *mgo.GridFS = nil - senderName LM.Sender = `System::CustomerDB` + mainSession *mgo.Session = nil + senderName LM.Sender = `System::CustomerDB` + databaseUsername string = `` + databasePassword string = `` + databaseDB string = `` ) diff --git a/ICCC/Doc.go b/ICCC/Doc.go index 95e7e3e..9ee2c19 100644 --- a/ICCC/Doc.go +++ b/ICCC/Doc.go @@ -1,4 +1,4 @@ /* -This is the "[I]nter Data [C]enter Se[c]ure [C]ommunication" :) +This is the "[I]nter Data [C]enter and Appli[c]ation [C]ommunication" */ package ICCC diff --git a/ICCC/Init.go b/ICCC/Init.go index d1dd496..818d05b 100644 --- a/ICCC/Init.go +++ b/ICCC/Init.go @@ -21,5 +21,6 @@ func init() { initDB() registerHost2Database() + cacheTimerLogic(false) initCacheTimer() } diff --git a/ICCC/InitDB.go b/ICCC/InitDB.go index 847a391..cdab44d 100644 --- a/ICCC/InitDB.go +++ b/ICCC/InitDB.go @@ -10,7 +10,7 @@ func initDB() { defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Done init the ICCC collection.`) // Get the database: - db = CustomerDB.DB() + dbSession, db = CustomerDB.DB() if db == nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to get the customer database.`) diff --git a/ICCC/ListenerCache.go b/ICCC/ListenerCache.go index 19c2ce6..4fc95d4 100644 --- a/ICCC/ListenerCache.go +++ b/ICCC/ListenerCache.go @@ -9,33 +9,38 @@ import "github.com/SommerEngineering/Ocean/Log" import LM "github.com/SommerEngineering/Ocean/Log/Meta" func initCacheTimer() { - go func() { for { - - if Shutdown.IsDown() { - return - } - - lastCount := cacheListenerDatabase.Len() - selection := bson.D{{`IsActive`, true}} - entriesIterator := collectionListener.Find(selection).Iter() - entry := Scheme.Listener{} - - cacheListenerDatabaseLock.Lock() - cacheListenerDatabase.Init() - for entriesIterator.Next(&entry) { - cacheListenerDatabase.PushBack(entry) - } - - cacheListenerDatabaseLock.Unlock() - nextDuration := time.Duration(5) * time.Minute - if cacheListenerDatabase.Len() == 0 { - nextDuration = time.Duration(10) * time.Second - } - - Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameEXECUTE, `The listener cache was refreshed with the values from the database.`, fmt.Sprintf(`last count=%d`, lastCount), fmt.Sprintf(`new count=%d`, cacheListenerDatabase.Len())) - time.Sleep(nextDuration) + cacheTimerLogic(true) } }() } + +func cacheTimerLogic(waiting bool) { + if Shutdown.IsDown() { + return + } + + lastCount := cacheListenerDatabase.Len() + selection := bson.D{{`IsActive`, true}} + entriesIterator := collectionListener.Find(selection).Iter() + entry := Scheme.Listener{} + + cacheListenerDatabaseLock.Lock() + cacheListenerDatabase.Init() + for entriesIterator.Next(&entry) { + cacheListenerDatabase.PushBack(entry) + } + + cacheListenerDatabaseLock.Unlock() + Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameEXECUTE, `The listener cache was refreshed with the values from the database.`, fmt.Sprintf(`last count=%d`, lastCount), fmt.Sprintf(`new count=%d`, cacheListenerDatabase.Len())) + + if waiting { + nextDuration := time.Duration(5) * time.Minute + if cacheListenerDatabase.Len() == 0 { + nextDuration = time.Duration(10) * time.Second + } + + time.Sleep(nextDuration) + } +} diff --git a/ICCC/Shutdown.go b/ICCC/Shutdown.go index 56f72ef..e3a5a71 100644 --- a/ICCC/Shutdown.go +++ b/ICCC/Shutdown.go @@ -26,5 +26,7 @@ func (a ShutdownFunction) Shutdown() { collectionListener.Update(selectionUpdate, entry) } + db.Logout() + dbSession.Close() Log.LogShort(senderName, LM.CategoryAPP, LM.LevelWARN, LM.MessageNameSHUTDOWN, `Done shutting down now all ICCC listener for this host.`) } diff --git a/ICCC/Variables.go b/ICCC/Variables.go index 593642d..c8e25ed 100644 --- a/ICCC/Variables.go +++ b/ICCC/Variables.go @@ -16,6 +16,7 @@ const ( var ( senderName LM.Sender = `ICCC` db *mgo.Database = nil + dbSession *mgo.Session = nil collectionListener *mgo.Collection = nil collectionHosts *mgo.Collection = nil reservedSystemChannels []string = []string{ChannelSYSTEM, ChannelNUMGEN, ChannelSHUTDOWN, ChannelSTARTUP, ChannelICCC} diff --git a/MimeTypes/KnownTypes.go b/MimeTypes/KnownTypes.go index 0f4f863..dc87fe5 100644 --- a/MimeTypes/KnownTypes.go +++ b/MimeTypes/KnownTypes.go @@ -3,6 +3,7 @@ package MimeTypes var TypeWebHTML = MimeType{MimeType: "text/html", FileExtension: []string{".html", ".htm"}} var TypeWebCSS = MimeType{MimeType: "text/css", FileExtension: []string{".css"}} var TypeWebJavaScript = MimeType{MimeType: "text/javascript", FileExtension: []string{".js"}} +var TypeWebDart = MimeType{MimeType: "application/dart", FileExtension: []string{".dart"}} var TypeXML = MimeType{MimeType: "text/xml", FileExtension: []string{".xml"}} var TypeArchiveZIP = MimeType{MimeType: "application/zip", FileExtension: []string{".zip"}} var TypeArchiveGZ = MimeType{MimeType: "application/gzip", FileExtension: []string{".gz"}} diff --git a/NumGen/InitDB.go b/NumGen/InitDB.go index 1122a43..2c94571 100644 --- a/NumGen/InitDB.go +++ b/NumGen/InitDB.go @@ -10,7 +10,7 @@ func initDB() { defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Done init of number generator collection.`) // Get the database: - db = CustomerDB.DB() + dbSession, db = CustomerDB.DB() if db == nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to get the customer database.`) diff --git a/NumGen/Shutdown.go b/NumGen/Shutdown.go index a2d2fed..76d0dc8 100644 --- a/NumGen/Shutdown.go +++ b/NumGen/Shutdown.go @@ -8,4 +8,6 @@ type ShutdownFunction struct { func (a ShutdownFunction) Shutdown() { Log.LogShort(senderName, LM.CategoryAPP, LM.LevelWARN, LM.MessageNameSHUTDOWN, `Shutting down the number generator.`) + db.Logout() + dbSession.Close() } diff --git a/NumGen/Variables.go b/NumGen/Variables.go index 3bf18c5..9348a23 100644 --- a/NumGen/Variables.go +++ b/NumGen/Variables.go @@ -10,6 +10,7 @@ var ( isActive bool = false getHandler string = `` db *mgo.Database = nil + dbSession *mgo.Session = nil collectionNumGen *mgo.Collection = nil channelBufferSize int = 10 channelList map[string]chan int64 = nil diff --git a/Shutdown/Shutdown.go b/Shutdown/Shutdown.go index c61852c..05c0b8b 100644 --- a/Shutdown/Shutdown.go +++ b/Shutdown/Shutdown.go @@ -9,7 +9,7 @@ type ShutdownHandler interface { } func AddShutdownHandler(handler ShutdownHandler) { - shutdownHandlers.PushBack(handler) + shutdownHandlers.PushFront(handler) } func executeShutdown() { diff --git a/StaticFiles/Init.go b/StaticFiles/Init.go index fa3138b..8dfb974 100644 --- a/StaticFiles/Init.go +++ b/StaticFiles/Init.go @@ -26,7 +26,9 @@ func init() { logStaticFileRequests = ConfigurationDB.Read(`LogStaticFileRequests`) == `true` // Read the static files' data from GridFS: - gridFS := CustomerDB.GridFS() + dbSession, gridFS := CustomerDB.GridFS() + defer dbSession.Close() + if gridFile, errGridFile := gridFS.Open(`staticFiles.zip`); errGridFile != nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to open the static files out of the GridFS!`, errGridFile.Error()) return diff --git a/System/Init.go b/System/Init.go index 3cee79e..761f795 100644 --- a/System/Init.go +++ b/System/Init.go @@ -78,11 +78,17 @@ func initSystem() { Log.LoggingIsReady() // Register all system shutdown handlers: + // + // Please notice: If the shutdown event occurs ... + // * all application handlers are called (order: last comed, first served) + // * 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{}) + // The logging subsystem is not registered here, because it will be automated called at the end // Register all system ICCC commands: diff --git a/Templates/Init.go b/Templates/Init.go index e811415..2262d3b 100644 --- a/Templates/Init.go +++ b/Templates/Init.go @@ -13,7 +13,9 @@ func init() { Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Starting the template engine.`) defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Starting the template engine done.`) - gridFS := CustomerDB.GridFS() + dbSession, gridFS := CustomerDB.GridFS() + defer dbSession.Close() + if gridFile, errGridFile := gridFS.Open(`templates.zip`); errGridFile != nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to open the templates out of the GridFS!`, errGridFile.Error()) return diff --git a/WebContent/Init.go b/WebContent/Init.go index 0c91c99..5569dc0 100644 --- a/WebContent/Init.go +++ b/WebContent/Init.go @@ -17,7 +17,8 @@ func init() { } filename = ConfigurationDB.Read(`FilenameWebResources`) - gridFS := CustomerDB.GridFS() + dbSession, gridFS := CustomerDB.GridFS() + defer dbSession.Close() if gridFile, errGridFile := gridFS.Open(filename); errGridFile != nil { Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to open the web content out of the GridFS!`, filename, errGridFile.Error())