Initial commit of Ocean's local development
This commit is contained in:
		
							parent
							
								
									9944a9e1df
								
							
						
					
					
						commit
						86451938ec
					
				
							
								
								
									
										19
									
								
								Configuration/Doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Configuration/Doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					This package reads the configuration file from the disk (file: configuration.json).
 | 
				
			||||||
 | 
					This configuratin is just used to specific the configuration database to go further.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					An example configuration.json file:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"ConfigDBHostname" : "localhost:27017",
 | 
				
			||||||
 | 
							"ConfigDBDatabase" : "MyDatabase",
 | 
				
			||||||
 | 
							"ConfigDBConfigurationCollection" : "Configuration",
 | 
				
			||||||
 | 
							"ConfigDBConfigurationCollectionUsername" : "ConfigurationUsername",
 | 
				
			||||||
 | 
							"ConfigDBConfigurationCollectionPassword" : "ConfigurationPassword"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hint #1: Ocean is using MongoDB as database ;-)
 | 
				
			||||||
 | 
					Hint #2: Normally, you do not use this package at all, because the application configuration should persist
 | 
				
			||||||
 | 
					inside the configuration database. Your task: Provide a configuration.json file at the installation directory ;-)
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package Configuration
 | 
				
			||||||
							
								
								
									
										6
									
								
								Configuration/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Configuration/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						readConfiguration()
 | 
				
			||||||
 | 
						isInit = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								Configuration/Meta/Structure.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Configuration/Meta/Structure.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The type which matches the configuration file:
 | 
				
			||||||
 | 
					type Configuration struct {
 | 
				
			||||||
 | 
						ConfigDBHostname                        string
 | 
				
			||||||
 | 
						ConfigDBDatabase                        string
 | 
				
			||||||
 | 
						ConfigDBConfigurationCollection         string
 | 
				
			||||||
 | 
						ConfigDBConfigurationCollectionUsername string
 | 
				
			||||||
 | 
						ConfigDBConfigurationCollectionPassword string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								Configuration/PublicRead.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Configuration/PublicRead.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					package Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Configuration/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Read the whole configuration and enable Ocean to get the configuration database.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hint: Normally, you do not use this package at all, because the application configuration should persist
 | 
				
			||||||
 | 
					inside the configuration database.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func Read() (result Meta.Configuration) {
 | 
				
			||||||
 | 
						result = configuration
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										52
									
								
								Configuration/ReadConfiguration.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								Configuration/ReadConfiguration.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					package Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "encoding/json"
 | 
				
			||||||
 | 
					import "os"
 | 
				
			||||||
 | 
					import "path/filepath"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func readConfiguration() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if isInit {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, Meta.CategorySYSTEM, Meta.LevelWARN, Meta.SeverityNone, Meta.ImpactNone, Meta.MessageNameINIT, `The configuration package is already init!`)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, Meta.CategorySYSTEM, Meta.LevelINFO, Meta.MessageNameCONFIGURATION, `Init of configuration starting.`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						currentDir, dirError := os.Getwd()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if dirError != nil {
 | 
				
			||||||
 | 
							panic(`Was not able to read the working directory: ` + dirError.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						currentPath := filepath.Join(currentDir, filename)
 | 
				
			||||||
 | 
						if _, errFile := os.Stat(currentPath); errFile != nil {
 | 
				
			||||||
 | 
							if os.IsNotExist(errFile) {
 | 
				
			||||||
 | 
								panic(`It was not possible to find the necessary configuration file 'configuration.json' at the application directory.`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								panic(`There was an error while open the configuration: ` + errFile.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file, fileError := os.Open(currentPath)
 | 
				
			||||||
 | 
						defer file.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if fileError != nil {
 | 
				
			||||||
 | 
							panic(`The configuration file is not accessible: ` + fileError.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						decoder := json.NewDecoder(file)
 | 
				
			||||||
 | 
						decError := decoder.Decode(&configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if decError != nil {
 | 
				
			||||||
 | 
							panic(`Decoding of the configuration file was not possible: ` + decError.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, Meta.CategorySYSTEM, Meta.LevelINFO, Meta.MessageNameINIT, `Init of configuration is done.`)
 | 
				
			||||||
 | 
						isInit = true
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								Configuration/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Configuration/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					package Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Configuration/Meta"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						filename                         = "configuration.json" // Where is the configuration located?
 | 
				
			||||||
 | 
						configuration Meta.Configuration = Meta.Configuration{} // The loaded configuration
 | 
				
			||||||
 | 
						isInit                           = false                // Is the configuration loaded?
 | 
				
			||||||
 | 
						senderName    LM.Sender          = `System::Configuration`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										65
									
								
								ConfigurationDB/CheckConfiguration.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								ConfigurationDB/CheckConfiguration.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					package ConfigurationDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo/bson"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkConfiguration() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameDATABASE, `Check now the configuration database.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameDATABASE, `Done checking the configuration database.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`InternalCommPassword`, `please replace this with e.g. a random GUID, etc.`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBHost`, `localhost:27017`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBDatabase`, `Ocean`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBUsername`, `root`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBPassword`, `please replace this with a good password`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDBHost`, `localhost:27017`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDBDatabase`, `Ocean`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDBUsername`, `root`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDBPassword`, `please replace this with a good password`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDBCacheSizeNumberOfEvents`, `50`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDBCacheSizeTime2FlushSeconds`, `6`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogBufferSize`, `500`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDeviceDelayNumberEvents`, `600`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogDeviceDelayTime2FlushSeconds`, `5`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogTimeoutSeconds`, `4`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogStaticFileRequests`, `false`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogUseDatabaseLogging`, `false`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`LogUseConsoleLogging`, `true`)
 | 
				
			||||||
 | 
						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(`OceanUtilizeCPUs`, `2`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`FilenameWebResources`, `web.zip`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`MapStaticFiles2Root`, `false`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`MapStaticFiles2RootRootFile`, `index.html`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`EnableStaticFiles`, `true`)
 | 
				
			||||||
 | 
						CheckSingleConfigurationPresentsAndAddIfMissing(`robots.txt`, `User-agent: *
 | 
				
			||||||
 | 
					Disallow:`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Use this function to ensure that the database contains at least a default value for the configuration.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func CheckSingleConfigurationPresentsAndAddIfMissing(name, value string) {
 | 
				
			||||||
 | 
						if !checkSingleConfigurationPresents(name) {
 | 
				
			||||||
 | 
							addSingleConfiguration(name, value)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkSingleConfigurationPresents(name string) (result bool) {
 | 
				
			||||||
 | 
						selection := bson.D{{"Name", name}}
 | 
				
			||||||
 | 
						count, _ := collection.Find(selection).Count()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return count > 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addSingleConfiguration(name, value string) {
 | 
				
			||||||
 | 
						entry := ConfigurationDBEntry{}
 | 
				
			||||||
 | 
						entry.Name = name
 | 
				
			||||||
 | 
						entry.Value = value
 | 
				
			||||||
 | 
						collection.Insert(entry)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameDATABASE, `Add a missing configuration to the configuration database.`, `Name=`+name, `Value=`+value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								ConfigurationDB/Doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								ConfigurationDB/Doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					This package provides the configuration database access: Ocean uses MongoDB as database! The configuration is represented as
 | 
				
			||||||
 | 
					name value pairs. Both, the name and the value, are strings. If you need numbers for the configuration, you have to convert
 | 
				
			||||||
 | 
					these strings in to numbers afterwards. Use the Read() function to read a specific configuration value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To provide own application configurations, use the function CheckSingleConfigurationPresentsAndAddIfMissing() to ensure, that
 | 
				
			||||||
 | 
					at least a default value is present in the database. Collect all these function calls inside a init() function somewhere at your
 | 
				
			||||||
 | 
					application.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package ConfigurationDB
 | 
				
			||||||
							
								
								
									
										38
									
								
								ConfigurationDB/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								ConfigurationDB/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					package ConfigurationDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Configuration"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config := Configuration.Read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Connect to MongoDB:
 | 
				
			||||||
 | 
						if newSession, errDial := mgo.Dial(config.ConfigDBHostname); 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 `+config.ConfigDBHostname, errDial.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							session = newSession
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Use the correct database:
 | 
				
			||||||
 | 
						db = session.DB(config.ConfigDBDatabase)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Login:
 | 
				
			||||||
 | 
						if errLogin := db.Login(config.ConfigDBConfigurationCollectionUsername, config.ConfigDBConfigurationCollectionPassword); errLogin != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNameDATABASE, `It was not possible to login the user `+config.ConfigDBConfigurationCollectionUsername, errLogin.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the collection:
 | 
				
			||||||
 | 
						collection = db.C(config.ConfigDBConfigurationCollection)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Take care about the index:
 | 
				
			||||||
 | 
						collection.EnsureIndexKey(`Name`)
 | 
				
			||||||
 | 
						collection.EnsureIndexKey(`Value`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						checkConfiguration()
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameDATABASE, `The configuration database is now ready.`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								ConfigurationDB/Read.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								ConfigurationDB/Read.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package ConfigurationDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo/bson"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function reads the current configuration value.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func Read(name string) (value string) {
 | 
				
			||||||
 | 
						if name == `` {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNameDATABASE, `Was not able to read a configuration out of the database.`, `The given name was nil!`)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := ConfigurationDBEntry{}
 | 
				
			||||||
 | 
						if errFind := collection.Find(bson.D{{"Name", name}}).One(&result); errFind != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNameDATABASE, `Was not able to read a configuration out of the database.`, `Error while find.`, errFind.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value = result.Value
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								ConfigurationDB/Scheme.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ConfigurationDB/Scheme.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package ConfigurationDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ConfigurationDBEntry struct {
 | 
				
			||||||
 | 
						Name  string `bson:"Name"`
 | 
				
			||||||
 | 
						Value string `bson:"Value"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								ConfigurationDB/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								ConfigurationDB/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package ConfigurationDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Do not use this type by your own! It is a Ocean internal type to provide a shutdown function for the configuration database.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					type ShutdownFunction struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					If the Ocean server is shutting down, this function is called to close the database.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (a ShutdownFunction) Shutdown() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategoryAPP, LM.LevelWARN, LM.MessageNameSHUTDOWN, `Close now the configuration database connection.`)
 | 
				
			||||||
 | 
						db.Logout()
 | 
				
			||||||
 | 
						session.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								ConfigurationDB/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								ConfigurationDB/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					package ConfigurationDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Configuration/Meta"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						session    *mgo.Session       = nil
 | 
				
			||||||
 | 
						db         *mgo.Database      = nil
 | 
				
			||||||
 | 
						collection *mgo.Collection    = nil
 | 
				
			||||||
 | 
						config     Meta.Configuration = Meta.Configuration{}
 | 
				
			||||||
 | 
						senderName LM.Sender          = `System::ConfigurationDB`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										19
									
								
								CustomerDB/AccessDB.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								CustomerDB/AccessDB.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package CustomerDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Get the database instance of the MGo Mongo driver.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func DB() (result *mgo.Database) {
 | 
				
			||||||
 | 
						result = db
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Get directly the GridFS instance of the Mgo Mongo driver.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func GridFS() (result *mgo.GridFS) {
 | 
				
			||||||
 | 
						result = gridFS
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								CustomerDB/Doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								CustomerDB/Doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					This package provides access to the customer database. To specific the customer database, please use the configuration database.
 | 
				
			||||||
 | 
					By the way: Ocean uses MongoDB as database ;-) This package is just a facade to hide the complexity from MongoDB and its driver.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package CustomerDB
 | 
				
			||||||
							
								
								
									
										52
									
								
								CustomerDB/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								CustomerDB/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					package CustomerDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Use the correct database:
 | 
				
			||||||
 | 
						db = session.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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Login:
 | 
				
			||||||
 | 
						if errLogin := db.Login(databaseUsername, databasePassword); errLogin != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNameDATABASE, `It was not possible to login the user `+databaseUsername, errLogin.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the GridFS:
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure the indexes for the GridFS:
 | 
				
			||||||
 | 
						filesCollection := gridFS.Files
 | 
				
			||||||
 | 
						filesCollection.EnsureIndexKey(`uploadDate`)
 | 
				
			||||||
 | 
						filesCollection.EnsureIndexKey(`filename`)
 | 
				
			||||||
 | 
						filesCollection.EnsureIndexKey(`filename`, `uploadDate`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameDATABASE, `Customer database is now ready.`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								CustomerDB/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								CustomerDB/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package CustomerDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Please do not use this type. It is an internal type of Ocean to provide a shutdown function!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					type ShutdownFunction struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					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()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								CustomerDB/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								CustomerDB/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					package CustomerDB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										122
									
								
								ICCC/Data2Message.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								ICCC/Data2Message.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "reflect"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Data2Message(target interface{}, data map[string][]string) (channel, command string, obj interface{}) {
 | 
				
			||||||
 | 
						if data == nil || len(data) == 0 {
 | 
				
			||||||
 | 
							channel = ``
 | 
				
			||||||
 | 
							command = ``
 | 
				
			||||||
 | 
							obj = nil
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						element := reflect.ValueOf(target)
 | 
				
			||||||
 | 
						element = element.Elem()
 | 
				
			||||||
 | 
						elementType := element.Type()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						channel = data[`channel`][0]
 | 
				
			||||||
 | 
						command = data[`command`][0]
 | 
				
			||||||
 | 
						for i := 0; i < element.NumField(); i++ {
 | 
				
			||||||
 | 
							field := element.Field(i)
 | 
				
			||||||
 | 
							switch field.Kind().String() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `int64`:
 | 
				
			||||||
 | 
								mapName := fmt.Sprintf(`int:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
								mapValue := data[mapName][0]
 | 
				
			||||||
 | 
								v, _ := strconv.ParseInt(mapValue, 10, 64)
 | 
				
			||||||
 | 
								field.SetInt(v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `string`:
 | 
				
			||||||
 | 
								mapName := fmt.Sprintf(`str:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
								mapValue := data[mapName][0]
 | 
				
			||||||
 | 
								field.SetString(mapValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `float64`:
 | 
				
			||||||
 | 
								mapName := fmt.Sprintf(`f64:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
								mapValue := data[mapName][0]
 | 
				
			||||||
 | 
								v, _ := strconv.ParseFloat(mapValue, 64)
 | 
				
			||||||
 | 
								field.SetFloat(v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `bool`:
 | 
				
			||||||
 | 
								mapName := fmt.Sprintf(`bool:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
								mapValue := data[mapName][0]
 | 
				
			||||||
 | 
								v, _ := strconv.ParseBool(mapValue)
 | 
				
			||||||
 | 
								field.SetBool(v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `uint8`:
 | 
				
			||||||
 | 
								mapName := fmt.Sprintf(`ui8:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
								mapValue := data[mapName][0]
 | 
				
			||||||
 | 
								v, _ := strconv.ParseUint(mapValue, 16, 8)
 | 
				
			||||||
 | 
								field.SetUint(v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `slice`:
 | 
				
			||||||
 | 
								sliceInterface := field.Interface()
 | 
				
			||||||
 | 
								sliceKind := reflect.ValueOf(sliceInterface).Type().String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								switch sliceKind {
 | 
				
			||||||
 | 
								case `[]uint8`: // bytes
 | 
				
			||||||
 | 
									mapName := fmt.Sprintf(`ui8[]:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
									mapValues := data[mapName]
 | 
				
			||||||
 | 
									fieldLen := len(mapValues)
 | 
				
			||||||
 | 
									fieldData := make([]uint8, fieldLen, fieldLen)
 | 
				
			||||||
 | 
									for n, mapValue := range mapValues {
 | 
				
			||||||
 | 
										v, _ := strconv.ParseUint(mapValue, 16, 8)
 | 
				
			||||||
 | 
										fieldData[n] = byte(v)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									fieldDataValue := reflect.ValueOf(fieldData)
 | 
				
			||||||
 | 
									field.Set(fieldDataValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case `[]int64`:
 | 
				
			||||||
 | 
									mapName := fmt.Sprintf(`int[]:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
									mapValues := data[mapName]
 | 
				
			||||||
 | 
									fieldLen := len(mapValues)
 | 
				
			||||||
 | 
									fieldData := make([]int64, fieldLen, fieldLen)
 | 
				
			||||||
 | 
									for n, mapValue := range mapValues {
 | 
				
			||||||
 | 
										v, _ := strconv.ParseInt(mapValue, 10, 64)
 | 
				
			||||||
 | 
										fieldData[n] = v
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									fieldDataValue := reflect.ValueOf(fieldData)
 | 
				
			||||||
 | 
									field.Set(fieldDataValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case `[]bool`:
 | 
				
			||||||
 | 
									mapName := fmt.Sprintf(`bool[]:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
									mapValues := data[mapName]
 | 
				
			||||||
 | 
									fieldLen := len(mapValues)
 | 
				
			||||||
 | 
									fieldData := make([]bool, fieldLen, fieldLen)
 | 
				
			||||||
 | 
									for n, mapValue := range mapValues {
 | 
				
			||||||
 | 
										v, _ := strconv.ParseBool(mapValue)
 | 
				
			||||||
 | 
										fieldData[n] = v
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									fieldDataValue := reflect.ValueOf(fieldData)
 | 
				
			||||||
 | 
									field.Set(fieldDataValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case `[]string`:
 | 
				
			||||||
 | 
									mapName := fmt.Sprintf(`str[]:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
									mapValues := data[mapName]
 | 
				
			||||||
 | 
									fieldDataValue := reflect.ValueOf(mapValues)
 | 
				
			||||||
 | 
									field.Set(fieldDataValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case `[]float64`:
 | 
				
			||||||
 | 
									mapName := fmt.Sprintf(`f64[]:%s`, elementType.Field(i).Name)
 | 
				
			||||||
 | 
									mapValues := data[mapName]
 | 
				
			||||||
 | 
									fieldLen := len(mapValues)
 | 
				
			||||||
 | 
									fieldData := make([]float64, fieldLen, fieldLen)
 | 
				
			||||||
 | 
									for n, mapValue := range mapValues {
 | 
				
			||||||
 | 
										v, _ := strconv.ParseFloat(mapValue, 64)
 | 
				
			||||||
 | 
										fieldData[n] = v
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									fieldDataValue := reflect.ValueOf(fieldData)
 | 
				
			||||||
 | 
									field.Set(fieldDataValue)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj = target
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								ICCC/Doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								ICCC/Doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					This is the "[I]nter Data [C]enter Se[c]ure [C]ommunication" :)
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package ICCC
 | 
				
			||||||
							
								
								
									
										34
									
								
								ICCC/HTTPConnector.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								ICCC/HTTPConnector.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Tools"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ICCCHandler(response http.ResponseWriter, request *http.Request) {
 | 
				
			||||||
 | 
						if errParse := request.ParseForm(); errParse != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameNETWORK, `Was not able to parse the HTTP form data from an ICCC message!`)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						messageData := map[string][]string(request.PostForm)
 | 
				
			||||||
 | 
						channel := messageData[`channel`][0]
 | 
				
			||||||
 | 
						command := messageData[`command`][0]
 | 
				
			||||||
 | 
						password := messageData[`InternalCommPassword`][0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if password != Tools.InternalCommPassword() {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityCritical, LM.ImpactNone, LM.MessageNamePASSWORD, `Received a ICCC message with wrong password!`, request.RemoteAddr)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key := fmt.Sprintf(`%s::%s`, channel, command)
 | 
				
			||||||
 | 
						listener := listeners[key]
 | 
				
			||||||
 | 
						if listener == nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `Was not able to find the correct listener for these ICCC message.`, `channel=`+channel, `command`+command, `hostname=`+Tools.ThisHostname())
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							listener(messageData)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								ICCC/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								ICCC/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Start init of ICCC.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Done init ICCC.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initDB()
 | 
				
			||||||
 | 
						registerHost2Database()
 | 
				
			||||||
 | 
						initCacheTimer()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								ICCC/InitDB.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								ICCC/InitDB.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/CustomerDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initDB() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Start init of the ICCC collections.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Done init the ICCC collection.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the database:
 | 
				
			||||||
 | 
						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.`)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get my collections:
 | 
				
			||||||
 | 
						collectionListener = db.C(`ICCCListener`)
 | 
				
			||||||
 | 
						collectionHosts = db.C(`ICCCHosts`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Take care about the indexes for ICCCListener:
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Command`)
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Command`, `IsActive`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Command`, `Channel`)
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Command`, `Channel`, `IsActive`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Channel`)
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Channel`, `IsActive`)
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Channel`, `Command`, `IPAddressPort`, `IsActive`)
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`Channel`, `Command`, `IsActive`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`IsActive`)
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`IsActive`, `IPAddressPort`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						collectionListener.EnsureIndexKey(`IPAddressPort`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexName1 := mgo.Index{}
 | 
				
			||||||
 | 
						indexName1.Key = []string{`Channel`, `Command`, `IPAddressPort`}
 | 
				
			||||||
 | 
						indexName1.Unique = true
 | 
				
			||||||
 | 
						collectionListener.EnsureIndex(indexName1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Index for hosts:
 | 
				
			||||||
 | 
						collectionHosts.EnsureIndexKey(`Hostname`, `IPAddressPort`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexName2 := mgo.Index{}
 | 
				
			||||||
 | 
						indexName2.Key = []string{`Hostname`}
 | 
				
			||||||
 | 
						indexName2.Unique = true
 | 
				
			||||||
 | 
						collectionHosts.EnsureIndex(indexName2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexName3 := mgo.Index{}
 | 
				
			||||||
 | 
						indexName3.Key = []string{`IPAddressPort`}
 | 
				
			||||||
 | 
						indexName3.Unique = true
 | 
				
			||||||
 | 
						collectionHosts.EnsureIndex(indexName3)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								ICCC/ListenerCache.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								ICCC/ListenerCache.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo/bson"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										95
									
								
								ICCC/Message2Data.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								ICCC/Message2Data.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "reflect"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func message2Data(channel, command string, message interface{}) (data map[string][]string) {
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch field.Kind().String() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `int64`:
 | 
				
			||||||
 | 
								key := fmt.Sprintf(`int:%s`, keyName)
 | 
				
			||||||
 | 
								data[key] = []string{strconv.FormatInt(field.Int(), 10)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `string`:
 | 
				
			||||||
 | 
								key := fmt.Sprintf(`str:%s`, keyName)
 | 
				
			||||||
 | 
								data[key] = []string{field.String()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `float64`:
 | 
				
			||||||
 | 
								key := fmt.Sprintf(`f64:%s`, keyName)
 | 
				
			||||||
 | 
								data[key] = []string{strconv.FormatFloat(field.Float(), 'f', 9, 64)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `bool`:
 | 
				
			||||||
 | 
								key := fmt.Sprintf(`bool:%s`, keyName)
 | 
				
			||||||
 | 
								data[key] = []string{strconv.FormatBool(field.Bool())}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `uint8`: // byte
 | 
				
			||||||
 | 
								key := fmt.Sprintf(`ui8:%s`, keyName)
 | 
				
			||||||
 | 
								data[key] = []string{strconv.FormatUint(field.Uint(), 16)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case `slice`:
 | 
				
			||||||
 | 
								sliceLen := field.Len()
 | 
				
			||||||
 | 
								if sliceLen > 0 {
 | 
				
			||||||
 | 
									sliceKind := field.Index(0).Kind()
 | 
				
			||||||
 | 
									key := ``
 | 
				
			||||||
 | 
									dataValues := make([]string, sliceLen, sliceLen)
 | 
				
			||||||
 | 
									switch sliceKind.String() {
 | 
				
			||||||
 | 
									case `uint8`: // bytes
 | 
				
			||||||
 | 
										key = fmt.Sprintf(`ui8[]:%s`, keyName)
 | 
				
			||||||
 | 
										values := field.Interface().([]uint8)
 | 
				
			||||||
 | 
										for index, value := range values {
 | 
				
			||||||
 | 
											dataValues[index] = strconv.FormatUint(uint64(value), 16)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									case `int64`:
 | 
				
			||||||
 | 
										key = fmt.Sprintf(`int[]:%s`, keyName)
 | 
				
			||||||
 | 
										values := field.Interface().([]int64)
 | 
				
			||||||
 | 
										for index, value := range values {
 | 
				
			||||||
 | 
											dataValues[index] = strconv.FormatInt(value, 10)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									case `bool`:
 | 
				
			||||||
 | 
										key = fmt.Sprintf(`bool[]:%s`, keyName)
 | 
				
			||||||
 | 
										values := field.Interface().([]bool)
 | 
				
			||||||
 | 
										for index, value := range values {
 | 
				
			||||||
 | 
											dataValues[index] = strconv.FormatBool(value)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									case `string`:
 | 
				
			||||||
 | 
										key = fmt.Sprintf(`str[]:%s`, keyName)
 | 
				
			||||||
 | 
										values := field.Interface().([]string)
 | 
				
			||||||
 | 
										for index, value := range values {
 | 
				
			||||||
 | 
											dataValues[index] = value
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									case `float64`:
 | 
				
			||||||
 | 
										key = fmt.Sprintf(`f64[]:%s`, keyName)
 | 
				
			||||||
 | 
										values := field.Interface().([]float64)
 | 
				
			||||||
 | 
										for index, value := range values {
 | 
				
			||||||
 | 
											dataValues[index] = strconv.FormatFloat(value, 'f', 9, 64)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									data[key] = dataValues
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								ICCC/Register2Database.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								ICCC/Register2Database.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo/bson"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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(¬ActiveEntry)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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.`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								ICCC/RegisterHost2Database.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								ICCC/RegisterHost2Database.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo/bson"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Tools"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func registerHost2Database() {
 | 
				
			||||||
 | 
						host := Scheme.Host{}
 | 
				
			||||||
 | 
						host.Hostname = Tools.ThisHostname()
 | 
				
			||||||
 | 
						host.IPAddressPort = correctAddressWithPort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection := bson.D{{`Hostname`, host.Hostname}, {`IPAddressPort`, host.IPAddressPort}}
 | 
				
			||||||
 | 
						count, _ := collectionHosts.Find(selection).Count()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if count == 1 {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `This host is already registered!`, `host=`+host.Hostname, `address=`+host.IPAddressPort)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if errInsert := collectionHosts.Insert(host); errInsert != nil {
 | 
				
			||||||
 | 
								Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `Was not able to register this host.`, errInsert.Error(), `host=`+host.Hostname, `address=`+host.IPAddressPort)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `This host is now registered.`, `host=`+host.Hostname, `address=`+host.IPAddressPort)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								ICCC/Registrar.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ICCC/Registrar.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Registrar(channel, command string, callback func(data map[string][]string)) {
 | 
				
			||||||
 | 
						listenersLock.Lock()
 | 
				
			||||||
 | 
						defer listenersLock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						register2Database(channel, command)
 | 
				
			||||||
 | 
						listeners[fmt.Sprintf(`%s::%s`, channel, command)] = callback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `The registrar has registered a new ICCC command.`, `channel=`+channel, `command=`+command)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								ICCC/Scheme/Host.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ICCC/Scheme/Host.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package Scheme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Host struct {
 | 
				
			||||||
 | 
						Hostname      string `bson:"Hostname"`
 | 
				
			||||||
 | 
						IPAddressPort string `bson:"IPAddressPort"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								ICCC/Scheme/Listener.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ICCC/Scheme/Listener.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					package Scheme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Listener struct {
 | 
				
			||||||
 | 
						Channel       string `bson:"Channel"`
 | 
				
			||||||
 | 
						Command       string `bson:"Command"`
 | 
				
			||||||
 | 
						IsActive      bool   `bson:"IsActive"`
 | 
				
			||||||
 | 
						IPAddressPort string `bson:"IPAddressPort"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								ICCC/Send.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								ICCC/Send.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "net/url"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Tools"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sendMessage(listener Scheme.Listener, data map[string][]string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						valuesHTTP := url.Values(data)
 | 
				
			||||||
 | 
						valuesHTTP.Add(`InternalCommPassword`, Tools.InternalCommPassword())
 | 
				
			||||||
 | 
						if _, err := http.PostForm(`http://`+listener.IPAddressPort+`/ICCC`, valuesHTTP); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameNETWORK, `Was not able to send the ICCC message.`, err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								ICCC/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								ICCC/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo/bson"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Please do not use this type. It is an internal type of Ocean to provide a shutdown function!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					type ShutdownFunction struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is called if the Ocean server is shutting down.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (a ShutdownFunction) Shutdown() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategoryAPP, LM.LevelWARN, LM.MessageNameSHUTDOWN, `Shutting down now all ICCC listener for this host.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection := bson.D{{`IPAddressPort`, correctAddressWithPort}}
 | 
				
			||||||
 | 
						entry := Scheme.Listener{}
 | 
				
			||||||
 | 
						iterator := collectionListener.Find(selection).Iter()
 | 
				
			||||||
 | 
						for iterator.Next(&entry) {
 | 
				
			||||||
 | 
							selectionUpdate := bson.D{{`Channel`, entry.Channel}, {`Command`, entry.Command}, {`IPAddressPort`, correctAddressWithPort}}
 | 
				
			||||||
 | 
							entry.IsActive = false
 | 
				
			||||||
 | 
							collectionListener.Update(selectionUpdate, entry)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategoryAPP, LM.LevelWARN, LM.MessageNameSHUTDOWN, `Done shutting down now all ICCC listener for this host.`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								ICCC/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								ICCC/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "sync"
 | 
				
			||||||
 | 
					import "container/list"
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ChannelSYSTEM   string = `System`
 | 
				
			||||||
 | 
						ChannelNUMGEN   string = `System::NumGen`
 | 
				
			||||||
 | 
						ChannelSHUTDOWN string = `System::Shutdown`
 | 
				
			||||||
 | 
						ChannelSTARTUP  string = `System::Startup`
 | 
				
			||||||
 | 
						ChannelICCC     string = `System::ICCC`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						senderName                LM.Sender                                 = `ICCC`
 | 
				
			||||||
 | 
						db                        *mgo.Database                             = nil
 | 
				
			||||||
 | 
						collectionListener        *mgo.Collection                           = nil
 | 
				
			||||||
 | 
						collectionHosts           *mgo.Collection                           = nil
 | 
				
			||||||
 | 
						reservedSystemChannels    []string                                  = []string{ChannelSYSTEM, ChannelNUMGEN, ChannelSHUTDOWN, ChannelSTARTUP, ChannelICCC}
 | 
				
			||||||
 | 
						listeners                 map[string]func(data map[string][]string) = nil
 | 
				
			||||||
 | 
						listenersLock             sync.RWMutex                              = sync.RWMutex{}
 | 
				
			||||||
 | 
						cacheListenerDatabase     *list.List                                = nil
 | 
				
			||||||
 | 
						cacheListenerDatabaseLock sync.RWMutex                              = sync.RWMutex{}
 | 
				
			||||||
 | 
						correctAddressWithPort    string                                    = ``
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										26
									
								
								ICCC/WriteMessage2All.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								ICCC/WriteMessage2All.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WriteMessage2All(channel, command string, message interface{}) {
 | 
				
			||||||
 | 
						cacheListenerDatabaseLock.RLock()
 | 
				
			||||||
 | 
						defer cacheListenerDatabaseLock.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := message2Data(channel, command, message)
 | 
				
			||||||
 | 
						counter := 0
 | 
				
			||||||
 | 
						for entry := cacheListenerDatabase.Front(); entry != nil; entry = entry.Next() {
 | 
				
			||||||
 | 
							listener := entry.Value.(Scheme.Listener)
 | 
				
			||||||
 | 
							if listener.Channel == channel && listener.Command == command {
 | 
				
			||||||
 | 
								go sendMessage(listener, data)
 | 
				
			||||||
 | 
								counter++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if counter == 0 {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `It was not able to deliver this message, because no listener was found!`, `channel=`+channel, `command=`+command)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								ICCC/WriteMessage2Any.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ICCC/WriteMessage2Any.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					package ICCC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Tools"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC/Scheme"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WriteMessage2Any(channel, command string, message interface{}) {
 | 
				
			||||||
 | 
						cacheListenerDatabaseLock.RLock()
 | 
				
			||||||
 | 
						defer cacheListenerDatabaseLock.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := message2Data(channel, command, message)
 | 
				
			||||||
 | 
						maxCount := cacheListenerDatabase.Len()
 | 
				
			||||||
 | 
						entries := make([]Scheme.Listener, 0, maxCount)
 | 
				
			||||||
 | 
						counter := 0
 | 
				
			||||||
 | 
						for entry := cacheListenerDatabase.Front(); entry != nil; entry = entry.Next() {
 | 
				
			||||||
 | 
							listener := entry.Value.(Scheme.Listener)
 | 
				
			||||||
 | 
							if listener.Channel == channel && listener.Command == command {
 | 
				
			||||||
 | 
								entries = entries[:len(entries)+1]
 | 
				
			||||||
 | 
								entries[counter] = listener
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count := len(entries)
 | 
				
			||||||
 | 
						if count > 0 {
 | 
				
			||||||
 | 
							listener := entries[Tools.RandomInteger(count)]
 | 
				
			||||||
 | 
							go sendMessage(listener, data)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `It was not able to deliver this message to any listener, because no listener was found!`, `channel=`+channel, `command=`+command)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								Log/AddDevice.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Log/AddDevice.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Device"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Registering the logging devices. Normally, it is not necessary to call this function. To enable or disable a logging device,
 | 
				
			||||||
 | 
					please use the configuration database instead. But if you create your own logging device, let say a e-mail logger, then you
 | 
				
			||||||
 | 
					are able to use this function to activate your own logging device. It is save to use this function at any time and it is
 | 
				
			||||||
 | 
					thread-save ;-)
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func AddLoggingDevice(device Device.Device) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newDevice := device
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							mutexDevices.Lock()
 | 
				
			||||||
 | 
							devices.PushBack(newDevice)
 | 
				
			||||||
 | 
							mutexDevices.Unlock()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								Log/Array.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Log/Array.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "container/list"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func logEntryListToArray(data *list.List) (result []Meta.Entry) {
 | 
				
			||||||
 | 
						count := data.Len()
 | 
				
			||||||
 | 
						result = make([]Meta.Entry, count, count)
 | 
				
			||||||
 | 
						position := 0
 | 
				
			||||||
 | 
						for entry := data.Front(); entry != nil; entry = entry.Next() {
 | 
				
			||||||
 | 
							result[position] = entry.Value.(Meta.Entry)
 | 
				
			||||||
 | 
							position++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								Log/Device/Device.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Log/Device/Device.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					package Device
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Device interface {
 | 
				
			||||||
 | 
						Log(logEntries []Meta.Entry)
 | 
				
			||||||
 | 
						Flush()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								Log/Device/Doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								Log/Device/Doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					This is the logging device interface you have to fulfill to be a logging device :)
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package Device
 | 
				
			||||||
							
								
								
									
										7
									
								
								Log/DeviceConsole/ActivateLoggingDevice.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Log/DeviceConsole/ActivateLoggingDevice.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package DeviceConsole
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ActivateLoggingDevice() {
 | 
				
			||||||
 | 
						Log.AddLoggingDevice(Console{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								Log/DeviceConsole/Console.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Log/DeviceConsole/Console.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					package DeviceConsole
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Console struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (dev Console) Log(entries []Meta.Entry) {
 | 
				
			||||||
 | 
						for _, entry := range entries {
 | 
				
			||||||
 | 
							fmt.Println(entry.Format())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (dev Console) Flush() {
 | 
				
			||||||
 | 
						// This is not necessary for a console logger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								Log/DeviceConsole/Doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								Log/DeviceConsole/Doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					This is the console logging device. Any received entry is logged to the console.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package DeviceConsole
 | 
				
			||||||
							
								
								
									
										7
									
								
								Log/DeviceDatabase/ActivateLoggingDevice.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Log/DeviceDatabase/ActivateLoggingDevice.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ActivateLoggingDevice() {
 | 
				
			||||||
 | 
						Log.AddLoggingDevice(Database{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								Log/DeviceDatabase/Doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Log/DeviceDatabase/Doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					This is the database logging device. The logging events will be cached and after a time span or a maximum amount of
 | 
				
			||||||
 | 
					events, the logging entries are written to the database.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
							
								
								
									
										14
									
								
								Log/DeviceDatabase/Flush.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Log/DeviceDatabase/Flush.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (dev Database) Flush() {
 | 
				
			||||||
 | 
						mutexCacheFull.Lock()
 | 
				
			||||||
 | 
						defer mutexCacheFull.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount := len(cache)
 | 
				
			||||||
 | 
						for counter := 0; counter < amount; counter++ {
 | 
				
			||||||
 | 
							write2Database(<-cache)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logDB.Logout()
 | 
				
			||||||
 | 
						logDBSession.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								Log/DeviceDatabase/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Log/DeviceDatabase/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Starting now the database logging.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Starting the database logging done.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initDatabase()
 | 
				
			||||||
 | 
						if value, err := strconv.Atoi(ConfigurationDB.Read(`LogDBCacheSizeNumberOfEvents`)); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityHigh, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `It was not possible to read the LogDBCacheSizeNumberOfEvents configuration.`, `The default value will be used.`, fmt.Sprintf(`Default value is %d.`, cacheSizeNumberOfEvents))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							cacheSizeNumberOfEvents = value
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Configuration LogDBCacheSizeNumberOfEvents was loaded.`, fmt.Sprintf(`The value is %d.`, cacheSizeNumberOfEvents))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if value, err := strconv.Atoi(ConfigurationDB.Read(`LogDBCacheSizeTime2FlushSeconds`)); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityHigh, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `It was not possible to read the LogDBCacheSizeTime2FlushSeconds configuration.`, `The default value will be used.`, fmt.Sprintf(`Default value is %d.`, cacheSizeTime2FlushSeconds))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							cacheSizeTime2FlushSeconds = value
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Configuration LogDBCacheSizeTime2FlushSeconds was loaded.`, fmt.Sprintf(`The value is %d.`, cacheSizeTime2FlushSeconds))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cache = make(chan LogDBEntry, cacheSizeNumberOfEvents)
 | 
				
			||||||
 | 
						initTimeout()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										165
									
								
								Log/DeviceDatabase/InitDB.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								Log/DeviceDatabase/InitDB.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,165 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initDatabase() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Checking and init the logging database collection.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Checking and init the logging database collection done.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						databaseHost := ConfigurationDB.Read(`LogDBHost`)
 | 
				
			||||||
 | 
						databaseDB := ConfigurationDB.Read(`LogDBDatabase`)
 | 
				
			||||||
 | 
						databaseUsername := ConfigurationDB.Read(`LogDBUsername`)
 | 
				
			||||||
 | 
						databasePassword := ConfigurationDB.Read(`LogDBPassword`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 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 {
 | 
				
			||||||
 | 
							logDBSession = newSession
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Use the correct database:
 | 
				
			||||||
 | 
						logDB = logDBSession.DB(databaseDB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Login:
 | 
				
			||||||
 | 
						if errLogin := logDB.Login(databaseUsername, databasePassword); errLogin != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityUnknown, LM.ImpactUnknown, LM.MessageNameDATABASE, `It was not possible to login the user `+databaseUsername, errLogin.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the collection:
 | 
				
			||||||
 | 
						logDBCollection = logDB.C(`Logbook`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Take care about all the indexes:
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						indexTimeUTC := mgo.Index{}
 | 
				
			||||||
 | 
						indexTimeUTC.Key = []string{`TimeUTC`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProject := mgo.Index{}
 | 
				
			||||||
 | 
						indexProject.Key = []string{`Project`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProject)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexSender := mgo.Index{}
 | 
				
			||||||
 | 
						indexSender.Key = []string{`Sender`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexSender)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexCategory := mgo.Index{}
 | 
				
			||||||
 | 
						indexCategory.Key = []string{`Category`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexCategory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexLevel := mgo.Index{}
 | 
				
			||||||
 | 
						indexLevel.Key = []string{`Level`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexLevel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexSeverity := mgo.Index{}
 | 
				
			||||||
 | 
						indexSeverity.Key = []string{`Severity`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexSeverity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexImpact := mgo.Index{}
 | 
				
			||||||
 | 
						indexImpact.Key = []string{`Impact`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexImpact)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexMessageName := mgo.Index{}
 | 
				
			||||||
 | 
						indexMessageName.Key = []string{`MessageName`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexMessageName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexMessageDescription := mgo.Index{}
 | 
				
			||||||
 | 
						indexMessageDescription.Key = []string{`MessageDescription`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexMessageDescription)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTC := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTC.Key = []string{`Project`, `TimeUTC`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectSender := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectSender.Key = []string{`Project`, `Sender`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectSender)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectCategory := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectCategory.Key = []string{`Project`, `Category`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectCategory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectLevel := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectLevel.Key = []string{`Project`, `Level`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectLevel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectSeverity := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectSeverity.Key = []string{`Project`, `Severity`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectSeverity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectImpact := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectImpact.Key = []string{`Project`, `Impact`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectImpact)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectMessageName := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectMessageName.Key = []string{`Project`, `MessageName`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectMessageName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectMessageDescription := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectMessageDescription.Key = []string{`Project`, `MessageDescription`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectMessageDescription)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTCSender := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCSender.Key = []string{`Project`, `TimeUTC`, `Sender`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTCSender)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTCCategory := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCCategory.Key = []string{`Project`, `TimeUTC`, `Category`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTCCategory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTCLevel := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCLevel.Key = []string{`Project`, `TimeUTC`, `Level`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTCLevel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTCSeverity := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCSeverity.Key = []string{`Project`, `TimeUTC`, `Severity`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTCSeverity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTCImpact := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCImpact.Key = []string{`Project`, `TimeUTC`, `Impact`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTCImpact)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTCMessageName := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCMessageName.Key = []string{`Project`, `TimeUTC`, `MessageName`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTCMessageName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexProjectTimeUTCMessageDescription := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCMessageDescription.Key = []string{`Project`, `TimeUTC`, `MessageDescription`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexProjectTimeUTCMessageDescription)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexTimeUTCSender := mgo.Index{}
 | 
				
			||||||
 | 
						indexTimeUTCSender.Key = []string{`TimeUTC`, `Sender`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTCSender)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexTimeUTCCategory := mgo.Index{}
 | 
				
			||||||
 | 
						indexTimeUTCCategory.Key = []string{`TimeUTC`, `Category`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTCCategory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexTimeUTCLevel := mgo.Index{}
 | 
				
			||||||
 | 
						indexTimeUTCLevel.Key = []string{`TimeUTC`, `Level`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTCLevel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexTimeUTCSeverity := mgo.Index{}
 | 
				
			||||||
 | 
						indexTimeUTCSeverity.Key = []string{`TimeUTC`, `Severity`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTCSeverity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexTimeUTCImpact := mgo.Index{}
 | 
				
			||||||
 | 
						indexTimeUTCImpact.Key = []string{`TimeUTC`, `Impact`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTCImpact)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexTimeUTCMessageName := mgo.Index{}
 | 
				
			||||||
 | 
						indexTimeUTCMessageName.Key = []string{`TimeUTC`, `MessageName`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTCMessageName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						indexTimeUTCMessageDescription := mgo.Index{}
 | 
				
			||||||
 | 
						indexProjectTimeUTCMessageDescription.Key = []string{`TimeUTC`, `MessageDescription`}
 | 
				
			||||||
 | 
						logDBCollection.EnsureIndex(indexTimeUTCMessageDescription)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								Log/DeviceDatabase/ReadFromCache.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								Log/DeviceDatabase/ReadFromCache.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Case: The cache is full
 | 
				
			||||||
 | 
					func cacheFull() {
 | 
				
			||||||
 | 
						mutexCacheFull.Lock()
 | 
				
			||||||
 | 
						defer mutexCacheFull.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(cache) < cacheSizeNumberOfEvents {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for counter := 0; counter < cacheSizeNumberOfEvents; counter++ {
 | 
				
			||||||
 | 
							write2Database(<-cache)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Case: Time out
 | 
				
			||||||
 | 
					func initTimeout() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if Shutdown.IsDown() {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								time.Sleep(time.Duration(cacheSizeTime2FlushSeconds) * time.Second)
 | 
				
			||||||
 | 
								mutexCacheFull.Lock()
 | 
				
			||||||
 | 
								amount := len(cache)
 | 
				
			||||||
 | 
								for counter := 0; counter < amount; counter++ {
 | 
				
			||||||
 | 
									write2Database(<-cache)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								mutexCacheFull.Unlock()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								Log/DeviceDatabase/ReceiveLogging.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Log/DeviceDatabase/ReceiveLogging.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Database struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (dev Database) Log(entries []Meta.Entry) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Can not log here to prevent endless loop (consumer is also producer)
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						write2Cache(entries)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								Log/DeviceDatabase/Scheme.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Log/DeviceDatabase/Scheme.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LogDBEntry struct {
 | 
				
			||||||
 | 
						TimeUTC            time.Time `bson:"TimeUTC"`
 | 
				
			||||||
 | 
						Project            string    `bson:"Project"`
 | 
				
			||||||
 | 
						Sender             string    `bson:"Sender"`
 | 
				
			||||||
 | 
						Category           string    `bson:"Category"`
 | 
				
			||||||
 | 
						Level              string    `bson:"Level"`
 | 
				
			||||||
 | 
						Severity           string    `bson:"Severity"`
 | 
				
			||||||
 | 
						Impact             string    `bson:"Impact"`
 | 
				
			||||||
 | 
						MessageName        string    `bson:"MessageName"`
 | 
				
			||||||
 | 
						MessageDescription string    `bson:"MessageDescription"`
 | 
				
			||||||
 | 
						Parameters         []string  `bson:"Parameters"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								Log/DeviceDatabase/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Log/DeviceDatabase/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "sync"
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						senderName                 LM.Sender       = `System::Logger::Database`
 | 
				
			||||||
 | 
						mutexCacheFull             sync.Mutex      = sync.Mutex{}
 | 
				
			||||||
 | 
						cache                      chan LogDBEntry = nil
 | 
				
			||||||
 | 
						cacheSizeNumberOfEvents    int             = 50
 | 
				
			||||||
 | 
						cacheSizeTime2FlushSeconds int             = 6
 | 
				
			||||||
 | 
						logDB                      *mgo.Database   = nil
 | 
				
			||||||
 | 
						logDBSession               *mgo.Session    = nil
 | 
				
			||||||
 | 
						logDBCollection            *mgo.Collection = nil
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										24
									
								
								Log/DeviceDatabase/Write2Cache.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Log/DeviceDatabase/Write2Cache.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func write2Cache(entries []Meta.Entry) {
 | 
				
			||||||
 | 
						for _, entry := range entries {
 | 
				
			||||||
 | 
							if len(cache) == cacheSizeNumberOfEvents {
 | 
				
			||||||
 | 
								go cacheFull()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							logDBentry := LogDBEntry{}
 | 
				
			||||||
 | 
							logDBentry.Category = Meta.FormatCategory(entry.Category)
 | 
				
			||||||
 | 
							logDBentry.Impact = Meta.FormatImpact(entry.Impact)
 | 
				
			||||||
 | 
							logDBentry.Level = Meta.FormatLevel(entry.Level)
 | 
				
			||||||
 | 
							logDBentry.MessageDescription = entry.MessageDescription
 | 
				
			||||||
 | 
							logDBentry.MessageName = string(entry.MessageName)
 | 
				
			||||||
 | 
							logDBentry.Parameters = entry.Parameters
 | 
				
			||||||
 | 
							logDBentry.Project = entry.Project
 | 
				
			||||||
 | 
							logDBentry.Sender = string(entry.Sender)
 | 
				
			||||||
 | 
							logDBentry.Severity = Meta.FormatSeverity(entry.Severity)
 | 
				
			||||||
 | 
							logDBentry.TimeUTC = entry.Time
 | 
				
			||||||
 | 
							cache <- logDBentry
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								Log/DeviceDatabase/Write2Database.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Log/DeviceDatabase/Write2Database.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package DeviceDatabase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func write2Database(entry LogDBEntry) {
 | 
				
			||||||
 | 
						if err := logDBCollection.Insert(entry); err != nil {
 | 
				
			||||||
 | 
							// Can not log here to prevent endless loop (consumer is also producer)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								Log/DeviceDelay.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								Log/DeviceDelay.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Device"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func deviceDelay(newEntry Meta.Entry) {
 | 
				
			||||||
 | 
						defer checkDeviceDelaySize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Insert the new entry at the correct position (time)!
 | 
				
			||||||
 | 
						for logEvent := deviceDelayBuffer.Front(); logEvent != nil; logEvent = logEvent.Next() {
 | 
				
			||||||
 | 
							currentEvent := logEvent.Value.(Meta.Entry)
 | 
				
			||||||
 | 
							if newEntry.Time.Before(currentEvent.Time) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								mutexDeviceDelays.Lock()
 | 
				
			||||||
 | 
								deviceDelayBuffer.InsertBefore(newEntry, logEvent)
 | 
				
			||||||
 | 
								mutexDeviceDelays.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Default: Insert at the back!
 | 
				
			||||||
 | 
						mutexDeviceDelays.Lock()
 | 
				
			||||||
 | 
						deviceDelayBuffer.PushBack(newEntry)
 | 
				
			||||||
 | 
						mutexDeviceDelays.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkDeviceDelaySize() {
 | 
				
			||||||
 | 
						mutexDeviceDelays.Lock()
 | 
				
			||||||
 | 
						if deviceDelayBuffer.Len() >= logDeviceDelayNumberEvents {
 | 
				
			||||||
 | 
							dataArray := logEntryListToArray(deviceDelayBuffer)
 | 
				
			||||||
 | 
							deviceDelayBuffer.Init()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mutexDevices.RLock()
 | 
				
			||||||
 | 
							for entry := devices.Front(); entry != nil; entry = entry.Next() {
 | 
				
			||||||
 | 
								dev := entry.Value.(Device.Device)
 | 
				
			||||||
 | 
								go dev.Log(dataArray)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							mutexDevices.RUnlock()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutexDeviceDelays.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								Log/Flush.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Log/Flush.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Device"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Please do not call this function your self! This function allows Ocean to flush the logging at the shutting down case.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func Flush() {
 | 
				
			||||||
 | 
						mutexChannel.Lock()
 | 
				
			||||||
 | 
						channelReady = false
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutexDeviceDelays.Lock()
 | 
				
			||||||
 | 
						dataArray := logEntryListToArray(deviceDelayBuffer)
 | 
				
			||||||
 | 
						deviceDelayBuffer.Init()
 | 
				
			||||||
 | 
						mutexDeviceDelays.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutexDevices.RLock()
 | 
				
			||||||
 | 
						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()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mutexDevices.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This is a bad design, but the devices need (may) some time to write the last messages:
 | 
				
			||||||
 | 
						time.Sleep(15 * time.Second)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										134
									
								
								Log/Handlers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Log/Handlers.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writeToChannel(logEntry Meta.Entry) {
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						case entriesBuffer <- logEntry:
 | 
				
			||||||
 | 
						case <-time.After(time.Duration(int64(logBufferTimeoutSeconds)) * time.Second):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Warn: Can not log here to prevent endless loop and memory leak!
 | 
				
			||||||
 | 
							fmt.Println(`Warning: Was not able to write to the logging buffer! Message=` + logEntry.Format())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					If, for any reason, you want to deliver a whole log entry to the logging system, then use this function to do so :) Normally,
 | 
				
			||||||
 | 
					just use the LogFull() and LogShort() functions instead ;) There is one reason to use this: If you have to deliver old log
 | 
				
			||||||
 | 
					events you have may imported or you have received a batch of log events of an remote system, etc. Because the LogShort() and
 | 
				
			||||||
 | 
					LogFull() methods are setting the time to the current UTC time. Therefore, TakeEntry() is the only way to provide the time!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func TakeEntry(logEntry Meta.Entry) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logEntry = clearEntry(logEntry)
 | 
				
			||||||
 | 
						mutexChannel.RLock()
 | 
				
			||||||
 | 
						defer mutexChannel.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !channelReady {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mutexPreChannelBuffer.Lock()
 | 
				
			||||||
 | 
							defer mutexPreChannelBuffer.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							preChannelBuffer.PushBack(logEntry)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !preChannelBufferUsed {
 | 
				
			||||||
 | 
							preChannelBufferUsed = true
 | 
				
			||||||
 | 
							mutexPreChannelBuffer.Lock()
 | 
				
			||||||
 | 
							for entry := preChannelBuffer.Front(); entry != nil; entry = entry.Next() {
 | 
				
			||||||
 | 
								writeToChannel(entry.Value.(Meta.Entry))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							preChannelBuffer.Init()
 | 
				
			||||||
 | 
							mutexPreChannelBuffer.Unlock()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writeToChannel(logEntry)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Create and deliver a full log message with all fields and with the current UTC time as logging time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sender		The sender of this message (name of your component, like e.g. "APP::LOGIC::PAYPAL" etc.)
 | 
				
			||||||
 | 
						Category	Use "CategoryBUSINESS" for business events (new payments, etc.), use "CategoryUSER" for log events
 | 
				
			||||||
 | 
								regarding users (e.g. new user registered, etc.) or "CategoryAPP" (for anything else).
 | 
				
			||||||
 | 
						Level 		Choose a logging level.
 | 
				
			||||||
 | 
						Severity	Choose a degree of severity.
 | 
				
			||||||
 | 
						Impact		Choose a degree of impact.
 | 
				
			||||||
 | 
						MessageName	Choose a message name. This is like a common category for this event!
 | 
				
			||||||
 | 
						Description	The logging message you want to deliver.
 | 
				
			||||||
 | 
						Parameters	Provide as many additional parameters (type string) as you need.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func LogFull(sender Meta.Sender, category Meta.Category, level Meta.Level, severity Meta.Severity, impact Meta.Impact, messageName Meta.MessageName, messageDescription string, parameters ...string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry := Meta.Entry{}
 | 
				
			||||||
 | 
						entry.Project = projectName
 | 
				
			||||||
 | 
						entry.Time = time.Now().UTC()
 | 
				
			||||||
 | 
						entry.Category = category
 | 
				
			||||||
 | 
						entry.Level = level
 | 
				
			||||||
 | 
						entry.MessageDescription = messageDescription
 | 
				
			||||||
 | 
						entry.MessageName = messageName
 | 
				
			||||||
 | 
						entry.Parameters = parameters
 | 
				
			||||||
 | 
						entry.Severity = severity
 | 
				
			||||||
 | 
						entry.Impact = impact
 | 
				
			||||||
 | 
						entry.Sender = sender
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TakeEntry(entry)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Create and deliver a short log message with the current UTC time as logging time. The fields severity and impact
 | 
				
			||||||
 | 
					are both set to "none" value. Therefore, this short logging function does not fit for logging problems, errors etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sender		The sender of this message (name of your component, like e.g. "APP::LOGIC::PAYPAL" etc.)
 | 
				
			||||||
 | 
						Category	Use "CategoryBUSINESS" for business events (new payments, etc.), use "CategoryUSER" for log events
 | 
				
			||||||
 | 
								regarding users (e.g. new user registered, etc.) or "CategoryAPP" (for anything else).
 | 
				
			||||||
 | 
						Level 		Choose a logging level.
 | 
				
			||||||
 | 
						MessageName	Choose a message name. This is like a common category for this event!
 | 
				
			||||||
 | 
						Description	The logging message you want to deliver.
 | 
				
			||||||
 | 
						Parameters	Provide as many additional parameters (type string) as you need.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func LogShort(sender Meta.Sender, category Meta.Category, level Meta.Level, messageName Meta.MessageName, messageDescription string, parameters ...string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry := Meta.Entry{}
 | 
				
			||||||
 | 
						entry.Project = projectName
 | 
				
			||||||
 | 
						entry.Time = time.Now().UTC()
 | 
				
			||||||
 | 
						entry.Category = category
 | 
				
			||||||
 | 
						entry.Level = level
 | 
				
			||||||
 | 
						entry.MessageDescription = messageDescription
 | 
				
			||||||
 | 
						entry.MessageName = messageName
 | 
				
			||||||
 | 
						entry.Parameters = parameters
 | 
				
			||||||
 | 
						entry.Severity = Meta.SeverityNone
 | 
				
			||||||
 | 
						entry.Impact = Meta.ImpactNone
 | 
				
			||||||
 | 
						entry.Sender = sender
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TakeEntry(entry)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func clearEntry(entry Meta.Entry) (result Meta.Entry) {
 | 
				
			||||||
 | 
						entry.MessageDescription = removeWhitespaces(entry.MessageDescription)
 | 
				
			||||||
 | 
						entry.Parameters = clearParameters(entry.Parameters)
 | 
				
			||||||
 | 
						result = entry
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func clearParameters(oldParameters []string) (result []string) {
 | 
				
			||||||
 | 
						for n := 0; n < len(oldParameters); n++ {
 | 
				
			||||||
 | 
							oldParameters[n] = removeWhitespaces(oldParameters[n])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = oldParameters
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func removeWhitespaces(text string) (result string) {
 | 
				
			||||||
 | 
						text = strings.Replace(text, "\n", ` `, -1)
 | 
				
			||||||
 | 
						text = strings.Replace(text, "\t", ` `, -1)
 | 
				
			||||||
 | 
						text = strings.Replace(text, "\r", ``, -1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = text
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										52
									
								
								Log/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								Log/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					import "container/list"
 | 
				
			||||||
 | 
					import "sync"
 | 
				
			||||||
 | 
					import "path/filepath"
 | 
				
			||||||
 | 
					import "os"
 | 
				
			||||||
 | 
					import "io/ioutil"
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func readProjectName() {
 | 
				
			||||||
 | 
						if currentDir, dirError := os.Getwd(); dirError != nil {
 | 
				
			||||||
 | 
							panic(`Can not read the current working directory and therefore can not read the project name!`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							filename := filepath.Join(currentDir, `project.name`)
 | 
				
			||||||
 | 
							if _, errFile := os.Stat(filename); errFile != nil {
 | 
				
			||||||
 | 
								if os.IsNotExist(errFile) {
 | 
				
			||||||
 | 
									panic(`Can not read the project name file 'project.name': File not found!`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									panic(`Can not read the project name file 'project.name': ` + errFile.Error())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if projectNameBytes, errRead := ioutil.ReadFile(filename); errRead != nil {
 | 
				
			||||||
 | 
								panic(`Can not read the project name file 'project.name': ` + errRead.Error())
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								projectName = string(projectNameBytes)
 | 
				
			||||||
 | 
								projectName = strings.TrimSpace(projectName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						readProjectName()
 | 
				
			||||||
 | 
						mutexDeviceDelays = sync.Mutex{}
 | 
				
			||||||
 | 
						mutexPreChannelBuffer = sync.Mutex{}
 | 
				
			||||||
 | 
						mutexChannel = sync.RWMutex{}
 | 
				
			||||||
 | 
						preChannelBuffer = list.New()
 | 
				
			||||||
 | 
						deviceDelayBuffer = list.New()
 | 
				
			||||||
 | 
						devices = list.New()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initTimer()
 | 
				
			||||||
 | 
						initCode()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initCode() {
 | 
				
			||||||
 | 
						entriesBuffer = make(chan Meta.Entry, logBufferSize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LogShort(senderName, Meta.CategorySYSTEM, Meta.LevelINFO, `Starting`, `The logger is now starting.`, `logBufferSize=`+strconv.Itoa(int(logBufferSize)), `logBufferTimeoutSeconds=`+strconv.Itoa(int(logBufferTimeoutSeconds)))
 | 
				
			||||||
 | 
						go scheduler(entriesBuffer)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								Log/LoggingIsReady.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Log/LoggingIsReady.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is used just internal by Ocean. Please do not call this function by your self!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func LoggingIsReady() {
 | 
				
			||||||
 | 
						channelReady = true
 | 
				
			||||||
 | 
						preChannelBufferUsed = false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								Log/Meta/Category.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Log/Meta/Category.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Category byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						CategoryBUSINESS = Category(iota)
 | 
				
			||||||
 | 
						CategorySYSTEM   = Category(iota)
 | 
				
			||||||
 | 
						CategoryAPP      = Category(iota)
 | 
				
			||||||
 | 
						CategoryUSER     = Category(iota)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FormatCategory(cat Category) (result string) {
 | 
				
			||||||
 | 
						switch cat {
 | 
				
			||||||
 | 
						case CategoryBUSINESS:
 | 
				
			||||||
 | 
							result = `C:BUSINESS`
 | 
				
			||||||
 | 
						case CategoryAPP:
 | 
				
			||||||
 | 
							result = `C:APP`
 | 
				
			||||||
 | 
						case CategorySYSTEM:
 | 
				
			||||||
 | 
							result = `C:SYSTEM`
 | 
				
			||||||
 | 
						case CategoryUSER:
 | 
				
			||||||
 | 
							result = `C:USER`
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							result = `C:N/A`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								Log/Meta/Entry.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Log/Meta/Entry.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Entry struct {
 | 
				
			||||||
 | 
						Project            string
 | 
				
			||||||
 | 
						Time               time.Time
 | 
				
			||||||
 | 
						Sender             Sender
 | 
				
			||||||
 | 
						Category           Category
 | 
				
			||||||
 | 
						Level              Level
 | 
				
			||||||
 | 
						Severity           Severity
 | 
				
			||||||
 | 
						Impact             Impact
 | 
				
			||||||
 | 
						MessageName        MessageName
 | 
				
			||||||
 | 
						MessageDescription string
 | 
				
			||||||
 | 
						Parameters         []string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										96
									
								
								Log/Meta/Format.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								Log/Meta/Format.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (entry Entry) Format() (result string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lenSender := len(entry.Sender)
 | 
				
			||||||
 | 
						if lenSender > 40 {
 | 
				
			||||||
 | 
							lenSender = 40
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lenMessageName := len(entry.MessageName)
 | 
				
			||||||
 | 
						if lenMessageName > 26 {
 | 
				
			||||||
 | 
							lenMessageName = 26
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lenProject := len(entry.Project)
 | 
				
			||||||
 | 
						if lenProject > 10 {
 | 
				
			||||||
 | 
							lenProject = 10
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						messageDescription := entry.MessageDescription
 | 
				
			||||||
 | 
						messageDescription = strings.Replace(messageDescription, `\n`, ` `, -1)
 | 
				
			||||||
 | 
						messageDescription = strings.Replace(messageDescription, `\t`, ` `, -1)
 | 
				
			||||||
 | 
						messageDescription = strings.Replace(messageDescription, `\r`, ` `, -1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = fmt.Sprintf(` [■] P:%10s [■] %s [■] %10s [■] %11s [■] %10s [■] %10s [■] sender: %-40s [■] name: %-26s [■] %s [■]`, entry.Project[:lenProject], formatTime(entry.Time), FormatCategory(entry.Category), FormatLevel(entry.Level), FormatSeverity(entry.Severity), FormatImpact(entry.Impact), entry.Sender[:lenSender], entry.MessageName[:lenMessageName], messageDescription)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, param := range entry.Parameters {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							paramText := param
 | 
				
			||||||
 | 
							paramText = strings.Replace(paramText, `\n`, ` `, -1)
 | 
				
			||||||
 | 
							paramText = strings.Replace(paramText, `\t`, ` `, -1)
 | 
				
			||||||
 | 
							paramText = strings.Replace(paramText, `\r`, ` `, -1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							result = fmt.Sprintf(`%s %s [■]`, result, paramText)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								Log/Meta/Impact.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Log/Meta/Impact.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Impact byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ImpactNone     = Impact(iota)
 | 
				
			||||||
 | 
						ImpactLow      = Impact(iota)
 | 
				
			||||||
 | 
						ImpactMiddle   = Impact(iota)
 | 
				
			||||||
 | 
						ImpactHigh     = Impact(iota)
 | 
				
			||||||
 | 
						ImpactCritical = Impact(iota)
 | 
				
			||||||
 | 
						ImpactUnknown  = Impact(iota)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FormatImpact(pri Impact) (result string) {
 | 
				
			||||||
 | 
						switch pri {
 | 
				
			||||||
 | 
						case ImpactCritical:
 | 
				
			||||||
 | 
							result = `I:CRITICAL`
 | 
				
			||||||
 | 
						case ImpactHigh:
 | 
				
			||||||
 | 
							result = `I:HIGH`
 | 
				
			||||||
 | 
						case ImpactLow:
 | 
				
			||||||
 | 
							result = `I:LOW`
 | 
				
			||||||
 | 
						case ImpactMiddle:
 | 
				
			||||||
 | 
							result = `I:MIDDLE`
 | 
				
			||||||
 | 
						case ImpactNone:
 | 
				
			||||||
 | 
							result = `I:NONE`
 | 
				
			||||||
 | 
						case ImpactUnknown:
 | 
				
			||||||
 | 
							result = `I:UNKNOWN`
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							result = `I:N/A`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								Log/Meta/Level.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Log/Meta/Level.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Level byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						LevelWARN      = Level(iota)
 | 
				
			||||||
 | 
						LevelDEBUG     = Level(iota)
 | 
				
			||||||
 | 
						LevelERROR     = Level(iota)
 | 
				
			||||||
 | 
						LevelINFO      = Level(iota)
 | 
				
			||||||
 | 
						LevelTALKATIVE = Level(iota)
 | 
				
			||||||
 | 
						LevelSECURITY  = Level(iota)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FormatLevel(lvl Level) (result string) {
 | 
				
			||||||
 | 
						switch lvl {
 | 
				
			||||||
 | 
						case LevelDEBUG:
 | 
				
			||||||
 | 
							result = `L:DEBUG`
 | 
				
			||||||
 | 
						case LevelERROR:
 | 
				
			||||||
 | 
							result = `L:ERROR`
 | 
				
			||||||
 | 
						case LevelINFO:
 | 
				
			||||||
 | 
							result = `L:INFO`
 | 
				
			||||||
 | 
						case LevelSECURITY:
 | 
				
			||||||
 | 
							result = `L:SECURITY`
 | 
				
			||||||
 | 
						case LevelTALKATIVE:
 | 
				
			||||||
 | 
							result = `L:TALKATIVE`
 | 
				
			||||||
 | 
						case LevelWARN:
 | 
				
			||||||
 | 
							result = `L:WARN`
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							result = `L:N/A`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								Log/Meta/MessageNames.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Log/Meta/MessageNames.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MessageName string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						MessageNameSTARTUP       = `Startup`
 | 
				
			||||||
 | 
						MessageNameINIT          = `Init`
 | 
				
			||||||
 | 
						MessageNameSHUTDOWN      = `Shutdown`
 | 
				
			||||||
 | 
						MessageNameEXECUTE       = `Execute`
 | 
				
			||||||
 | 
						MessageNameDATABASE      = `Database`
 | 
				
			||||||
 | 
						MessageNameNETWORK       = `Network`
 | 
				
			||||||
 | 
						MessageNameLOGIN         = `Login`
 | 
				
			||||||
 | 
						MessageNameLOGOUT        = `Logout`
 | 
				
			||||||
 | 
						MessageNameSESSION       = `Session`
 | 
				
			||||||
 | 
						MessageNameTIMEOUT       = `Timeout`
 | 
				
			||||||
 | 
						MessageNameFILESYSTEM    = `Filesystem`
 | 
				
			||||||
 | 
						MessageNameCOMMUNICATION = `Communication`
 | 
				
			||||||
 | 
						MessageNameWRITE         = `Write`
 | 
				
			||||||
 | 
						MessageNameREAD          = `Read`
 | 
				
			||||||
 | 
						MessageNameALGORITHM     = `Algorithm`
 | 
				
			||||||
 | 
						MessageNameCONFIGURATION = `Configuration`
 | 
				
			||||||
 | 
						MessageNameTIMER         = `Timer`
 | 
				
			||||||
 | 
						MessageNameINPUT         = `Input`
 | 
				
			||||||
 | 
						MessageNameOUTPUT        = `Output`
 | 
				
			||||||
 | 
						MessageNameBROWSER       = `Browser`
 | 
				
			||||||
 | 
						MessageNameSECURITY      = `Security`
 | 
				
			||||||
 | 
						MessageNameNOTFOUND      = `NotFound`
 | 
				
			||||||
 | 
						MessageNameANALYSIS      = `Analysis`
 | 
				
			||||||
 | 
						MessageNameSTATE         = `State`
 | 
				
			||||||
 | 
						MessageNameGENERATOR     = `Generator`
 | 
				
			||||||
 | 
						MessageNamePRODUCER      = `Producer`
 | 
				
			||||||
 | 
						MessageNameCONSUMER      = `Consumer`
 | 
				
			||||||
 | 
						MessageNamePASSWORD      = `Password`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										3
									
								
								Log/Meta/Sender.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Log/Meta/Sender.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Sender string
 | 
				
			||||||
							
								
								
									
										33
									
								
								Log/Meta/Severity.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Log/Meta/Severity.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					package Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Severity byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						SeverityNone     = Severity(iota)
 | 
				
			||||||
 | 
						SeverityLow      = Severity(iota)
 | 
				
			||||||
 | 
						SeverityMiddle   = Severity(iota)
 | 
				
			||||||
 | 
						SeverityHigh     = Severity(iota)
 | 
				
			||||||
 | 
						SeverityCritical = Severity(iota)
 | 
				
			||||||
 | 
						SeverityUnknown  = Severity(iota)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FormatSeverity(pri Severity) (result string) {
 | 
				
			||||||
 | 
						switch pri {
 | 
				
			||||||
 | 
						case SeverityCritical:
 | 
				
			||||||
 | 
							result = `S:CRITICAL`
 | 
				
			||||||
 | 
						case SeverityHigh:
 | 
				
			||||||
 | 
							result = `S:HIGH`
 | 
				
			||||||
 | 
						case SeverityLow:
 | 
				
			||||||
 | 
							result = `S:LOW`
 | 
				
			||||||
 | 
						case SeverityMiddle:
 | 
				
			||||||
 | 
							result = `S:MIDDLE`
 | 
				
			||||||
 | 
						case SeverityNone:
 | 
				
			||||||
 | 
							result = `S:NONE`
 | 
				
			||||||
 | 
						case SeverityUnknown:
 | 
				
			||||||
 | 
							result = `S:UNKNOWN`
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							result = `S:N/A`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								Log/Scheduler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Log/Scheduler.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Note: The scheduler is the consumer for the logging channel!
 | 
				
			||||||
 | 
					func scheduler(logBuffer chan Meta.Entry) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LogShort(senderName, Meta.CategorySYSTEM, Meta.LevelINFO, Meta.MessageNameSTARTUP, `The scheduler runs now.`)
 | 
				
			||||||
 | 
						var stopNextTime = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							if stopNextTime {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nextEntry, ok := <-logBuffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								// The channel was closed!
 | 
				
			||||||
 | 
								stopNextTime = true
 | 
				
			||||||
 | 
								nextEntry = Meta.Entry{}
 | 
				
			||||||
 | 
								nextEntry.Project = projectName
 | 
				
			||||||
 | 
								nextEntry.Time = time.Now().UTC()
 | 
				
			||||||
 | 
								nextEntry.Sender = senderName
 | 
				
			||||||
 | 
								nextEntry.Category = Meta.CategorySYSTEM
 | 
				
			||||||
 | 
								nextEntry.Level = Meta.LevelWARN
 | 
				
			||||||
 | 
								nextEntry.Severity = Meta.SeverityCritical
 | 
				
			||||||
 | 
								nextEntry.Impact = Meta.ImpactNone
 | 
				
			||||||
 | 
								nextEntry.MessageName = Meta.MessageNameCOMMUNICATION
 | 
				
			||||||
 | 
								nextEntry.MessageDescription = `The logging channel was closed!`
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							deviceDelay(nextEntry)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LogFull(senderName, Meta.CategorySYSTEM, Meta.LevelWARN, Meta.SeverityCritical, Meta.ImpactNone, Meta.MessageNameSHUTDOWN, `The scheduler is down now.`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								Log/SetConfiguration.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								Log/SetConfiguration.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is used just internal by Ocean to change some configuration afterwards, after the first runtime stage
 | 
				
			||||||
 | 
					(transition from not configured state in to the desired configurated stage, after the configuration database is ready).
 | 
				
			||||||
 | 
					Please do not call this function by your self!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func SetBufferSize(bufferSize int) {
 | 
				
			||||||
 | 
						logBufferSize = bufferSize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is used just internal by Ocean to change some configuration afterwards, after the first runtime stage
 | 
				
			||||||
 | 
					(transition from not configured state in to the desired configurated stage, after the configuration database is ready).
 | 
				
			||||||
 | 
					Please do not call this function by your self!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func SetTimeoutSeconds(timeoutSeconds int) {
 | 
				
			||||||
 | 
						logBufferTimeoutSeconds = timeoutSeconds
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is used just internal by Ocean to change some configuration afterwards, after the first runtime stage
 | 
				
			||||||
 | 
					(transition from not configured state in to the desired configurated stage, after the configuration database is ready).
 | 
				
			||||||
 | 
					Please do not call this function by your self!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func SetDeviceDelayNumberEvents(numberEvents int) {
 | 
				
			||||||
 | 
						logDeviceDelayNumberEvents = numberEvents
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is used just internal by Ocean to change some configuration afterwards, after the first runtime stage
 | 
				
			||||||
 | 
					(transition from not configured state in to the desired configurated stage, after the configuration database is ready).
 | 
				
			||||||
 | 
					Please do not call this function by your self!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func SetDeviceDelayTimeoutSeconds(seconds int) {
 | 
				
			||||||
 | 
						logDeviceDelayTimeoutSeconds = seconds
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is used just internal by Ocean to change some configuration afterwards, after the first runtime stage
 | 
				
			||||||
 | 
					(transition from not configured state in to the desired configurated stage, after the configuration database is ready).
 | 
				
			||||||
 | 
					Please do not call this function by your self!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func SetProjectName(project string) {
 | 
				
			||||||
 | 
						projectName = project
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This function is used just internal by Ocean to change some configuration afterwards, after the first runtime stage
 | 
				
			||||||
 | 
					(transition from not configured state in to the desired configurated stage, after the configuration database is ready).
 | 
				
			||||||
 | 
					Please do not call this function by your self!
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func ApplyConfigurationChanges() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutexChannel.Lock()
 | 
				
			||||||
 | 
						channelReady = false
 | 
				
			||||||
 | 
						close(entriesBuffer)
 | 
				
			||||||
 | 
						mutexChannel.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initCode()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								Log/Timer.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Log/Timer.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Device"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initTimer() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if timerIsRunning == true {
 | 
				
			||||||
 | 
							LogFull(senderName, Meta.CategorySYSTEM, Meta.LevelWARN, Meta.SeverityHigh, Meta.ImpactNone, Meta.MessageNameSTARTUP, `The logging timer is already running.`)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timerIsRunning = true
 | 
				
			||||||
 | 
						LogShort(senderName, Meta.CategorySYSTEM, Meta.LevelINFO, Meta.MessageNameSTARTUP, `Create the logging timer now.`, fmt.Sprintf(`Timeout=%d seconds`, logDeviceDelayTimeoutSeconds))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								time.Sleep(time.Duration(logDeviceDelayTimeoutSeconds) * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								mutexDeviceDelays.Lock()
 | 
				
			||||||
 | 
								dataArray := logEntryListToArray(deviceDelayBuffer)
 | 
				
			||||||
 | 
								deviceDelayBuffer.Init()
 | 
				
			||||||
 | 
								mutexDeviceDelays.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								mutexDevices.RLock()
 | 
				
			||||||
 | 
								for entry := devices.Front(); entry != nil; entry = entry.Next() {
 | 
				
			||||||
 | 
									dev := entry.Value.(Device.Device)
 | 
				
			||||||
 | 
									go dev.Log(dataArray)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								mutexDevices.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								Log/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Log/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					package Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					import "container/list"
 | 
				
			||||||
 | 
					import "sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						entriesBuffer                chan Meta.Entry = nil
 | 
				
			||||||
 | 
						logBufferSize                int             = 500
 | 
				
			||||||
 | 
						logBufferTimeoutSeconds      int             = 4
 | 
				
			||||||
 | 
						logDeviceDelayNumberEvents   int             = 600
 | 
				
			||||||
 | 
						logDeviceDelayTimeoutSeconds int             = 5
 | 
				
			||||||
 | 
						channelReady                 bool            = false
 | 
				
			||||||
 | 
						preChannelBufferUsed         bool            = false
 | 
				
			||||||
 | 
						preChannelBuffer             *list.List      = nil
 | 
				
			||||||
 | 
						deviceDelayBuffer            *list.List      = nil
 | 
				
			||||||
 | 
						devices                      *list.List      = nil
 | 
				
			||||||
 | 
						mutexDeviceDelays            sync.Mutex      = sync.Mutex{}
 | 
				
			||||||
 | 
						mutexPreChannelBuffer        sync.Mutex      = sync.Mutex{}
 | 
				
			||||||
 | 
						mutexChannel                 sync.RWMutex    = sync.RWMutex{}
 | 
				
			||||||
 | 
						mutexDevices                 sync.RWMutex    = sync.RWMutex{}
 | 
				
			||||||
 | 
						timerIsRunning               bool            = false
 | 
				
			||||||
 | 
						projectName                  string          = `not set`
 | 
				
			||||||
 | 
						senderName                   Meta.Sender     = `System::Log`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										38
									
								
								MimeTypes/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								MimeTypes/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					package MimeTypes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var allTypes [32]MimeType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						allTypes[0] = TypeWebHTML
 | 
				
			||||||
 | 
						allTypes[1] = TypeWebCSS
 | 
				
			||||||
 | 
						allTypes[2] = TypeWebJavaScript
 | 
				
			||||||
 | 
						allTypes[3] = TypeXML
 | 
				
			||||||
 | 
						allTypes[4] = TypeArchiveZIP
 | 
				
			||||||
 | 
						allTypes[5] = TypeArchiveGZ
 | 
				
			||||||
 | 
						allTypes[6] = TypeWebOCTET
 | 
				
			||||||
 | 
						allTypes[7] = TypeDocumentPDF
 | 
				
			||||||
 | 
						allTypes[8] = TypeDocumentLaTeX
 | 
				
			||||||
 | 
						allTypes[9] = TypeShockwave
 | 
				
			||||||
 | 
						allTypes[10] = TypeArchiveTAR
 | 
				
			||||||
 | 
						allTypes[11] = TypeAudioWAV
 | 
				
			||||||
 | 
						allTypes[12] = TypeAudioMP3
 | 
				
			||||||
 | 
						allTypes[13] = TypeAudioAAC
 | 
				
			||||||
 | 
						allTypes[14] = TypeAudioOGG
 | 
				
			||||||
 | 
						allTypes[15] = TypeAudioWMA
 | 
				
			||||||
 | 
						allTypes[16] = TypeImageGIF
 | 
				
			||||||
 | 
						allTypes[17] = TypeImageCommon
 | 
				
			||||||
 | 
						allTypes[18] = TypeUnknown
 | 
				
			||||||
 | 
						allTypes[19] = TypeImageJPEG
 | 
				
			||||||
 | 
						allTypes[20] = TypeImagePNG
 | 
				
			||||||
 | 
						allTypes[21] = TypePlainText
 | 
				
			||||||
 | 
						allTypes[22] = TypeVideoMPEG
 | 
				
			||||||
 | 
						allTypes[23] = TypeVideoMOV
 | 
				
			||||||
 | 
						allTypes[24] = TypeVideoAVI
 | 
				
			||||||
 | 
						allTypes[25] = TypeVideoMP4
 | 
				
			||||||
 | 
						allTypes[26] = TypeFontEOT
 | 
				
			||||||
 | 
						allTypes[27] = TypeFontOTF
 | 
				
			||||||
 | 
						allTypes[28] = TypeImageSVG
 | 
				
			||||||
 | 
						allTypes[29] = TypeFontTTF
 | 
				
			||||||
 | 
						allTypes[30] = TypeFontWOFF
 | 
				
			||||||
 | 
						allTypes[31] = TypeWebJSON
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								MimeTypes/KnownTypes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								MimeTypes/KnownTypes.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					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 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"}}
 | 
				
			||||||
 | 
					var TypeWebOCTET = MimeType{MimeType: "application/octet-stream", FileExtension: []string{".bin", ".exe", ".dll", ".class"}}
 | 
				
			||||||
 | 
					var TypeDocumentPDF = MimeType{MimeType: "application/pdf", FileExtension: []string{".pdf"}}
 | 
				
			||||||
 | 
					var TypeDocumentLaTeX = MimeType{MimeType: "application/x-latex", FileExtension: []string{".tex", ".latex"}}
 | 
				
			||||||
 | 
					var TypeShockwave = MimeType{MimeType: "application/x-shockwave-flash", FileExtension: []string{".swf"}}
 | 
				
			||||||
 | 
					var TypeArchiveTAR = MimeType{MimeType: "application/x-tar", FileExtension: []string{".tar"}}
 | 
				
			||||||
 | 
					var TypeAudioWAV = MimeType{MimeType: "application/x-wav", FileExtension: []string{".wav"}}
 | 
				
			||||||
 | 
					var TypeAudioMP3 = MimeType{MimeType: "audio/mpeg", FileExtension: []string{".mp3"}}
 | 
				
			||||||
 | 
					var TypeAudioAAC = MimeType{MimeType: "audio/aac", FileExtension: []string{".aac", ".m4a"}}
 | 
				
			||||||
 | 
					var TypeAudioOGG = MimeType{MimeType: "audio/ogg", FileExtension: []string{"vogg", ".oga"}}
 | 
				
			||||||
 | 
					var TypeAudioWMA = MimeType{MimeType: "audio/x-ms-wma", FileExtension: []string{".wma"}}
 | 
				
			||||||
 | 
					var TypeImageGIF = MimeType{MimeType: "image/gif", FileExtension: []string{".gif"}}
 | 
				
			||||||
 | 
					var TypeImageCommon = MimeType{MimeType: "image", FileExtension: []string{}}
 | 
				
			||||||
 | 
					var TypeUnknown = MimeType{MimeType: "application/octet-stream", FileExtension: []string{}}
 | 
				
			||||||
 | 
					var TypeImageJPEG = MimeType{MimeType: "image/jpeg", FileExtension: []string{".jpg", ".jpeg"}}
 | 
				
			||||||
 | 
					var TypeImagePNG = MimeType{MimeType: "image/png", FileExtension: []string{".png"}}
 | 
				
			||||||
 | 
					var TypePlainText = MimeType{MimeType: "text/plain", FileExtension: []string{".txt"}}
 | 
				
			||||||
 | 
					var TypeVideoMPEG = MimeType{MimeType: "video/mpeg", FileExtension: []string{".mpeg", ".mpg"}}
 | 
				
			||||||
 | 
					var TypeVideoMOV = MimeType{MimeType: "video/quicktime", FileExtension: []string{".mov", ".qt"}}
 | 
				
			||||||
 | 
					var TypeVideoAVI = MimeType{MimeType: "video/x-msvideo", FileExtension: []string{".avi"}}
 | 
				
			||||||
 | 
					var TypeVideoMP4 = MimeType{MimeType: "video/mp4", FileExtension: []string{".mp4"}}
 | 
				
			||||||
 | 
					var TypeFontEOT = MimeType{MimeType: "application/vnd.ms-fontobject", FileExtension: []string{".eot"}}
 | 
				
			||||||
 | 
					var TypeFontOTF = MimeType{MimeType: "application/font-sfnt", FileExtension: []string{".otf"}}
 | 
				
			||||||
 | 
					var TypeImageSVG = MimeType{MimeType: "image/svg+xml", FileExtension: []string{".svg"}}
 | 
				
			||||||
 | 
					var TypeFontTTF = MimeType{MimeType: "application/font-sfnt", FileExtension: []string{".ttf"}}
 | 
				
			||||||
 | 
					var TypeFontWOFF = MimeType{MimeType: "application/font-woff", FileExtension: []string{".woff"}}
 | 
				
			||||||
 | 
					var TypeWebJSON = MimeType{MimeType: "application/json", FileExtension: []string{".json"}}
 | 
				
			||||||
							
								
								
									
										22
									
								
								MimeTypes/MimeTypes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								MimeTypes/MimeTypes.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					package MimeTypes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MimeType struct {
 | 
				
			||||||
 | 
						MimeType      string
 | 
				
			||||||
 | 
						FileExtension []string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DetectType(filename string) (mime MimeType, err error) {
 | 
				
			||||||
 | 
						for _, typeElement := range allTypes {
 | 
				
			||||||
 | 
							for _, extension := range typeElement.FileExtension {
 | 
				
			||||||
 | 
								if strings.HasSuffix(filename, extension) {
 | 
				
			||||||
 | 
									mime = typeElement
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mime = TypeUnknown
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								MimeTypes/Write2HTTP.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								MimeTypes/Write2HTTP.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package MimeTypes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Write2HTTP(response http.ResponseWriter, mime MimeType) {
 | 
				
			||||||
 | 
						response.Header().Add(`Content-Type`, mime.MimeType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								NumGen/BadNumber.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								NumGen/BadNumber.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BadNumber() (result int64) {
 | 
				
			||||||
 | 
						result = badNumber64
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								NumGen/GetNumber.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								NumGen/GetNumber.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "net/url"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetNextInt64(name string) (result int64) {
 | 
				
			||||||
 | 
						result = badNumber64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if Shutdown.IsDown() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if responseData, errRequest := http.PostForm(getHandler, url.Values{"name": {name}, "password": {correctPassword}}); errRequest != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameGENERATOR, `Requesting the next number was not possible.`, errRequest.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							nextNumberText := responseData.Header.Get(`nextNumber`)
 | 
				
			||||||
 | 
							if number, errAtio := strconv.Atoi(nextNumberText); errAtio != nil {
 | 
				
			||||||
 | 
								Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameGENERATOR, `It was not possible to convert the answer into an int64.`, errAtio.Error())
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								result = int64(number)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								NumGen/HandlerGetNext.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								NumGen/HandlerGetNext.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func HandlerGetNext(response http.ResponseWriter, request *http.Request) {
 | 
				
			||||||
 | 
						if Shutdown.IsDown() {
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !isActive {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactNone, LM.MessageNameCONFIGURATION, `Called the get handler on an inactive host.`, `Wrong configuration?`)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if correctPassword == `` {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSECURITY, `No communication password was set.`)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						name := request.FormValue(`name`)
 | 
				
			||||||
 | 
						pwd := request.FormValue(`password`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if pwd != correctPassword {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityCritical, LM.ImpactNone, LM.MessageNamePASSWORD, `A wrong password was used to access this system handler.`, `This should never happens: Is this a hacking attempt?`, `IP address of requester=`+request.RemoteAddr)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelDEBUG, LM.MessageNameANALYSIS, `Next number requested.`, name, pwd)
 | 
				
			||||||
 | 
						channel := requestChannel4Name(name)
 | 
				
			||||||
 | 
						nextNumber := <-channel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						response.Header().Add(`nextNumber`, fmt.Sprintf(`%d`, nextNumber))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								NumGen/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								NumGen/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Init the number generator.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						channelListLock.Lock()
 | 
				
			||||||
 | 
						defer channelListLock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						correctPassword = ConfigurationDB.Read(`InternalCommPassword`)
 | 
				
			||||||
 | 
						activeHost := ConfigurationDB.Read(`NumGenActiveHosts`)
 | 
				
			||||||
 | 
						isActive = strings.Contains(activeHost, Tools.ThisHostname())
 | 
				
			||||||
 | 
						getHandler = ConfigurationDB.Read(`NumGenGetHandler`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if isActive {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.MessageNameCONFIGURATION, `The number generator is active on this host.`, `This host is producer and consumer.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							channelBufferSizeText := ConfigurationDB.Read(`NumGenBufferSize`)
 | 
				
			||||||
 | 
							if bufferSizeNumber, errBufferSizeNumber := strconv.Atoi(channelBufferSizeText); errBufferSizeNumber != nil {
 | 
				
			||||||
 | 
								Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactMiddle, LM.MessageNameCONFIGURATION, `Was not able to parse the configuration value of NumGenBufferSize.`, errBufferSizeNumber.Error(), `Use the default value now!`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								channelBufferSize = bufferSizeNumber
 | 
				
			||||||
 | 
								Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `The buffer size for the number generator was loaded.`, `Buffer size=`+channelBufferSizeText)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							channelList = make(map[string]chan int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							initDB()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.MessageNameCONFIGURATION, `The number generator is not active on this host.`, `This host is just a consumer.`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								NumGen/InitDB.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								NumGen/InitDB.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/CustomerDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initDB() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Start init of number generator collection.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Done init of number generator collection.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the database:
 | 
				
			||||||
 | 
						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.`)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get my collection:
 | 
				
			||||||
 | 
						collectionNumGen = db.C(`NumGen`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Take care about the indexes:
 | 
				
			||||||
 | 
						indexName := mgo.Index{}
 | 
				
			||||||
 | 
						indexName.Key = []string{`Name`}
 | 
				
			||||||
 | 
						indexName.Unique = true
 | 
				
			||||||
 | 
						collectionNumGen.EnsureIndex(indexName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										68
									
								
								NumGen/Producer.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								NumGen/Producer.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo/bson"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func producer(name string) {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The NumGen producer is now starting.`, `name=`+name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get my channel:
 | 
				
			||||||
 | 
						myChannel := requestChannel4Name(name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read my next free number:
 | 
				
			||||||
 | 
						currentNextFreeNumber := nextFreeNumberFromDatabase(name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Where is the next "reload"?
 | 
				
			||||||
 | 
						nextReload := currentNextFreeNumber + int64(channelBufferSize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set the next free number to the database:
 | 
				
			||||||
 | 
						updateNextFreeNumber2Database(name, nextReload)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The NumGen producer is now running.`, `name=`+name)
 | 
				
			||||||
 | 
						for nextNumber := currentNextFreeNumber; true; {
 | 
				
			||||||
 | 
							if Shutdown.IsDown() {
 | 
				
			||||||
 | 
								Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSHUTDOWN, `The NumGen producer is now down.`, `name=`+name)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if nextNumber > nextReload {
 | 
				
			||||||
 | 
								nextReload = nextReload + int64(channelBufferSize)
 | 
				
			||||||
 | 
								updateNextFreeNumber2Database(name, nextReload)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Enables the administrator to monitor the frequence of chunks and is able to reconfigure the settings:
 | 
				
			||||||
 | 
								Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelDEBUG, LM.MessageNamePRODUCER, `The NumGen producer creates the next chunk.`, `name=`+name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Enqueue the next number:
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case myChannel <- nextNumber:
 | 
				
			||||||
 | 
								nextNumber++
 | 
				
			||||||
 | 
							case <-time.After(time.Millisecond * 500):
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nextFreeNumberFromDatabase(name string) (result int64) {
 | 
				
			||||||
 | 
						selection := bson.D{{`Name`, name}}
 | 
				
			||||||
 | 
						searchResult := NumberGenScheme{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, _ := collectionNumGen.Find(selection).Count()
 | 
				
			||||||
 | 
						if count == 1 {
 | 
				
			||||||
 | 
							collectionNumGen.Find(selection).One(&searchResult)
 | 
				
			||||||
 | 
							result = searchResult.NextFreeNumber
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							searchResult.Name = name
 | 
				
			||||||
 | 
							searchResult.NextFreeNumber = startValue64
 | 
				
			||||||
 | 
							collectionNumGen.Insert(searchResult)
 | 
				
			||||||
 | 
							result = searchResult.NextFreeNumber
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func updateNextFreeNumber2Database(name string, nextFreeNumber int64) {
 | 
				
			||||||
 | 
						selection := bson.D{{`Name`, name}}
 | 
				
			||||||
 | 
						collectionNumGen.Update(selection, NumberGenScheme{Name: name, NextFreeNumber: nextFreeNumber})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								NumGen/RequestChannel.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								NumGen/RequestChannel.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func requestChannel4Name(name string) (result chan int64) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if Shutdown.IsDown() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !isActive {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactNone, LM.MessageNameCONFIGURATION, `Called the requestChannel4Name() on an inactive host.`, `Wrong configuration?`)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						channelListLock.RLock()
 | 
				
			||||||
 | 
						channel, isPresent := channelList[name]
 | 
				
			||||||
 | 
						channelListLock.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if isPresent {
 | 
				
			||||||
 | 
							result = channel
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create the entry:
 | 
				
			||||||
 | 
						newChannel := make(chan int64, channelBufferSize)
 | 
				
			||||||
 | 
						result = newChannel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						channelListLock.Lock()
 | 
				
			||||||
 | 
						channelList[name] = newChannel
 | 
				
			||||||
 | 
						channelListLock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create the new producer:
 | 
				
			||||||
 | 
						go producer(name)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								NumGen/Scheme.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								NumGen/Scheme.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type NumberGenScheme struct {
 | 
				
			||||||
 | 
						Name           string `bson:"Name"`
 | 
				
			||||||
 | 
						NextFreeNumber int64  `bson:"NextFreeNumber"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								NumGen/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								NumGen/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ShutdownFunction struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a ShutdownFunction) Shutdown() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategoryAPP, LM.LevelWARN, LM.MessageNameSHUTDOWN, `Shutting down the number generator.`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								NumGen/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								NumGen/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					package NumGen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "sync"
 | 
				
			||||||
 | 
					import "labix.org/v2/mgo"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						correctPassword   string                = ``
 | 
				
			||||||
 | 
						senderName        LM.Sender             = `System::NumGen::Producer`
 | 
				
			||||||
 | 
						isActive          bool                  = false
 | 
				
			||||||
 | 
						getHandler        string                = ``
 | 
				
			||||||
 | 
						db                *mgo.Database         = nil
 | 
				
			||||||
 | 
						collectionNumGen  *mgo.Collection       = nil
 | 
				
			||||||
 | 
						channelBufferSize int                   = 10
 | 
				
			||||||
 | 
						channelList       map[string]chan int64 = nil
 | 
				
			||||||
 | 
						channelListLock   sync.RWMutex          = sync.RWMutex{}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						badNumber64  int64 = 9222222222222222222
 | 
				
			||||||
 | 
						startValue64 int64 = -9223372036854775808
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										17
									
								
								Robots/Handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Robots/Handler.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					package Robots
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func HandlerRobots(response http.ResponseWriter, request *http.Request) {
 | 
				
			||||||
 | 
						if Shutdown.IsDown() {
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameNETWORK, `The robots.txt was requested.`, request.RemoteAddr)
 | 
				
			||||||
 | 
						fmt.Fprintf(response, `%s`, robotsContent)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								Robots/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Robots/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					package Robots
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Init the robots component.`)
 | 
				
			||||||
 | 
						robotsContent = ConfigurationDB.Read(`robots.txt`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								Robots/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Robots/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package Robots
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						senderName    LM.Sender = `System::Robots`
 | 
				
			||||||
 | 
						robotsContent string    = `User-agent: *
 | 
				
			||||||
 | 
					Disallow: /`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										6
									
								
								Shutdown/Check.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Shutdown/Check.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package Shutdown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func IsDown() (result bool) {
 | 
				
			||||||
 | 
						result = stopAllRequests
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								Shutdown/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Shutdown/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					package Shutdown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "container/list"
 | 
				
			||||||
 | 
					import "os/signal"
 | 
				
			||||||
 | 
					import "os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func InitShutdown() {
 | 
				
			||||||
 | 
						shutdownHandlers = list.New()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Apply the shutdown handler:
 | 
				
			||||||
 | 
						signal.Notify(shutdownSignal, os.Interrupt, os.Kill)
 | 
				
			||||||
 | 
						go executeShutdown()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								Shutdown/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								Shutdown/Shutdown.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					package Shutdown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "os"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ShutdownHandler interface {
 | 
				
			||||||
 | 
						Shutdown()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func AddShutdownHandler(handler ShutdownHandler) {
 | 
				
			||||||
 | 
						shutdownHandlers.PushBack(handler)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func executeShutdown() {
 | 
				
			||||||
 | 
						sig := <-shutdownSignal
 | 
				
			||||||
 | 
						stopAllRequests = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSHUTDOWN, `The system is shutting down now.`)
 | 
				
			||||||
 | 
						Log.Flush()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						os.Exit(6)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								Shutdown/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Shutdown/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package Shutdown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "os"
 | 
				
			||||||
 | 
					import "container/list"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						shutdownSignal   chan os.Signal = make(chan os.Signal)
 | 
				
			||||||
 | 
						shutdownHandlers *list.List     = nil
 | 
				
			||||||
 | 
						senderName       LM.Sender      = `System::Shutdown`
 | 
				
			||||||
 | 
						stopAllRequests  bool           = false
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										47
									
								
								StaticFiles/FindAndReadFile.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								StaticFiles/FindAndReadFile.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					package StaticFiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "io/ioutil"
 | 
				
			||||||
 | 
					import "bytes"
 | 
				
			||||||
 | 
					import "archive/zip"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FindAndReadFile(filename string) (result []byte) {
 | 
				
			||||||
 | 
						if Shutdown.IsDown() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Prepare the path:
 | 
				
			||||||
 | 
						path := filename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read the content from the ZIP file:
 | 
				
			||||||
 | 
						reader, readerError := zip.NewReader(bytes.NewReader(zipData), int64(len(zipData)))
 | 
				
			||||||
 | 
						if readerError != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameREAD, `Was not able to read the ZIP file.`, readerError.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, file := range reader.File {
 | 
				
			||||||
 | 
							if file.Name == path {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								fileReader, openError := file.Open()
 | 
				
			||||||
 | 
								defer fileReader.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if openError == nil {
 | 
				
			||||||
 | 
									contentData, readError := ioutil.ReadAll(fileReader)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if readError != nil {
 | 
				
			||||||
 | 
										Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameREAD, `Was not able to read the content of the desired file.`, readError.Error(), path)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									result = contentData
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameNOTFOUND, `The desired file is not part of the ZIP file.`, `Do you use an old version?`, path)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										57
									
								
								StaticFiles/Handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								StaticFiles/Handler.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					package StaticFiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/MimeTypes"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func HandlerStaticFiles(response http.ResponseWriter, request *http.Request) {
 | 
				
			||||||
 | 
						if Shutdown.IsDown() {
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Prepare the path:
 | 
				
			||||||
 | 
						path := strings.Replace(request.RequestURI, `/staticFiles/`, ``, 1)
 | 
				
			||||||
 | 
						path = strings.Replace(path, `%20`, ` `, -1)
 | 
				
			||||||
 | 
						fileType := ``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Determine the MIME type:
 | 
				
			||||||
 | 
						if mimeType, errMime := MimeTypes.DetectType(path); errMime != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityMiddle, LM.ImpactMiddle, LM.MessageNameNOTFOUND, `Was not able to detect the MIME type of the font.`, errMime.Error(), path)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fileType = mimeType.MimeType
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if fileType == `` {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameNOTFOUND, `The mime type is unknown.`, path)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contentData := FindAndReadFile(path)
 | 
				
			||||||
 | 
						if contentData == nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameDATABASE, `The desired file was not found.`, path)
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fileLenText := fmt.Sprintf(`%d`, len(contentData))
 | 
				
			||||||
 | 
						response.Header().Add(`Content-Length`, fileLenText)
 | 
				
			||||||
 | 
						response.Header().Add(`Content-Type`, fileType)
 | 
				
			||||||
 | 
						response.Write(contentData)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if logStaticFileRequests {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameBROWSER, `A static file was requested.`, path)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.NotFound(response, request)
 | 
				
			||||||
 | 
						Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameNOTFOUND, `The desired file is not part of the ZIP file.`, `Do you use an old version?`, path)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								StaticFiles/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								StaticFiles/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					package StaticFiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "io/ioutil"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/CustomerDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Starting now the static files component.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Starting the static files component done.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ConfigurationDB.Read(`EnableStaticFiles`) != `true` {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Static files are disabled.`)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Static files are enabled.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read the configuration:
 | 
				
			||||||
 | 
						if ConfigurationDB.Read(`MapStaticFiles2Root`) == `true` {
 | 
				
			||||||
 | 
							startFile4Map2Root = ConfigurationDB.Read(`MapStaticFiles2RootRootFile`)
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The desired root document was set.`, `rootDocument=`+startFile4Map2Root)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logStaticFileRequests = ConfigurationDB.Read(`LogStaticFileRequests`) == `true`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read the static files' data from GridFS:
 | 
				
			||||||
 | 
						gridFS := CustomerDB.GridFS()
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							defer gridFile.Close()
 | 
				
			||||||
 | 
							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 static files.`, ioError.Error())
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								zipData = data
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								StaticFiles/Map2Root.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								StaticFiles/Map2Root.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package StaticFiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func HandlerMapStaticFiles2Root(response http.ResponseWriter, request *http.Request) {
 | 
				
			||||||
 | 
						if Shutdown.IsDown() {
 | 
				
			||||||
 | 
							http.NotFound(response, request)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if request.RequestURI == `/` {
 | 
				
			||||||
 | 
							request.RequestURI = `/staticFiles/` + startFile4Map2Root
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							request.RequestURI = `/staticFiles` + request.RequestURI
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						HandlerStaticFiles(response, request)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								StaticFiles/Variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								StaticFiles/Variables.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					package StaticFiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						senderName            LM.Sender = `System::StaticFiles`
 | 
				
			||||||
 | 
						startFile4Map2Root    string    = `index.html`
 | 
				
			||||||
 | 
						logStaticFileRequests bool      = false
 | 
				
			||||||
 | 
						zipData               []byte    = nil
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										8
									
								
								System/ICCCStart.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								System/ICCCStart.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					package System
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										90
									
								
								System/Init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								System/Init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					package System
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "runtime"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Shutdown"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/CustomerDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/NumGen"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initSystem() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The system is now starting.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set the desired amount of CPUs:
 | 
				
			||||||
 | 
						utilizeCPUs := 2
 | 
				
			||||||
 | 
						if value, err := strconv.Atoi(ConfigurationDB.Read(`OceanUtilizeCPUs`)); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `Was not able to read the OceanUtilizeCPUs configuration.`, `Use the default value instead.`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							utilizeCPUs = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						runtime.GOMAXPROCS(utilizeCPUs)
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Configuration OceanUtilizeCPUs is set.`, fmt.Sprintf(`value=%d`, utilizeCPUs))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Apply all desired logging devices:
 | 
				
			||||||
 | 
						initLoggingDevices()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set the logging buffer size:
 | 
				
			||||||
 | 
						logBufferSize := 500
 | 
				
			||||||
 | 
						if value, err := strconv.Atoi(ConfigurationDB.Read(`LogBufferSize`)); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `Was not able to read the LogBufferSize configuration.`, `Use the default value instead.`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							logBufferSize = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.SetBufferSize(logBufferSize)
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Configuration LogBufferSize is set.`, fmt.Sprintf(`value=%d`, logBufferSize))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set the logging device delay (number of events):
 | 
				
			||||||
 | 
						logDeviceDelayNumberEvents := 600
 | 
				
			||||||
 | 
						if value, err := strconv.Atoi(ConfigurationDB.Read(`LogDeviceDelayNumberEvents`)); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `Was not able to read the LogDeviceDelayNumberEvents configuration.`, `Use the default value instead.`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							logDeviceDelayNumberEvents = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.SetDeviceDelayNumberEvents(logDeviceDelayNumberEvents)
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Configuration LogDeviceDelayNumberEvents is set.`, fmt.Sprintf(`value=%d`, logDeviceDelayNumberEvents))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set the logging device delay time to flush (seconds):
 | 
				
			||||||
 | 
						logDeviceDelayTime2FlushSeconds := 5
 | 
				
			||||||
 | 
						if value, err := strconv.Atoi(ConfigurationDB.Read(`LogDeviceDelayTime2FlushSeconds`)); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `Was not able to read the LogDeviceDelayTime2FlushSeconds configuration.`, `Use the default value instead.`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							logDeviceDelayTime2FlushSeconds = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.SetDeviceDelayTimeoutSeconds(logDeviceDelayTime2FlushSeconds)
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Configuration LogDeviceDelayTime2FlushSeconds is set.`, fmt.Sprintf(`value=%d`, logDeviceDelayTime2FlushSeconds))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set the logging timeout (seconds):
 | 
				
			||||||
 | 
						logTimeoutSeconds := 3
 | 
				
			||||||
 | 
						if value, err := strconv.Atoi(ConfigurationDB.Read(`LogTimeoutSeconds`)); err != nil {
 | 
				
			||||||
 | 
							Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactUnknown, LM.MessageNameCONFIGURATION, `Was not able to read the LogTimeoutSeconds configuration.`, `Use the default value instead.`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							logTimeoutSeconds = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.SetTimeoutSeconds(logTimeoutSeconds)
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `Configuration LogTimeoutSeconds is set.`, fmt.Sprintf(`value=%d`, logTimeoutSeconds))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Apply these changes:
 | 
				
			||||||
 | 
						Log.ApplyConfigurationChanges()
 | 
				
			||||||
 | 
						Log.LoggingIsReady()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Register all system shutdown handlers:
 | 
				
			||||||
 | 
						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:
 | 
				
			||||||
 | 
						ICCC.Registrar(ICCC.ChannelSYSTEM, `System::Start`, icccSystemStart)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								System/InitHandlers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								System/InitHandlers.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package System
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ICCC"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/WebContent"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/StaticFiles"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/NumGen"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Robots"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func InitHandlers() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initSystem()
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Register now all system handlers.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.HandleFunc(`/framework/`, WebContent.HandlerDeliverFramework)
 | 
				
			||||||
 | 
						http.HandleFunc(`/staticFiles/`, StaticFiles.HandlerStaticFiles)
 | 
				
			||||||
 | 
						http.HandleFunc(`/next/number`, NumGen.HandlerGetNext)
 | 
				
			||||||
 | 
						http.HandleFunc(`/robots.txt`, Robots.HandlerRobots)
 | 
				
			||||||
 | 
						http.HandleFunc(`/ICCC`, ICCC.ICCCHandler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ConfigurationDB.Read(`MapStaticFiles2Root`) == "true" {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The static files are mapped to the root.`)
 | 
				
			||||||
 | 
							http.HandleFunc(`/`, StaticFiles.HandlerMapStaticFiles2Root)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `Done with registering all system handler.`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								System/RegisterLoggingDevices.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								System/RegisterLoggingDevices.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					package System
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/DeviceConsole"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log/DeviceDatabase"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/ConfigurationDB"
 | 
				
			||||||
 | 
					import "github.com/SommerEngineering/Ocean/Log"
 | 
				
			||||||
 | 
					import LM "github.com/SommerEngineering/Ocean/Log/Meta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initLoggingDevices() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Init the logging devices.`)
 | 
				
			||||||
 | 
						defer Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameINIT, `Init the logging devices done.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ConfigurationDB.Read(`LogUseDatabaseLogging`) == `true` {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `The database logger is active.`)
 | 
				
			||||||
 | 
							activateDatabaseLogger()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `The database logger is NOT active.`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ConfigurationDB.Read(`LogUseConsoleLogging`) == `true` {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `The console logger is active.`)
 | 
				
			||||||
 | 
							activateConsoleLogger()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, `The console logger is NOT active.`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func activateDatabaseLogger() {
 | 
				
			||||||
 | 
						DeviceDatabase.ActivateLoggingDevice()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func activateConsoleLogger() {
 | 
				
			||||||
 | 
						DeviceConsole.ActivateLoggingDevice()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user