[INIT+STANDALONE] fresh init of this project from original without specific confidential documents
This commit is contained in:
55
kvmstoreserver_solution/etc/kvmstoreserver.conf
Executable file
55
kvmstoreserver_solution/etc/kvmstoreserver.conf
Executable file
@@ -0,0 +1,55 @@
|
||||
#******************************************************************************
|
||||
#* storeserver main config file
|
||||
#******************************************************************************
|
||||
|
||||
#******************************************************************************
|
||||
#* The kvmstoreserver was compiled with the configPoller extension. This means
|
||||
#* that changes to this config file can be captured after 60 seconds and
|
||||
#* loaded at runtime of the kvmstoreserver. Not all of the parameters listed
|
||||
#* below can be updated at runtime. Parameters with the comment label DYNAMIC
|
||||
#* can be updated at runtime. Parameters with the label STATIC did not belong.
|
||||
#*
|
||||
#* Caution when updating DYNAMIC parameters.
|
||||
#* In case of incorrect entries, the kvmstoreserver can crash!
|
||||
#*
|
||||
#******************************************************************************
|
||||
|
||||
|
||||
###################### General Server settings ################################
|
||||
|
||||
# DINAMIC
|
||||
storage_target = <Path to the solution on your hard disk>/kvmstoreserver_solution/var/warehouse
|
||||
|
||||
# DINAMIC
|
||||
serde_driver = filesystem
|
||||
|
||||
# All log file parameters -> STATIC
|
||||
default_log_file = <Path to the solution on your hard disk>/kvmstoreserver_solution/var/log/storeserver.log
|
||||
log_max_size_mb = 100
|
||||
log_max_age_days = 30
|
||||
log_write_to_console = true
|
||||
|
||||
|
||||
######################### HTTP Server settings ###############################
|
||||
|
||||
# All HTTP Server Settings -> STATIC
|
||||
http_hostname = <IP or Domain name>
|
||||
http_port = 3344
|
||||
read_header_timeout = 30
|
||||
read_timeout = 30
|
||||
write_timeout = 30
|
||||
tcp_idle_timeout_millsec = 100
|
||||
|
||||
########################### Http Route settings ##############################
|
||||
### Attention, the maximum path length per route is reduced to 1. Longer paths,
|
||||
### such as /controller/add/ are not allowed and cause errors
|
||||
|
||||
### All routes that work with JSON documents must always have an end slash in
|
||||
### the name such as /add"/"
|
||||
|
||||
# All Controller parameter -> STATIC
|
||||
ctrl_add_path = /add/
|
||||
ctrl_get_path = /get/
|
||||
ctrl_del_path = /del/
|
||||
ctrl_tree_path = /tree
|
||||
ctrl_version_path = /version
|
||||
55
kvmstoreserver_solution/etc/kvmstoreserver_test.conf
Executable file
55
kvmstoreserver_solution/etc/kvmstoreserver_test.conf
Executable file
@@ -0,0 +1,55 @@
|
||||
#******************************************************************************
|
||||
#* storeserver main config file
|
||||
#******************************************************************************
|
||||
|
||||
#******************************************************************************
|
||||
#* The kvmstoreserver was compiled with the configPoller extension. This means
|
||||
#* that changes to this config file can be captured after 60 seconds and
|
||||
#* loaded at runtime of the kvmstoreserver. Not all of the parameters listed
|
||||
#* below can be updated at runtime. Parameters with the comment label DYNAMIC
|
||||
#* can be updated at runtime. Parameters with the label STATIC did not belong.
|
||||
#*
|
||||
#* Caution when updating DYNAMIC parameters.
|
||||
#* In case of incorrect entries, the kvmstoreserver can crash!
|
||||
#*
|
||||
#******************************************************************************
|
||||
|
||||
|
||||
###################### General Server settings ################################
|
||||
|
||||
# DINAMIC
|
||||
storage_target = <Path to the solution on your hard disk>/kvmstoreserver_solution/var/warehouse_test
|
||||
|
||||
# DINAMIC
|
||||
serde_driver = filesystem
|
||||
|
||||
# All log file parameters -> STATIC
|
||||
default_log_file = <Path to the solution on your hard disk>/kvmstoreserver_solution/var/log/storeserver_test.log
|
||||
log_max_size_mb = 100
|
||||
log_max_age_days = 30
|
||||
log_write_to_console = true
|
||||
|
||||
|
||||
######################### HTTP Server settings ###############################
|
||||
|
||||
# All HTTP Server Settings -> STATIC
|
||||
http_hostname = <IP or Domain name>
|
||||
http_port = 3345
|
||||
read_header_timeout = 30
|
||||
read_timeout = 30
|
||||
write_timeout = 30
|
||||
tcp_idle_timeout_millsec = 100
|
||||
|
||||
########################### Http Route settings ##############################
|
||||
### Attention, the maximum path length per route is reduced to 1. Longer paths,
|
||||
### such as /controller/add/ are not allowed and cause errors
|
||||
|
||||
### All routes that work with JSON documents must always have an end slash in
|
||||
### the name such as /add"/"
|
||||
|
||||
# All Controller parameter -> STATIC
|
||||
ctrl_add_path = /add/
|
||||
ctrl_get_path = /get/
|
||||
ctrl_del_path = /del/
|
||||
ctrl_tree_path = /tree
|
||||
ctrl_version_path = /version
|
||||
61
kvmstoreserver_solution/src/essentials/controlEnums.go
Executable file
61
kvmstoreserver_solution/src/essentials/controlEnums.go
Executable file
@@ -0,0 +1,61 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: controlEnums.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package essentials offers various control elements that can be used by all
|
||||
// components. In this way, enums are formed in Go
|
||||
package essentials
|
||||
|
||||
// Control wrapps the type unit8
|
||||
type Control uint8
|
||||
|
||||
const (
|
||||
// DoPanic is used to signal that a panic is necessary
|
||||
DoPanic Control = iota
|
||||
|
||||
// DontPanic is used to signal that a panic is not necessary
|
||||
DontPanic
|
||||
|
||||
// Save is used to signal that something needs to be saved
|
||||
Save
|
||||
|
||||
// Delete is used to signal that something needs to be deleted
|
||||
Delete
|
||||
|
||||
// Load is used to signal that something needs to be loaded
|
||||
Load
|
||||
)
|
||||
58
kvmstoreserver_solution/src/essentials/injectJsonRespHeader.go
Executable file
58
kvmstoreserver_solution/src/essentials/injectJsonRespHeader.go
Executable file
@@ -0,0 +1,58 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: injectJsonRespHeader.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package essentials contains components that offer various functionalities for
|
||||
// different purposes. Everyone can use these functionalities
|
||||
package essentials
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Finctions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// InjectJSONTypeToHeader Injected in the response header the key value pair
|
||||
// Content-Type = application/json
|
||||
func InjectJSONTypeToHeader(writer http.ResponseWriter) {
|
||||
|
||||
writer.Header().Set("Content-Type", "application/json")
|
||||
}
|
||||
57
kvmstoreserver_solution/src/essentials/trimUrlKeyName.go
Executable file
57
kvmstoreserver_solution/src/essentials/trimUrlKeyName.go
Executable file
@@ -0,0 +1,57 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: trimUrlKeyName.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package essentials
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions:
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// CutKeyFromURL cuts the key name out of the URL. This function only works if
|
||||
// the corresponding middleware is in front of it and performs a preliminary
|
||||
// check
|
||||
func CutKeyFromURL(s string) string {
|
||||
|
||||
return strings.Split(strings.Split(s, "/")[2], "?")[0]
|
||||
}
|
||||
52
kvmstoreserver_solution/src/kvmstoreserver/main.go
Executable file
52
kvmstoreserver_solution/src/kvmstoreserver/main.go
Executable file
@@ -0,0 +1,52 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: main.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package main contains the start sequence of the kvmstoreserver. After
|
||||
// initializing the start method (this is a wrapper to the HTTP instance), the
|
||||
// HTTP server prevents mehtode from causing it to jump to the end. The wait
|
||||
// method intercepts the main end until the function gracefulShutdown() is done
|
||||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
kvmstoreserver := newAppServer(false, "")
|
||||
|
||||
kvmstoreserver.start()
|
||||
|
||||
kvmstoreserver.wait()
|
||||
}
|
||||
157
kvmstoreserver_solution/src/kvmstoreserver/stage0.go
Executable file
157
kvmstoreserver_solution/src/kvmstoreserver/stage0.go
Executable file
@@ -0,0 +1,157 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: stage0.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
conf "utils/configMap"
|
||||
"utils/configPoller"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: appServer
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// appServer is a unit-like structure. it is empty and serves
|
||||
// only as a method wrapper for the http instance
|
||||
type appServer struct{}
|
||||
|
||||
//******************** Methods ************************************************
|
||||
|
||||
// start starts the HTTP instance in stage0_ext3
|
||||
func (slf *appServer) start() {
|
||||
|
||||
log.Infof("Starting HTTP frontend - kvmstoreserver is online and listen on http://%v:%v",
|
||||
conf.GetStringOf("http_hostname"), conf.GetStringOf("http_port"))
|
||||
|
||||
httpFrontend.start()
|
||||
}
|
||||
|
||||
// wait activated when the HTTP server goes off. prevents the
|
||||
// end before the graceful shutdown procedure is finished
|
||||
func (slf *appServer) wait() { shutdown.wg.Wait() }
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* storeserver startup initiator
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// newAppServer creates a new wrapper instance and initialize
|
||||
// all components in the following order:
|
||||
//
|
||||
// 1.) set configMap
|
||||
// 2.) set configPoller
|
||||
// 3.) set logrjack log engine
|
||||
// 4.) init (load) Btree
|
||||
// 5.) init Middleware Chains
|
||||
// 6.) init a new HTTP instance
|
||||
// 7.) init a separate goroutine for shutdown signals (only sigint and sigterm)
|
||||
func newAppServer(testMode bool, overridePath string) *appServer {
|
||||
|
||||
if testMode {
|
||||
conf.Settings(overridePath)
|
||||
log.Infof("Starting storeserver in test mode with a different config -> %v",
|
||||
overridePath)
|
||||
} else {
|
||||
conf.Settings(pathFromCmd())
|
||||
}
|
||||
|
||||
// Register config reader in config poller
|
||||
configPoller.RegisterReaders(60, conf.GetConfigMapRef())
|
||||
|
||||
log.Setup(log.Settings{
|
||||
Filename: conf.GetStringOf("default_log_file"),
|
||||
MaxSizeMB: (int)(conf.GetInt32Of("log_max_size_mb")),
|
||||
MaxAgeDays: (int)(conf.GetInt32Of("log_max_age_days")),
|
||||
WriteStdout: conf.GetBoolOf("log_write_to_console"),
|
||||
})
|
||||
|
||||
log.Info(
|
||||
"Start config poller in a seperate goroutine with a polling interval of -> 60 Seconds",
|
||||
)
|
||||
|
||||
log.Info("******************** Initialze start procedure ********************")
|
||||
initializeBtree()
|
||||
|
||||
log.Info("Initialize Middleware components and final handlers")
|
||||
initializeMiddleware()
|
||||
|
||||
log.Info("Initialize a new HTTP server instance")
|
||||
initializeHTTPInstance()
|
||||
|
||||
initializeShutdownWatcher()
|
||||
signal.Notify(shutdown.signalChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
go shutdown.captureSignal()
|
||||
|
||||
var as appServer
|
||||
|
||||
return &as
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Methods
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// Parse command line args if the param -config is set
|
||||
func pathFromCmd() string {
|
||||
|
||||
pathToConfig := flag.String("config", "",
|
||||
"The path to the main configuration file")
|
||||
flag.Parse()
|
||||
|
||||
trimmedConfigPath := strings.Trim(*pathToConfig, " ")
|
||||
if trimmedConfigPath == "" {
|
||||
fmt.Println("Missing path to config file -> -config=<Path to valid config file>")
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
return *pathToConfig
|
||||
}
|
||||
232
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext1.go
Executable file
232
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext1.go
Executable file
@@ -0,0 +1,232 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: stage0_ext1.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
*
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
bth "kvmstoreserver_utils/bTreeHandling"
|
||||
sh "kvmstoreserver_utils/serdeHandling"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
conf "utils/configMap"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions: Loader Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// initializeBtree initialize the Btree loader
|
||||
func initializeBtree() {
|
||||
|
||||
newNodeLoaderController().fillTree()
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure:
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// nodeLoaderController This structure serves as a node deserializer and
|
||||
// loader. It synchronizes its own structure with an internal lock mechanism
|
||||
type nodeLoaderController struct {
|
||||
initBtree bth.IBtreeController
|
||||
rootNodeID int
|
||||
nodeListSlice []int
|
||||
nodeListLenght int
|
||||
nodeCounter int
|
||||
lockController sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
//******************** Load Methods *******************************************
|
||||
|
||||
// fillTree this structure takes over the actual loading of the nodes into
|
||||
// the tree. It executes the loading of the nodes in parallel (uncontrolled
|
||||
// with up to 10000 goroutines or mapped 1:1 OS threads)
|
||||
func (slf *nodeLoaderController) fillTree() {
|
||||
|
||||
backend := sh.LoaderFactory()
|
||||
|
||||
if slf.nodeListLenght == 0 && slf.rootNodeID == 0 {
|
||||
log.Info("The backend storage was empty - Nothing loaded")
|
||||
} else {
|
||||
|
||||
newRootNode := bth.CreateContainerFromSource(backend(slf.rootNodeID))
|
||||
slf.initBtree.InsertContainer(newRootNode)
|
||||
|
||||
log.Infof("The following node was loaded as root -> (ID: %v) | (Orig Key Name: %v)",
|
||||
newRootNode.GetID(), newRootNode.GetOrigKeyName())
|
||||
|
||||
// Here is the parallel load of nodes. The WaitGroup is prepared in
|
||||
// the Cotroller, but there were problems with using it in a FOR loop.
|
||||
// On a file system level, this is not necessary. For future use with
|
||||
// a DB, a chunk-based method must be implemented
|
||||
for idx := 0; idx < slf.nodeListLenght; idx++ {
|
||||
slf.wg.Add(1)
|
||||
go deserialNode(slf, slf.nodeListSlice[idx])
|
||||
}
|
||||
|
||||
// Wait until all routines are done
|
||||
slf.wg.Wait()
|
||||
|
||||
if slf.nodeCounter != slf.nodeListLenght {
|
||||
log.Fatalf("Not all nodes could be deserialized (only: %v) - Start aborted",
|
||||
slf.nodeCounter)
|
||||
}
|
||||
log.Infof("All nodes could be loaded | Loaded -> %v",
|
||||
slf.nodeListLenght)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Fnctions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// newNodeLoaderController returns a prepared controller back
|
||||
func newNodeLoaderController() *nodeLoaderController {
|
||||
|
||||
var nodeLoader nodeLoaderController
|
||||
|
||||
nodeLoader.initBtree = bth.NewBtree()
|
||||
nodeLoader.nodeListSlice, nodeLoader.rootNodeID = getNodeListWithRoot()
|
||||
nodeLoader.nodeListLenght = len(nodeLoader.nodeListSlice)
|
||||
|
||||
return &nodeLoader
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions: Helper Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// getSortedNodeList This function reads in the file names of the nodes and
|
||||
// saves them in a slice. It also extracts the most suitable node as root node
|
||||
func getNodeListWithRoot() ([]int, int) {
|
||||
|
||||
var intList []int
|
||||
var copyOfIntList []int
|
||||
var rootNode int
|
||||
|
||||
rawObjList, loadErr := ioutil.ReadDir(conf.GetStringOf("storage_target"))
|
||||
if loadErr != nil {
|
||||
panic("Can not load node files!")
|
||||
}
|
||||
|
||||
if len(rawObjList) > 0 {
|
||||
for idx := 0; idx < len(rawObjList); idx++ {
|
||||
rawName := strings.Split(rawObjList[idx].Name(), ".json")[0]
|
||||
newInt64, err := strconv.ParseInt(rawName, 10, 64)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("Corrupt file name -> (%v)",
|
||||
rawObjList[idx].Name())
|
||||
panic(errMsg)
|
||||
}
|
||||
|
||||
newInt := int(newInt64)
|
||||
intList = append(intList, newInt)
|
||||
|
||||
}
|
||||
copyOfIntList = make([]int, len(intList))
|
||||
|
||||
// Make a copy of the slice and sort it. This identifies the middle
|
||||
// node, which serves as the root node. The list was then discarded
|
||||
copy(copyOfIntList, intList)
|
||||
sort.Ints(copyOfIntList)
|
||||
|
||||
rootNodeIdx := len(copyOfIntList) / 2
|
||||
rootNode = copyOfIntList[rootNodeIdx]
|
||||
|
||||
if rootNodeIdx == 0 && len(rawObjList) == 1 {
|
||||
return make([]int, 0), rootNode
|
||||
}
|
||||
|
||||
var rootDelIdx int
|
||||
|
||||
if rootNodeIdx > 0 {
|
||||
for index, id := range intList {
|
||||
if id == rootNode {
|
||||
rootDelIdx = index
|
||||
}
|
||||
}
|
||||
|
||||
intList = append(intList[:rootDelIdx], intList[rootDelIdx+1:]...)
|
||||
}
|
||||
} else {
|
||||
return make([]int, 0), rootNode
|
||||
}
|
||||
|
||||
return intList, rootNode
|
||||
}
|
||||
|
||||
// deserialNode function is often executed as a standalone goutout
|
||||
func deserialNode(ncl *nodeLoaderController, curruentListIdx int) {
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
log.Warnf("Problem by parallel deserialization -> (ID: %v) | (Orig Err: %v)",
|
||||
curruentListIdx, err)
|
||||
}
|
||||
}()
|
||||
|
||||
backend := sh.LoaderFactory()
|
||||
|
||||
ncl.lockController.Lock()
|
||||
|
||||
ncl.initBtree.InsertContainer(bth.CreateContainerFromSource(backend(curruentListIdx)))
|
||||
ncl.nodeCounter++
|
||||
ncl.wg.Add(-1)
|
||||
|
||||
ncl.lockController.Unlock()
|
||||
}
|
||||
138
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext2.go
Executable file
138
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext2.go
Executable file
@@ -0,0 +1,138 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: stage0_ext2.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
fh "kvmstoreserver_utils/HttpHandlers/finalHandlers"
|
||||
mf "kvmstoreserver_utils/HttpHandlers/middlewareFunctions"
|
||||
"net/http"
|
||||
fcb "utils/Middleware/functionChainBuilder"
|
||||
conf "utils/configMap"
|
||||
"versionInfo"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
// Here, middleware chian containers can be formed and the corresponding routes
|
||||
// defined. A convention valid in this file requires setting log entries for
|
||||
// loading containers and routes
|
||||
func initializeMiddleware() {
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Create and set Middleware components and final handlers
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// Setup controller /add/
|
||||
ctrlAddChain := fcb.NewChainConatainer().
|
||||
RegisterFunctions(mf.MWareInOutLogger, mf.MWareIfMethodPost, mf.MWareCheckKeyInURL).
|
||||
SetFinalHandler(fh.AddFinalHandler)
|
||||
|
||||
log.Infof("Initialize chain container for route -> %v",
|
||||
conf.GetStringOf("ctrl_add_path"))
|
||||
|
||||
// Setup controller /get/
|
||||
ctrlGetChain := fcb.NewChainConatainer().
|
||||
RegisterFunctions(mf.MWareInOutLogger, mf.MWareIfMethodGet, mf.MWareCheckKeyInURL, mf.MwareCheckParamIntegrity).
|
||||
SetFinalHandler(fh.GetFinalHandler)
|
||||
|
||||
log.Infof("Initialize chain container for route -> %v",
|
||||
conf.GetStringOf("ctrl_get_path"))
|
||||
|
||||
// Setup controller /del/
|
||||
ctrlDelChain := fcb.NewChainConatainer().
|
||||
RegisterFunctions(mf.MWareInOutLogger, mf.MWareIfMethodDelete, mf.MWareCheckKeyInURL).
|
||||
SetFinalHandler(fh.DelFinalHandler)
|
||||
|
||||
log.Infof("Initialize chain container for route -> %v",
|
||||
conf.GetStringOf("ctrl_del_path"))
|
||||
|
||||
// Setup controller /tree
|
||||
ctrlTreeChain := fcb.NewChainConatainer().
|
||||
RegisterFunctions(mf.MWareInOutLogger, mf.MWareIfMethodGet).
|
||||
SetFinalHandler(fh.TreeFinalHandler)
|
||||
|
||||
log.Infof("Initialize chain container for route -> %v",
|
||||
conf.GetStringOf("ctrl_tree_path"))
|
||||
|
||||
// Setup controller /tree
|
||||
ctrlVersionChain := fcb.NewChainConatainer().
|
||||
RegisterFunctions(mf.MWareInOutLogger, mf.MWareIfMethodGet).
|
||||
SetFinalHandler(versionInfo.VerInfoFinalHandler)
|
||||
|
||||
log.Infof("Initialize chain container for route -> %v",
|
||||
conf.GetStringOf("ctrl_version_path"))
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Configure Routes
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// Configure ROUTE for controller /add/
|
||||
http.Handle(conf.GetStringOf("ctrl_add_path"), ctrlAddChain.RunChain())
|
||||
|
||||
log.Infof("Set controller into route -> %v",
|
||||
conf.GetStringOf("ctrl_add_path"))
|
||||
|
||||
// Configure ROUTE for controller /get/
|
||||
http.Handle(conf.GetStringOf("ctrl_get_path"), ctrlGetChain.RunChain())
|
||||
|
||||
log.Infof("Set controller into route -> %v",
|
||||
conf.GetStringOf("ctrl_get_path"))
|
||||
|
||||
// Configure ROUTE for controller /del/
|
||||
http.Handle(conf.GetStringOf("ctrl_del_path"), ctrlDelChain.RunChain())
|
||||
|
||||
log.Infof("Set controller into route -> %v",
|
||||
conf.GetStringOf("ctrl_del_path"))
|
||||
|
||||
// Configure ROUTE for controller /tree
|
||||
http.Handle(conf.GetStringOf("ctrl_tree_path"), ctrlTreeChain.RunChain())
|
||||
|
||||
log.Infof("Set controller into route -> %v",
|
||||
conf.GetStringOf("ctrl_tree_path"))
|
||||
|
||||
// Configure ROUTE for controller /tree
|
||||
http.Handle(conf.GetStringOf("ctrl_version_path"), ctrlVersionChain.RunChain())
|
||||
|
||||
log.Infof("Set controller into route -> %v",
|
||||
conf.GetStringOf("ctrl_version_path"))
|
||||
}
|
||||
97
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext3.go
Executable file
97
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext3.go
Executable file
@@ -0,0 +1,97 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: stage0_ext3.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
conf "utils/configMap"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions: Loader Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// Here a new HTTP server instance is formed. It runs on its own structure, so
|
||||
// that functionalities of the Go HTTP package can be abstracted using own
|
||||
// methods
|
||||
func initializeHTTPInstance() {
|
||||
|
||||
httpFrontend.server = http.Server{
|
||||
Addr: conf.GetStringOf("http_hostname") + ":" + conf.GetStringOf("http_port"),
|
||||
ReadHeaderTimeout: time.Second * time.Duration(conf.GetInt32Of("read_header_timeout")),
|
||||
ReadTimeout: time.Second * time.Duration(conf.GetInt32Of("read_timeout")),
|
||||
WriteTimeout: time.Second * time.Duration(conf.GetInt32Of("write_timeout")),
|
||||
IdleTimeout: time.Millisecond * time.Duration(conf.GetInt32Of("tcp_idle_timeout_millsec")),
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Variable declarations
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
var httpFrontend httpServer
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: httpServer
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// httpServer ...
|
||||
type httpServer struct {
|
||||
server http.Server
|
||||
}
|
||||
|
||||
//******************** Methods ************************************************
|
||||
|
||||
func (slf *httpServer) start() {
|
||||
|
||||
err := slf.server.ListenAndServe()
|
||||
if err != nil {
|
||||
fmt.Println("The HTTP component is stopped")
|
||||
}
|
||||
}
|
||||
|
||||
func (slf *httpServer) stop() { slf.server.Close() }
|
||||
108
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext4.go
Executable file
108
kvmstoreserver_solution/src/kvmstoreserver/stage0_ext4.go
Executable file
@@ -0,0 +1,108 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: stage0_ext4.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions: Loader Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// This controller controls the removal of OS signals. So a ctrl + c or SIGTERM
|
||||
// can be intercepted and a clean shutdown initiated
|
||||
func initializeShutdownWatcher() {
|
||||
|
||||
shutdown = &shutdownController{signalChan: make(chan os.Signal, 1)}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Variable declarations
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
var shutdown *shutdownController
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Struct: shutdownCotroller
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// shutdownController ...
|
||||
type shutdownController struct {
|
||||
signalChan chan os.Signal
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
//******************** Methods ************************************************
|
||||
|
||||
// This method is started from the outside as goroutine
|
||||
func (slf *shutdownController) captureSignal() {
|
||||
|
||||
sig := <-slf.signalChan
|
||||
if sig == syscall.SIGINT ||
|
||||
sig == syscall.SIGTERM {
|
||||
slf.gracefulShutdown()
|
||||
}
|
||||
}
|
||||
|
||||
func (slf *shutdownController) gracefulShutdown() {
|
||||
|
||||
slf.wg.Add(1)
|
||||
httpFrontend.stop()
|
||||
|
||||
fmt.Println("Start graceful shutdown procedure - Please wait...")
|
||||
log.Info("Started graceful shutdown procedure")
|
||||
time.Sleep(time.Second * 5)
|
||||
fmt.Println("The appserver is down - Bye :)")
|
||||
log.Info("The server ist down")
|
||||
|
||||
slf.wg.Done()
|
||||
}
|
||||
101
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_001_test.go
Executable file
101
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_001_test.go
Executable file
@@ -0,0 +1,101 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: testCaseRef_4_3_001_test.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-12
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test4_3_001_test tests the middleware, which should intercept wrong HTTP methods.
|
||||
// Here are the following tests:
|
||||
//
|
||||
// - Try using Add with POST (Must work)
|
||||
// - Try using Add with DELETE (Error message expected)
|
||||
// - Try using Add with GET (Error message expected)
|
||||
//
|
||||
// - Try using Get with GET (Must work)
|
||||
// - Try using Get with DELETE (Error message expected)
|
||||
// - Try using Get with POST (Error message expected)
|
||||
//
|
||||
// - Try using Del with DELETE (Must work)
|
||||
// - Try using Del with POST (Error message expected)
|
||||
// - Try using Del with GET (Error message expected)
|
||||
func Test4_3_001_test(t *testing.T) {
|
||||
|
||||
// Create test data
|
||||
tests := []struct {
|
||||
name string
|
||||
keySeqNbr int
|
||||
revNbr int
|
||||
cliAction clientAction
|
||||
httpMeth string
|
||||
wantedStatusCode int
|
||||
}{
|
||||
// Test sequence 1
|
||||
{name: "Test 1_1: Try to insert entry (Controller /add/ | Method POST)", keySeqNbr: 100, revNbr: 0, cliAction: actionAdd, httpMeth: POST, wantedStatusCode: 201},
|
||||
{name: "Test 1_2: Try to insert entry (Controller /add/ | Method DELETE)", keySeqNbr: 100, revNbr: 0, cliAction: actionAdd, httpMeth: DELETE, wantedStatusCode: 405},
|
||||
{name: "Test 1_3: Try to insert entry (Controller /add/ | Method GET)", keySeqNbr: 100, revNbr: 0, cliAction: actionAdd, httpMeth: GET, wantedStatusCode: 405},
|
||||
// Test sequence 2
|
||||
{name: "Test 2_1: Try to get entry (Controller /get/ | Method GET)", keySeqNbr: 100, revNbr: 0, cliAction: actionGet, httpMeth: GET, wantedStatusCode: 200},
|
||||
{name: "Test 2_2: Try to get entry (Controller /get/ | Method DELETE)", keySeqNbr: 100, revNbr: 0, cliAction: actionGet, httpMeth: DELETE, wantedStatusCode: 405},
|
||||
{name: "Test 2_3: Try to get entry (Controller /get/ | Method POST)", keySeqNbr: 100, revNbr: 0, cliAction: actionGet, httpMeth: POST, wantedStatusCode: 405},
|
||||
// Test sequence 3
|
||||
{name: "Test 3_1: Try to delete entry (Controller /del/ | Method DELETE)", keySeqNbr: 100, revNbr: 0, cliAction: actionDel, httpMeth: DELETE, wantedStatusCode: 200},
|
||||
{name: "Test 3_2: Try to delete entry (Controller /del/ | Method POST)", keySeqNbr: 100, revNbr: 0, cliAction: actionDel, httpMeth: POST, wantedStatusCode: 405},
|
||||
{name: "Test 3_3: Try to delete entry (Controller /del/ | Method GET)", keySeqNbr: 100, revNbr: 0, cliAction: actionDel, httpMeth: GET, wantedStatusCode: 405},
|
||||
}
|
||||
|
||||
// Start a test server in a separate gourutine
|
||||
runKvmssTestInstance()
|
||||
|
||||
// Clean up the environment (if there are remnants of the last test)
|
||||
testClient(tests[0].keySeqNbr, tests[0].revNbr, actionDel, DELETE, "")
|
||||
|
||||
// Execute the test series
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := testClient(tt.keySeqNbr, tt.revNbr, tt.cliAction, tt.httpMeth, ""); got.StatusCode != tt.wantedStatusCode {
|
||||
t.Errorf("Start testClient() (Client Test Desc.: HTTP Method allowed?) = %v, want %v", got.StatusCode, tt.wantedStatusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Post job: Clean up the environment
|
||||
testClient(tests[0].keySeqNbr, tests[0].revNbr, actionDel, DELETE, "")
|
||||
}
|
||||
216
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_005_2_test.go
Executable file
216
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_005_2_test.go
Executable file
@@ -0,0 +1,216 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: testCaseRef_4_3_005_2_test.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-12
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test4_3_005_2_test contains several individual tests. The detailed
|
||||
// descriptions of the tests can be found as comments in the tests themselves
|
||||
func Test4_3_005_2_test(t *testing.T) {
|
||||
|
||||
// Create test struct for the test data
|
||||
type innerStruct []struct {
|
||||
name string
|
||||
keySeqNbr int
|
||||
revNbr int
|
||||
cliAction clientAction
|
||||
httpMeth string
|
||||
paramExt string
|
||||
}
|
||||
tests := map[int]innerStruct{}
|
||||
tests = make(map[int]innerStruct, 0)
|
||||
|
||||
// Create test data
|
||||
tests[0] = innerStruct{
|
||||
// Insert sequence 1
|
||||
{name: "Test 1_1: Try to insert entry first time (Controller /get/ | Method Get)", keySeqNbr: 501, revNbr: 0, cliAction: actionGet, httpMeth: GET, paramExt: "?rev"},
|
||||
{name: "Test 1_2: Try to insert entry second time (Controller /get/ | Method Get)", keySeqNbr: 501, revNbr: 1, cliAction: actionGet, httpMeth: GET, paramExt: "?search"},
|
||||
{name: "Test 1_3: Try to insert entry third time (Controller /get/ | Method Get)", keySeqNbr: 501, revNbr: 2, cliAction: actionGet, httpMeth: GET, paramExt: "?search=rev_nbr"},
|
||||
}
|
||||
tests[1] = innerStruct{
|
||||
// Insert sequence 2
|
||||
{name: "Test 2_1: Try to insert entry first time (Controller /get/ | Method Get)", keySeqNbr: 502, revNbr: 0, cliAction: actionGet, httpMeth: GET, paramExt: "?search&rev"},
|
||||
{name: "Test 2_2: Try to insert entry second time (Controller /get/ | Method Get)", keySeqNbr: 502, revNbr: 1, cliAction: actionGet, httpMeth: GET, paramExt: "?rev=1&search=rev_nbr"},
|
||||
{name: "Test 2_3: Try to insert entry third time (Controller /get/ | Method POST)", keySeqNbr: 502, revNbr: 2, cliAction: actionGet, httpMeth: GET},
|
||||
}
|
||||
tests[2] = innerStruct{
|
||||
// Insert sequence 3
|
||||
{name: "Test 3_1: Try to insert entry first time (Controller /get/ | Method Get)", keySeqNbr: 503, revNbr: 0, cliAction: actionGet, httpMeth: GET, paramExt: "?search_wrong=rev_nbr"},
|
||||
{name: "Test 3_2: Try to insert entry second time (Controller /get/ | Method Get)", keySeqNbr: 503, revNbr: 1, cliAction: actionGet, httpMeth: GET},
|
||||
{name: "Test 3_3: Try to insert entry third time (Controller /get/ | Method Get)", keySeqNbr: 503, revNbr: 2, cliAction: actionGet, httpMeth: GET},
|
||||
}
|
||||
|
||||
// Start a test server in a separate gourutine
|
||||
runKvmssTestInstance()
|
||||
|
||||
// Clean up the environment (if there are remnants of the last test)
|
||||
testClient(tests[0][0].keySeqNbr, tests[0][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(tests[1][0].keySeqNbr, tests[1][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(tests[2][0].keySeqNbr, tests[2][0].revNbr, actionDel, DELETE, "")
|
||||
|
||||
// Insert test data into kvmstoreserver
|
||||
for _, outer := range tests {
|
||||
for _, inner := range outer {
|
||||
testClient(inner.keySeqNbr, inner.revNbr, actionAdd, POST, "")
|
||||
}
|
||||
}
|
||||
|
||||
// Test 1: Try to get the JSON field RevNbr from key 1 revision 2
|
||||
// (Expected: Int 2 && Status code 200)
|
||||
{
|
||||
testLine := &tests[0][2]
|
||||
got := testClient(testLine.keySeqNbr, testLine.revNbr, testLine.cliAction, testLine.httpMeth, testLine.paramExt)
|
||||
ressult, _, resultStatus := parseBodyRevAndSearch(got)
|
||||
if ressult != 2 || resultStatus != 200 {
|
||||
t.Errorf("Start testClient() (%v) = %v | Status: %v, want %v | Status: %v", testLine, ressult, resultStatus, 2, 200)
|
||||
}
|
||||
}
|
||||
|
||||
// Test 2: Try to get the JSON field RevNbr from key 2 revision 1
|
||||
// (Expected: Int 1 && Status code 200)
|
||||
{
|
||||
testLine := &tests[1][1]
|
||||
got := testClient(testLine.keySeqNbr, testLine.revNbr, testLine.cliAction, testLine.httpMeth, testLine.paramExt)
|
||||
ressult, _, resultStatus := parseBodyRevAndSearch(got)
|
||||
if ressult != 1 || resultStatus != 200 {
|
||||
t.Errorf("Start testClient() (%v) = %v | Status: %v, want %v | Status: %v", testLine.name, ressult, resultStatus, 1, 200)
|
||||
}
|
||||
}
|
||||
|
||||
// Test 3: Try to get the JSON field RevNbr from key 3 revision 0
|
||||
// The http parameter search is misspelled
|
||||
// (This test also applies to the parameter rev {Equivalent Implementation})
|
||||
// (Expected: Status code 400)
|
||||
{
|
||||
testLine := &tests[2][0]
|
||||
got := testClient(testLine.keySeqNbr, testLine.revNbr, testLine.cliAction, testLine.httpMeth, testLine.paramExt)
|
||||
_, _, resultStatus := parseBodyRevAndSearch(got)
|
||||
if resultStatus != 400 {
|
||||
t.Errorf("Start testClient() (%v) = %v, want %v", testLine.name, resultStatus, 400)
|
||||
}
|
||||
}
|
||||
|
||||
// Test 4: Try to get the JSON document from key 1 revision ()
|
||||
// The http parameter rev is set but not defined
|
||||
// (Expected: The last valid revision of the key {current revision})
|
||||
{
|
||||
testLine := &tests[0][0]
|
||||
got := testClient(testLine.keySeqNbr, testLine.revNbr, testLine.cliAction, testLine.httpMeth, testLine.paramExt)
|
||||
_, fullAnswer, resultStatus := parseBodyRevAndSearch(got)
|
||||
if resultStatus != 200 && fullAnswer.RevNbr != testLine.revNbr {
|
||||
t.Errorf("Start testClient() (%v) = %v, want %v", testLine.name, resultStatus, 400)
|
||||
}
|
||||
}
|
||||
|
||||
// Test 5: Try to get the field () from the current JSON document
|
||||
// The http parameter search is set but not defined
|
||||
// (Expected: The last valid revision of the key {current revision})
|
||||
{
|
||||
testLine := &tests[0][1]
|
||||
got := testClient(testLine.keySeqNbr, testLine.revNbr, testLine.cliAction, testLine.httpMeth, testLine.paramExt)
|
||||
_, fullAnswer, resultStatus := parseBodyRevAndSearch(got)
|
||||
if resultStatus != 200 && fullAnswer.RevNbr != testLine.revNbr {
|
||||
t.Errorf("Start testClient() (%v) = %v, want %v", testLine.name, resultStatus, 400)
|
||||
}
|
||||
}
|
||||
|
||||
// Test 6: Try to get the field () from the revision ()
|
||||
// The http parameters search and rev are set but not defined
|
||||
// (Expected: The last valid revision of the key {current revision})
|
||||
{
|
||||
testLine := &tests[1][0]
|
||||
got := testClient(testLine.keySeqNbr, testLine.revNbr, testLine.cliAction, testLine.httpMeth, testLine.paramExt)
|
||||
_, fullAnswer, resultStatus := parseBodyRevAndSearch(got)
|
||||
if resultStatus != 200 && fullAnswer.RevNbr != testLine.revNbr {
|
||||
t.Errorf("Start testClient() (%v) = %v, want %v", testLine.name, resultStatus, 400)
|
||||
}
|
||||
}
|
||||
|
||||
// Post job: Clean up the environment
|
||||
testClient(tests[0][0].keySeqNbr, tests[0][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(tests[1][0].keySeqNbr, tests[1][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(tests[2][0].keySeqNbr, tests[2][0].revNbr, actionDel, DELETE, "")
|
||||
}
|
||||
|
||||
// Here valid standard parser. Accepts the response of the testClient,
|
||||
// decodes it and returns the following:
|
||||
//
|
||||
// @var int (1) = JSON field RevNbr (int)
|
||||
// @var *fullRespAnswer = In struct decoded JSOn content from kvmstoreserver
|
||||
// @var int (2) = The http status code from the response header
|
||||
func parseBodyRevAndSearch(resp *http.Response) (int, *fullRespAnswer, int) {
|
||||
|
||||
var revNbrResult int
|
||||
var fullAnswer fullRespAnswer
|
||||
|
||||
body, errBody := ioutil.ReadAll(resp.Body)
|
||||
if errBody != nil {
|
||||
errMsg := fmt.Sprintf("Can not read body content (OrigErr)-> %v", errBody)
|
||||
panic(errMsg)
|
||||
}
|
||||
|
||||
if resp.StatusCode == 200 {
|
||||
errJSONOuter := json.Unmarshal(body, &revNbrResult)
|
||||
if errJSONOuter != nil {
|
||||
errJSONInner := json.Unmarshal(body, &fullAnswer)
|
||||
if errJSONInner != nil {
|
||||
errMsg := fmt.Sprintf("Can not decode JSON from body (OK Response; oter or inner) (OrigErr)-> %v", errJSONInner)
|
||||
panic(errMsg)
|
||||
}
|
||||
return 0, &fullAnswer, resp.StatusCode
|
||||
}
|
||||
}
|
||||
|
||||
return revNbrResult, &fullAnswer, resp.StatusCode
|
||||
}
|
||||
|
||||
type fullRespAnswer struct {
|
||||
SystemName string `json:"system_name"`
|
||||
SystemNumber int `json:"system_number"`
|
||||
SystemVersion float64 `json:"system_version"`
|
||||
SystemActive bool `json:"system_active"`
|
||||
SystemNull interface{} `json:"system_null"`
|
||||
RevNbr int `json:"rev_nbr"`
|
||||
}
|
||||
121
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_005_test.go
Executable file
121
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_005_test.go
Executable file
@@ -0,0 +1,121 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: testCaseRef_4_3_005_test.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-12
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test4_3_005_test first inserts a new key into the server. Then the testClient
|
||||
// creates two more revisions. The exam is passed if the JSON inside RevNbr
|
||||
// field returns the number 2 via testClient
|
||||
// (the check takes place in the parser)
|
||||
func Test4_3_005_test(t *testing.T) {
|
||||
|
||||
// Create test data
|
||||
tests := []struct {
|
||||
name string
|
||||
keySeqNbr int
|
||||
revNbr int
|
||||
cliAction clientAction
|
||||
httpMeth string
|
||||
}{
|
||||
// Test sequence 1
|
||||
{name: "Test 1_1: Try to insert entry first time (Controller /add/ | Method POST)", keySeqNbr: 500, revNbr: 0, cliAction: actionAdd, httpMeth: POST},
|
||||
{name: "Test 1_2: Try to insert entry second time (Controller /add/ | Method POST)", keySeqNbr: 500, revNbr: 1, cliAction: actionAdd, httpMeth: POST},
|
||||
{name: "Test 1_3: Try to insert entry third time (Controller /add/ | Method POST)", keySeqNbr: 500, revNbr: 2, cliAction: actionAdd, httpMeth: POST},
|
||||
}
|
||||
|
||||
var got *http.Response
|
||||
|
||||
// Start a test server in a separate gourutine
|
||||
runKvmssTestInstance()
|
||||
|
||||
// Clean up the environment (if there are remnants of the last test)
|
||||
testClient(tests[0].keySeqNbr, tests[2].revNbr, actionDel, DELETE, "")
|
||||
|
||||
// Execute the test series
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got = testClient(tt.keySeqNbr, tt.revNbr, tt.cliAction, tt.httpMeth, "")
|
||||
})
|
||||
}
|
||||
if result, status := parseBodyRev(got); !result {
|
||||
t.Errorf("Start testClient() (Try to insert 3 entries) = %v, want %v", status, 2)
|
||||
}
|
||||
|
||||
// Post job: Clean up the environment
|
||||
testClient(tests[0].keySeqNbr, tests[2].revNbr, actionDel, DELETE, "")
|
||||
}
|
||||
|
||||
// Here valid standard parser. Accepts the response of the testClient,
|
||||
// decodes it and returns the following:
|
||||
//
|
||||
// @var bool = If the JSON field NewRevisionNumber from response (NewRevisionNumber != 2) == false
|
||||
// @var int = The number from the JSON field NewRevisionNumber of the current respone
|
||||
func parseBodyRev(resp *http.Response) (bool, int) {
|
||||
|
||||
innerStruct := struct {
|
||||
StatusCode int `json:"status_code"`
|
||||
Description string `json:"description"`
|
||||
NewRevisionNumber int `json:"new_revision_number"`
|
||||
}{}
|
||||
|
||||
body, errBody := ioutil.ReadAll(resp.Body)
|
||||
if errBody != nil {
|
||||
errMsg := fmt.Sprintf("Can not read body content (OrigErr)-> %v", errBody)
|
||||
panic(errMsg)
|
||||
}
|
||||
|
||||
errJSON := json.Unmarshal(body, &innerStruct)
|
||||
if errJSON != nil {
|
||||
errMsg := fmt.Sprintf("Can not decode JSON from body (OrigErr)-> %v", errJSON)
|
||||
panic(errMsg)
|
||||
}
|
||||
|
||||
if innerStruct.NewRevisionNumber != 2 {
|
||||
return false, innerStruct.NewRevisionNumber
|
||||
}
|
||||
|
||||
return true, innerStruct.NewRevisionNumber
|
||||
}
|
||||
158
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_006_test.go
Executable file
158
kvmstoreserver_solution/src/kvmstoreserver/testCaseRef_4_3_006_test.go
Executable file
@@ -0,0 +1,158 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: testCaseRef_4_3_006_test.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-13
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test4_3_006_test adds an entry to the kvmstoreserver and deletes it again.
|
||||
// This process is repeated three times. At each repetition it is checked if a
|
||||
// positive status code (200) comes back and if the deletion text is contained
|
||||
// (All information was deleted)
|
||||
func Test4_3_006_test(t *testing.T) {
|
||||
|
||||
// Create test struct for the test data
|
||||
type innerStruct []struct {
|
||||
name string
|
||||
keySeqNbr int
|
||||
revNbr int
|
||||
cliAction clientAction
|
||||
httpMeth string
|
||||
}
|
||||
|
||||
// Create test data
|
||||
insertValues := map[int]innerStruct{}
|
||||
insertValues = make(map[int]innerStruct, 0)
|
||||
insertValues[0] = innerStruct{
|
||||
// Test sequence 1
|
||||
{name: "Test 1_1: Try to insert entry first time (Controller /add/ | Method POST)", keySeqNbr: 700, revNbr: 0, cliAction: actionAdd, httpMeth: POST},
|
||||
{name: "Test 1_2: Try to delete entry (Controller /del/ | Method DELETE)", keySeqNbr: 700, revNbr: 0, cliAction: actionDel, httpMeth: DELETE},
|
||||
}
|
||||
insertValues[1] = innerStruct{
|
||||
// Test sequence 2
|
||||
{name: "Test 2_1: Try to insert entry first time (Controller /add/ | Method POST)", keySeqNbr: 701, revNbr: 0, cliAction: actionAdd, httpMeth: POST},
|
||||
{name: "Test 2_2: Try to delete entry (Controller /del/ | Method DELETE)", keySeqNbr: 701, revNbr: 0, cliAction: actionDel, httpMeth: DELETE},
|
||||
}
|
||||
insertValues[2] = innerStruct{
|
||||
// Test sequence 3
|
||||
{name: "Test 3_1: Try to insert entry first time (Controller /add/ | Method POST)", keySeqNbr: 702, revNbr: 0, cliAction: actionAdd, httpMeth: POST},
|
||||
{name: "Test 3_2: Try to delete entry (Controller /del/ | Method DELETE)", keySeqNbr: 702, revNbr: 0, cliAction: actionDel, httpMeth: DELETE},
|
||||
}
|
||||
|
||||
// Create test data (delete instructions)
|
||||
deleteValues := map[int]innerStruct{}
|
||||
deleteValues = make(map[int]innerStruct, 0)
|
||||
deleteValues[0] = innerStruct{
|
||||
// Delete instuctions for all keys
|
||||
{name: "Test 1_3: Try to delete entry (Controller /get/ | Method GET)", keySeqNbr: 700, revNbr: 0, cliAction: actionGet, httpMeth: GET},
|
||||
{name: "Test 2_3: Try to delete entry (Controller /get/ | Method GET)", keySeqNbr: 701, revNbr: 0, cliAction: actionGet, httpMeth: GET},
|
||||
{name: "Test 3_3: Try to delete entry (Controller /get/ | Method GET)", keySeqNbr: 702, revNbr: 0, cliAction: actionGet, httpMeth: GET},
|
||||
}
|
||||
|
||||
// Start a test server in a separate gourutine
|
||||
runKvmssTestInstance()
|
||||
|
||||
// Clean up the environment (if there are remnants of the last test)
|
||||
testClient(insertValues[0][0].keySeqNbr, insertValues[0][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(insertValues[1][0].keySeqNbr, insertValues[1][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(insertValues[2][0].keySeqNbr, insertValues[2][0].revNbr, actionDel, DELETE, "")
|
||||
|
||||
// Execute the test series
|
||||
for _, insertOuter := range insertValues {
|
||||
for _, insertInner := range insertOuter {
|
||||
t.Run(insertInner.name, func(t *testing.T) {
|
||||
testClient(insertInner.keySeqNbr, insertInner.revNbr, insertInner.cliAction, insertInner.httpMeth, "")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, outer := range deleteValues {
|
||||
for _, tt := range outer {
|
||||
got := testClient(tt.keySeqNbr, tt.revNbr, tt.cliAction, tt.httpMeth, "")
|
||||
if result, status, errMsg := parseBodyAfterDel(got); result {
|
||||
t.Errorf("Start testClient() (%v) = %v - %v, want %v - %v", tt, status, errMsg, 400, "The container with the name \"...\" existed once, but its contents were deleted")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Post job: Clean up the environment
|
||||
testClient(insertValues[0][0].keySeqNbr, insertValues[0][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(insertValues[1][0].keySeqNbr, insertValues[1][0].revNbr, actionDel, DELETE, "")
|
||||
testClient(insertValues[2][0].keySeqNbr, insertValues[2][0].revNbr, actionDel, DELETE, "")
|
||||
}
|
||||
|
||||
// Here valid standard parser. Accepts the response of the testClient,
|
||||
// decodes it and returns the following:
|
||||
//
|
||||
// @var bool = If the JSON field NewRevisionNumber from response (StatusCode != 200) == false
|
||||
// @var int = The status code from the current reponse
|
||||
// @var string = The description JSON field of the current response
|
||||
func parseBodyAfterDel(resp *http.Response) (bool, int, string) {
|
||||
|
||||
innerStruct := struct {
|
||||
StatusCode int `json:"status_code"`
|
||||
Description string `json:"description"`
|
||||
OriginalErrorMessage string `json:"original_error_message"`
|
||||
}{}
|
||||
|
||||
body, errBody := ioutil.ReadAll(resp.Body)
|
||||
if errBody != nil {
|
||||
errMsg := fmt.Sprintf("Can not read body content (OrigErr)-> %v", errBody)
|
||||
panic(errMsg)
|
||||
}
|
||||
|
||||
errJSON := json.Unmarshal(body, &innerStruct)
|
||||
if errJSON != nil {
|
||||
errMsg := fmt.Sprintf("Can not decode JSON from body (OrigErr)-> %v", errJSON)
|
||||
panic(errMsg)
|
||||
}
|
||||
|
||||
if innerStruct.StatusCode != 400 ||
|
||||
!strings.Contains(innerStruct.OriginalErrorMessage, "existed once, but its contents were deleted") {
|
||||
return true, innerStruct.StatusCode, innerStruct.OriginalErrorMessage
|
||||
}
|
||||
|
||||
return false, innerStruct.StatusCode, innerStruct.OriginalErrorMessage
|
||||
}
|
||||
185
kvmstoreserver_solution/src/kvmstoreserver/testing_essentials.go
Executable file
185
kvmstoreserver_solution/src/kvmstoreserver/testing_essentials.go
Executable file
@@ -0,0 +1,185 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: testCaseRef_4_3_006_test.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-12
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Declarations: Constants
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// clientAction alias type for uint8
|
||||
type clientAction uint8
|
||||
|
||||
// Enum to define the client request action
|
||||
const (
|
||||
actionAdd clientAction = iota
|
||||
actionGet
|
||||
actionDel
|
||||
)
|
||||
|
||||
// Enum with aliases for the HTTP methods
|
||||
const (
|
||||
// GET is a alias for string "GET"
|
||||
GET string = "GET"
|
||||
|
||||
// POST is a alias for string "POST"
|
||||
POST string = "POST"
|
||||
|
||||
// DELETE is a alias for string "DELETE"
|
||||
DELETE string = "DELETE"
|
||||
)
|
||||
|
||||
// Client and (partial Server) configuration parameters
|
||||
const (
|
||||
pathToTestConfiguration string = "C:/Users/tbogd/GIT/gitlab.com/tbogdanovic/Diplomarbeit_NDS_16NI/CODE/kvmstoreserver_solution/etc/kvmstoreserver_test.conf"
|
||||
|
||||
// Replace here the hostname (or IP) and the port with the parameters
|
||||
// from the config file above
|
||||
kvmstoreserverNameOrIP string = "192.168.117.86"
|
||||
serverPortTest string = "3345"
|
||||
|
||||
// Don not touch the settings below
|
||||
serverStartDelay int = 2
|
||||
|
||||
addRoute string = "http://" + kvmstoreserverNameOrIP + ":" + serverPortTest + "/add/"
|
||||
getRoute string = "http://" + kvmstoreserverNameOrIP + ":" + serverPortTest + "/get/"
|
||||
delRoute string = "http://" + kvmstoreserverNameOrIP + ":" + serverPortTest + "/del/"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// runKvmssTestInstance starts a kvmstoreserver in a separate
|
||||
// goroutine and waits 2 seconds until everything is ready.
|
||||
// (!!! This time must be deducted during time measurements !!!)
|
||||
func runKvmssTestInstance() {
|
||||
|
||||
go func() {
|
||||
testkvvmsrv := newAppServer(true, pathToTestConfiguration)
|
||||
testkvvmsrv.start()
|
||||
testkvvmsrv.wait()
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second * time.Duration(serverStartDelay))
|
||||
}
|
||||
|
||||
// This is a dynamic test clinet, which you can give a sequence number, from
|
||||
// which it then generates a valid key name. In addition, you can also give him
|
||||
// the RevNbr, which is written in the JSON document. To send a request, the
|
||||
// action can be given, what needs to be addressed (add, get, del), as well as
|
||||
// the HTTP Mtheode which should be written in the header. The last parameter
|
||||
// allows the setting of free parameters, which are appended to the url call.
|
||||
// The result is an HTTP response.
|
||||
// (Attention, the body of the response (reader) is NOT closed!)
|
||||
func testClient(keyNbr, revNbr int, action clientAction, httpMeth string, paramExt string) *http.Response {
|
||||
|
||||
// Intialize a request body - default pattern
|
||||
keyNbrStr := strconv.Itoa(keyNbr)
|
||||
newName := "Testsystem_Name_" + keyNbrStr
|
||||
newRev := revNbr
|
||||
newNbr := keyNbr
|
||||
newVers := float64(keyNbr) + 0.99999999
|
||||
newAct := keyNbr%2 == 0
|
||||
newNull := "null"
|
||||
|
||||
buildBodyRequestADD := func() *bytes.Reader {
|
||||
return bytes.NewReader([]byte(
|
||||
fmt.Sprintf(`{"system_name": "%v","system_number": %v,"system_version": %v,"system_active": %v,"system_null": %v, "rev_nbr": %v}`,
|
||||
newName, newNbr, newVers, newAct, newNull, newRev),
|
||||
))
|
||||
}
|
||||
|
||||
buildBodyRequestDEL := func() *bytes.Reader {
|
||||
return bytes.NewReader([]byte(
|
||||
fmt.Sprintf(`{"key_name": "%v","confirm_delete": true}`,
|
||||
newName),
|
||||
))
|
||||
}
|
||||
|
||||
// Initialize and run a client request and catch and return a
|
||||
// reference as output
|
||||
client := &http.Client{Timeout: time.Second * 60}
|
||||
var callURL string
|
||||
var req *http.Request
|
||||
var reqBuildError error
|
||||
|
||||
switch action {
|
||||
case actionAdd:
|
||||
callURL = addRoute + newName
|
||||
req, reqBuildError = http.NewRequest(httpMeth, callURL, buildBodyRequestADD())
|
||||
case actionGet:
|
||||
callURL = getRoute + newName
|
||||
|
||||
if paramExt != "" {
|
||||
callURL = callURL + paramExt
|
||||
}
|
||||
req, reqBuildError = http.NewRequest(httpMeth, callURL, nil)
|
||||
case actionDel:
|
||||
callURL = delRoute + newName
|
||||
req, reqBuildError = http.NewRequest(httpMeth, callURL, buildBodyRequestDEL())
|
||||
}
|
||||
|
||||
if reqBuildError != nil {
|
||||
panic("Error by building request")
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "Injection-Client-storeserver-1.0.0")
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
panic("Can not call target URL (Go internal client agent)")
|
||||
}
|
||||
|
||||
// The body (reader) is not closed here!
|
||||
|
||||
return resp
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: successJsonResponse.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package essentials
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// SendSuccessJSONAdd Creates a JSON message with the last (current) revision
|
||||
// number and using its own internal structure and writes the result directly
|
||||
// into the ResponseWriter
|
||||
func SendSuccessJSONAdd(writer http.ResponseWriter, statusCode,
|
||||
|
||||
newRevNbr int, customText string) {
|
||||
|
||||
if customText == "" {
|
||||
customText = "Operation successfully finished"
|
||||
}
|
||||
|
||||
innerAswerStruct := &struct {
|
||||
StatusCode int `json:"status_code"`
|
||||
Description string `json:"description"`
|
||||
NewRevisionNumber int `json:"new_revision_number"`
|
||||
}{
|
||||
StatusCode: statusCode,
|
||||
Description: customText,
|
||||
NewRevisionNumber: newRevNbr,
|
||||
}
|
||||
|
||||
jsonOutput, err := json.Marshal(innerAswerStruct)
|
||||
if err != nil {
|
||||
panic("Internal error when sending the positive Add JSON response. Operation has been successful anyway")
|
||||
}
|
||||
|
||||
writer.WriteHeader(statusCode)
|
||||
writer.Write(jsonOutput)
|
||||
}
|
||||
|
||||
// SendSuccessJSONDel Creates a JSON message with the original key Name and
|
||||
// using its own internal structure and writes the result directly into
|
||||
// the ResponseWriter
|
||||
func SendSuccessJSONDel(writer http.ResponseWriter, statusCode int,
|
||||
|
||||
keyName, customText string) {
|
||||
if customText == "" {
|
||||
customText = "Operation successfully finished"
|
||||
}
|
||||
|
||||
innerAswerStruct := &struct {
|
||||
StatusCode int `json:"status_code"`
|
||||
Description string `json:"description"`
|
||||
KeyName string `json:"key_name"`
|
||||
}{
|
||||
StatusCode: statusCode,
|
||||
Description: customText,
|
||||
KeyName: keyName,
|
||||
}
|
||||
|
||||
jsonOutput, err := json.Marshal(innerAswerStruct)
|
||||
if err != nil {
|
||||
panic("Internal error when sending the positive Delete JSON response. Operation has been successful anyway")
|
||||
}
|
||||
|
||||
writer.WriteHeader(statusCode)
|
||||
writer.Write(jsonOutput)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: addFinalHandler.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package finalHandlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
es "essentials"
|
||||
answer "kvmstoreserver_utils/HttpHandlers/essentials"
|
||||
bth "kvmstoreserver_utils/bTreeHandling"
|
||||
eh "kvmstoreserver_utils/errorHandling"
|
||||
knh "kvmstoreserver_utils/keyNameHandling"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions: Final Handler
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// AddFinalHandler includes all the logic to add a document.
|
||||
//
|
||||
// The logic is equivalent to the use -Entgegennehmen-
|
||||
func AddFinalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
defer eh.Try("FinalHandler->AddFinalHandler()")
|
||||
es.InjectJSONTypeToHeader(w)
|
||||
|
||||
parsedKeyName, errKeyParser := url.PathUnescape(
|
||||
es.CutKeyFromURL(r.RequestURI))
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errKeyParser, http.StatusBadRequest,
|
||||
"Invalid character in key name", es.DoPanic)
|
||||
|
||||
keyCtx, errKeyName := knh.NewKeyContext(parsedKeyName)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errKeyName, http.StatusBadRequest,
|
||||
"Error by Key to=> ID mapping - Maybe forget the name?", es.DoPanic)
|
||||
|
||||
newModel := bth.DataModel{}
|
||||
newModel.MetaHeader = bth.NewMetaData(r)
|
||||
|
||||
jsonDecoder := json.NewDecoder(r.Body)
|
||||
errDecode := jsonDecoder.Decode(&newModel.Data)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errDecode, http.StatusInternalServerError,
|
||||
"Please check the syntax of your JSON document, there is an error",
|
||||
es.DoPanic)
|
||||
|
||||
currentRevNbr, errInsert := bth.NewBtree().Insert(keyCtx, &newModel)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errInsert, http.StatusInternalServerError,
|
||||
"When trying to write the data on the store a mistake has occurred",
|
||||
es.DoPanic)
|
||||
|
||||
log.Infof("Inserted data into node -> (ID: %v) | (Key name: %v) | (RevNbr: %v) -> for (Client: %v)",
|
||||
keyCtx.GetNodeID(), keyCtx.GetKeyStrName(), currentRevNbr, r.RemoteAddr)
|
||||
|
||||
answer.SendSuccessJSONAdd(w, http.StatusCreated, currentRevNbr, "")
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: delFinalHandler.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package finalHandlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
es "essentials"
|
||||
"fmt"
|
||||
answer "kvmstoreserver_utils/HttpHandlers/essentials"
|
||||
bth "kvmstoreserver_utils/bTreeHandling"
|
||||
eh "kvmstoreserver_utils/errorHandling"
|
||||
knh "kvmstoreserver_utils/keyNameHandling"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: deleteConfirm
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// deleteConfirm ...
|
||||
type deleteConfirm struct {
|
||||
KeyName string `json:"key_name"`
|
||||
ConfirmDelete bool `json:"confirm_delete"`
|
||||
}
|
||||
|
||||
//******************** Methods ************************************************
|
||||
|
||||
func (slf *deleteConfirm) notEqualTo(s string) bool { return slf.KeyName != s }
|
||||
|
||||
func (slf *deleteConfirm) notConfirmed() bool { return slf.ConfirmDelete != true }
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions: Final Handler
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// DelFinalHandler deletes the content of a node and its data stored at
|
||||
// harddisk
|
||||
//
|
||||
// The logic is equivalent to the use -loeschen-
|
||||
func DelFinalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
defer eh.Try("FinalHandler->DelFinalHandler()")
|
||||
es.InjectJSONTypeToHeader(w)
|
||||
|
||||
parsedKeyName, errKeyParser := url.PathUnescape(
|
||||
es.CutKeyFromURL(r.RequestURI))
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errKeyParser, http.StatusBadRequest,
|
||||
"Invalid character in key name", es.DoPanic)
|
||||
|
||||
keyCtx, errKeyName := knh.NewKeyContext(parsedKeyName)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errKeyName, http.StatusInternalServerError,
|
||||
"Error by Key to=> ID mapping - Maybe forget the name?", es.DoPanic)
|
||||
|
||||
newDelConfirm := deleteConfirm{}
|
||||
|
||||
newJSONDecoder := json.NewDecoder(r.Body)
|
||||
|
||||
errDecode := newJSONDecoder.Decode(&newDelConfirm)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errDecode, http.StatusInternalServerError,
|
||||
"Please check the syntax of your JSON document, there is an error",
|
||||
es.DoPanic)
|
||||
|
||||
if newDelConfirm.notEqualTo(keyCtx.GetKeyStrName()) {
|
||||
eh.IfErrBuildJSONAndOrPanic(w,
|
||||
fmt.Errorf("Your URL key and the key name in the JSON are not equal | (URL)-> %v != (JSON)-> %v",
|
||||
keyCtx.GetKeyStrName(), newDelConfirm.KeyName),
|
||||
http.StatusBadRequest,
|
||||
"Your key name does not correspond to the name in URL", es.DoPanic)
|
||||
}
|
||||
if newDelConfirm.notConfirmed() {
|
||||
eh.IfErrBuildJSONAndOrPanic(w,
|
||||
fmt.Errorf("You forget to confirm the deletion | Recived-> (%v) || Wanted-> (true)",
|
||||
newDelConfirm.ConfirmDelete),
|
||||
http.StatusBadRequest,
|
||||
"You forgot to confirm the deletion", es.DoPanic)
|
||||
}
|
||||
|
||||
errMember := bth.NewBtree().Member(keyCtx)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errMember, http.StatusBadRequest,
|
||||
"It seems that the key does not exist", es.DoPanic)
|
||||
|
||||
delErr := bth.NewBtree().Del(keyCtx)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, delErr, http.StatusInternalServerError,
|
||||
"Internal storage Error. Your key has not been deleted!", es.DoPanic)
|
||||
|
||||
log.Infof("Successful delete node -> (ID: %v) | (Key name: %v) -> for (Client: %v)",
|
||||
keyCtx.GetNodeID(), keyCtx.GetKeyStrName(), r.RemoteAddr)
|
||||
|
||||
answer.SendSuccessJSONDel(w, http.StatusOK, keyCtx.GetKeyStrName(),
|
||||
"All information was deleted")
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: getFinalHandler.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package finalHandlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
es "essentials"
|
||||
bth "kvmstoreserver_utils/bTreeHandling"
|
||||
eh "kvmstoreserver_utils/errorHandling"
|
||||
knh "kvmstoreserver_utils/keyNameHandling"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions: Final Handler
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// GetFinalHandler includes all the logic to get a document, a document
|
||||
// by revision or a specific key back.
|
||||
//
|
||||
// The logic is equivalent to the use -Zurueckliefern-
|
||||
func GetFinalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
defer eh.Try("FinalHandler->GetFinalHandler()")
|
||||
es.InjectJSONTypeToHeader(w)
|
||||
|
||||
var (
|
||||
revNbrInt *int
|
||||
jsonOutput interface{}
|
||||
handlerRuntimeErrors error
|
||||
)
|
||||
|
||||
parsedKeyName, errKeyParser := url.PathUnescape(
|
||||
es.CutKeyFromURL(r.RequestURI))
|
||||
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errKeyParser, http.StatusBadRequest,
|
||||
"Invalid character in key name", es.DoPanic)
|
||||
|
||||
keyCtx, errKeyName := knh.NewKeyContext(parsedKeyName)
|
||||
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errKeyName, http.StatusBadRequest,
|
||||
"Error by Key to=> ID mapping - Maybe forget the name?", es.DoPanic)
|
||||
|
||||
errMember := bth.NewBtree().Member(keyCtx)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errMember, http.StatusBadRequest,
|
||||
"It seems that the key does not exist", es.DoPanic)
|
||||
|
||||
if r.URL.Query().Get("rev") != "" {
|
||||
revNbr, parseIntErr := strconv.
|
||||
ParseInt(r.URL.Query().Get("rev"), 10, 32)
|
||||
|
||||
eh.IfErrBuildJSONAndOrPanic(w, parseIntErr,
|
||||
http.StatusInternalServerError,
|
||||
"The revision number must be a number", es.DoPanic)
|
||||
|
||||
parsedInt := int(revNbr)
|
||||
revNbrInt = &parsedInt
|
||||
}
|
||||
|
||||
// If revNbrInt empty, then it is nil. GetModelOrDefault() returns by a
|
||||
// nil *int the last entry (current revison)
|
||||
model, errModelSearch := bth.NewBtree().Get(keyCtx).GetModelOrDefault(revNbrInt)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, errModelSearch, http.StatusBadRequest,
|
||||
"Is this revision number really correct?", es.DoPanic)
|
||||
|
||||
searchOnject := r.URL.Query().Get("search")
|
||||
if searchOnject != "" {
|
||||
jsonOutput, handlerRuntimeErrors = model.Search(searchOnject)
|
||||
eh.IfErrBuildJSONAndOrPanic(w, handlerRuntimeErrors, http.StatusBadRequest,
|
||||
"It seems like the search term is wrong, please check it again", es.DoPanic)
|
||||
} else {
|
||||
jsonOutput = model.Data
|
||||
}
|
||||
|
||||
output, handlerRuntimeErrors := json.Marshal(jsonOutput)
|
||||
|
||||
eh.IfErrBuildJSONAndOrPanic(w, handlerRuntimeErrors,
|
||||
http.StatusInternalServerError,
|
||||
"Error by converting cotent into a JSON structure", es.DoPanic)
|
||||
|
||||
log.Infof("Successful reply sent -> (ID: %v) | (Key name: %v) | (RevNbr: %v) -> send back to (Client: %v)",
|
||||
keyCtx.GetNodeID(), keyCtx.GetKeyStrName(), model.RevNbr, r.RemoteAddr)
|
||||
|
||||
w.Write(output)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: treeFinalHandler.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package finalHandlers
|
||||
|
||||
import (
|
||||
"kvmstoreserver_utils/bTreeHandling"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions: Final Handler
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// TreeFinalHandler return a JSON document (JSON array) with the
|
||||
// in a Slice mappt Btree structure
|
||||
func TreeFinalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
btree := bTreeHandling.NewBtree()
|
||||
|
||||
w.Write(btree.GetBtreeStruct())
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: httpMethodCheckers.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package middlewareFunctions
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
eh "kvmstoreserver_utils/errorHandling"
|
||||
"net/http"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Declarations
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// Shortcats for HTTP methods
|
||||
// Looks more beautiful in the functions than a string
|
||||
const (
|
||||
post = "POST"
|
||||
get = "GET"
|
||||
del = "DELETE"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions: Middleware functionality
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// MWareIfMethodPost checks if the client request is from HTTP method type POST
|
||||
func MWareIfMethodPost(nextFunc http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// BEGIN Handler Logic ->
|
||||
if result := checkMethod(w, r, post); result == eh.Nok {
|
||||
return
|
||||
}
|
||||
|
||||
nextFunc.ServeHTTP(w, r)
|
||||
// <- END Handler Logic
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// MWareIfMethodGet checks if the client request is from HTTP method type Get
|
||||
func MWareIfMethodGet(nextFunc http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// BEGIN Handler Logic ->
|
||||
if result := checkMethod(w, r, get); result == eh.Nok {
|
||||
return
|
||||
}
|
||||
|
||||
nextFunc.ServeHTTP(w, r)
|
||||
// <- END Handler Logic
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// MWareIfMethodDelete checks if the client request is from HTTP method type DELETE
|
||||
func MWareIfMethodDelete(nextFunc http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// BEGIN Handler Logic ->
|
||||
if result := checkMethod(w, r, del); result == eh.Nok {
|
||||
return
|
||||
}
|
||||
|
||||
nextFunc.ServeHTTP(w, r)
|
||||
// <- END Handler Logic
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// checkMethod checks the method type and returns a JSON document (error)
|
||||
// in case of a wrong methed call. This function has its own inner Structure
|
||||
func checkMethod(iw http.ResponseWriter, ir *http.Request,
|
||||
meth string) eh.Result {
|
||||
|
||||
innerAswerStruct := &struct {
|
||||
StatusCode int `json:"status_code,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
}{
|
||||
StatusCode: http.StatusMethodNotAllowed,
|
||||
Description: fmt.Sprintf("Access denied, wrong http method"),
|
||||
Reason: fmt.Sprintf("This controller allows only method -> %v", meth),
|
||||
}
|
||||
|
||||
if ir.Method != meth {
|
||||
|
||||
jsonOutput, err := json.Marshal(innerAswerStruct)
|
||||
if err != nil {
|
||||
panic("Can not recover panic, kill this routine without to give the client a answer")
|
||||
}
|
||||
|
||||
iw.WriteHeader(http.StatusMethodNotAllowed)
|
||||
iw.Write(jsonOutput)
|
||||
log.Warnf("Request stopped - Wrong Http method -> (%v | Received: %v | Wanted: %v)",
|
||||
ir.RemoteAddr, ir.Method, meth)
|
||||
|
||||
return eh.Nok
|
||||
}
|
||||
|
||||
return eh.Ok
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: inputOutputLogger.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package middlewareFunctions
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions: Middleware functionality
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// MWareInOutLogger loggs every entry in the server. In case of a goroutine
|
||||
// crash, its possible to see here whether a call is left unanswered
|
||||
func MWareInOutLogger(nextFunc http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// BEGIN Handler Logic ->
|
||||
reqPath := r.RequestURI
|
||||
remoteAddr := r.RemoteAddr
|
||||
|
||||
log.Infof("Processing order received for: (Controller and KEY -> %v) from -> (%v) ",
|
||||
reqPath, remoteAddr)
|
||||
|
||||
nextFunc.ServeHTTP(w, r)
|
||||
|
||||
log.Infof("Processing completed successfully for -> (%v) and JOB -> (Controller and KEY -> %v)",
|
||||
remoteAddr, reqPath)
|
||||
// <- END Handler Logic
|
||||
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: urlIntegretyCHecker.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package middlewareFunctions
|
||||
|
||||
import (
|
||||
"errors"
|
||||
es "essentials"
|
||||
"fmt"
|
||||
eh "kvmstoreserver_utils/errorHandling"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Declarations
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
var validParams = []string{"rev", "search"}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions: Middleware functionality
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// MWareCheckKeyInURL checks if a key name exist in the the URL call
|
||||
// from the client.
|
||||
func MWareCheckKeyInURL(nextFunc http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// BEGIN Handler Logic ->
|
||||
|
||||
keyInUrlwithoutParams := es.CutKeyFromURL(r.RequestURI)
|
||||
|
||||
if keyInUrlwithoutParams == "" ||
|
||||
strings.Contains(keyInUrlwithoutParams, "%26") {
|
||||
|
||||
result := eh.IfErrBuildJSONAndOrPanic(w,
|
||||
errors.New("Missing key name as a segment of the URL"),
|
||||
http.StatusBadRequest, "Error in Middleware", es.DontPanic)
|
||||
|
||||
log.Warnf("Request without key name received and abort from -> (%v)",
|
||||
r.RemoteAddr)
|
||||
|
||||
if result != eh.Ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
nextFunc.ServeHTTP(w, r)
|
||||
// <- END Handler Logic
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// MwareCheckParamIntegrity allows only the known parameters
|
||||
// (define in validParams). All other parameter calls are not allowed
|
||||
func MwareCheckParamIntegrity(nextFunc http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// BEGIN Handler Logic ->
|
||||
outer:
|
||||
for param := range r.URL.Query() {
|
||||
for _, vaildParam := range validParams {
|
||||
if param == vaildParam {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
|
||||
result := eh.IfErrBuildJSONAndOrPanic(w,
|
||||
fmt.Errorf("This parameter is not allowed -> (%v)", param),
|
||||
http.StatusBadRequest, "Error in Middleware", es.DontPanic)
|
||||
|
||||
log.Warnf("Request aborted - unknown parameter -> (%v) was detected from -> (%v)",
|
||||
param, r.RemoteAddr)
|
||||
|
||||
if result != eh.Ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
nextFunc.ServeHTTP(w, r)
|
||||
// <- END Handler Logic
|
||||
|
||||
})
|
||||
}
|
||||
217
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/btree.go
Executable file
217
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/btree.go
Executable file
@@ -0,0 +1,217 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: btree.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package bTreeHandling contains all the components that are necessary for the
|
||||
// operation of the binary tree. Some components, such as MetaData, are not
|
||||
// required, but are included here. The Pakage implements the Signleton
|
||||
// Pattern. If this is removed, this package can be partially used as a
|
||||
// stand-alone data type
|
||||
package bTreeHandling
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
knh "kvmstoreserver_utils/keyNameHandling"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Declarations
|
||||
//*
|
||||
//*****************************************************************************
|
||||
var (
|
||||
// This reference is always transported to the outside
|
||||
// after the first creation
|
||||
binTree *btree
|
||||
|
||||
// Is necessary for mapping the tree into a slice
|
||||
nodeMatrixSlice []*nodeMatrix
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* STRUCTURE: Btree (Public)
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// btree includes a reference to nodeCOntainer and provides the
|
||||
// only known node (root)
|
||||
//
|
||||
// Implement: IBtreeController
|
||||
type btree struct {
|
||||
root *nodeContainer
|
||||
}
|
||||
|
||||
//********************* Iface Methods: IBtreeController ***********************
|
||||
|
||||
// Member checks if a node exists with the passed key context in the tree.
|
||||
func (slf *btree) Member(nodeCtx knh.IHandelWithIds) error {
|
||||
|
||||
if slf.root != nil {
|
||||
return slf.root.member(nodeCtx)
|
||||
}
|
||||
|
||||
return fmt.Errorf("Can not find a ressource with key name -> %v",
|
||||
nodeCtx.GetKeyStrName())
|
||||
}
|
||||
|
||||
// InsertContainer a complete container in the Tree.
|
||||
// Is it only used by the node loader -> stage0_ext1
|
||||
func (slf *btree) InsertContainer(ct IHandelWithNodes) {
|
||||
|
||||
if slf.root == nil {
|
||||
slf.root = (ct).(*nodeContainer)
|
||||
} else {
|
||||
slf.root.insertContainer(ct)
|
||||
}
|
||||
}
|
||||
|
||||
// Insert a dataModel in the tree. the position (nodeID) is
|
||||
// read from the key context.
|
||||
func (slf *btree) Insert(nodeCtx knh.IHandelWithIds, data *DataModel) (int, error) {
|
||||
|
||||
if slf.root == nil {
|
||||
slf.root = newNode(nodeCtx)
|
||||
log.Infof("Create new ROOT node with (ID: %v) for (Key name: %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
|
||||
return slf.root.insertData(data)
|
||||
}
|
||||
|
||||
return slf.root.insert(nodeCtx, data)
|
||||
}
|
||||
|
||||
// Get returns an interface to the node container.
|
||||
// This can be used to access data in the node contianer
|
||||
func (slf *btree) Get(nodeCtx knh.IHandelWithIds) IHandelWithNodes {
|
||||
|
||||
return slf.root.get(nodeCtx)
|
||||
}
|
||||
|
||||
// Del empties the node container and deletes the information on the disk.
|
||||
// The Contian itself remains intact during the term of the program and
|
||||
// can be addressed and filled as needed
|
||||
func (slf *btree) Del(nodeCtx knh.IHandelWithIds) error {
|
||||
|
||||
return slf.root.del(nodeCtx)
|
||||
}
|
||||
|
||||
//******************** Tree representation ************************************
|
||||
|
||||
/*
|
||||
In this section is the complete functionality to map the Btree into a slice.
|
||||
|
||||
It calls mapTreeIntoSlice recrucively and goes down the whole tree on the left
|
||||
until it meets an end. Then the call goes back one step and takes the right
|
||||
branch. If this is not empty, the function tries again first on the left side
|
||||
to an end, then goes back one step and so goes the recursive call until the
|
||||
tree is worked from bottom left to bottom right
|
||||
*/
|
||||
|
||||
type nodeMatrix struct {
|
||||
NodeID int `json:"node_id,omitempty"`
|
||||
IsRootNode bool `json:"is_root_node"`
|
||||
BranchLeftID int `json:"branch_left_id,omitempty"`
|
||||
BranchRightID int `json:"branch_right_id,omitempty"`
|
||||
}
|
||||
|
||||
type emptyTree struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// GetBtreeStruct returns the structure of the tree mapped
|
||||
// into a slice. The slice is also converted into a JSON document
|
||||
func (slf *btree) GetBtreeStruct() []byte {
|
||||
|
||||
nodeMatrixSlice = make([]*nodeMatrix, 0)
|
||||
mapTreeIntoSlice(slf.root, true)
|
||||
jsonOutput, _ := json.Marshal(&nodeMatrixSlice)
|
||||
if len(jsonOutput) <= 2 {
|
||||
empty := &emptyTree{
|
||||
Message: "The Tree is empty :(",
|
||||
}
|
||||
jsonEmpty, _ := json.Marshal(empty)
|
||||
return jsonEmpty
|
||||
}
|
||||
|
||||
nodeMatrixSlice = nil
|
||||
return jsonOutput
|
||||
}
|
||||
|
||||
func mapTreeIntoSlice(nc *nodeContainer, isRoot bool) {
|
||||
|
||||
if nc == nil {
|
||||
return
|
||||
}
|
||||
|
||||
newNodeInfo := nodeMatrix{}
|
||||
newNodeInfo.IsRootNode = isRoot
|
||||
if nc.BranchLeft != nil {
|
||||
newNodeInfo.BranchLeftID = nc.BranchLeft.NodeID
|
||||
}
|
||||
if nc.BranchRight != nil {
|
||||
newNodeInfo.BranchRightID = nc.BranchRight.NodeID
|
||||
}
|
||||
newNodeInfo.NodeID = nc.NodeID
|
||||
|
||||
nodeMatrixSlice = append(nodeMatrixSlice, &newNodeInfo)
|
||||
|
||||
mapTreeIntoSlice(nc.BranchLeft, false)
|
||||
mapTreeIntoSlice(nc.BranchRight, false)
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// NewBtree generates a new empty tree on the first call and saves it in the
|
||||
// global variable of the package. Each call causes only the reference to the
|
||||
// global variable to be passed on
|
||||
func NewBtree() IBtreeController {
|
||||
|
||||
if binTree == nil {
|
||||
binTree = &btree{}
|
||||
return binTree
|
||||
}
|
||||
|
||||
return binTree
|
||||
}
|
||||
72
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/dataModel.go
Executable file
72
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/dataModel.go
Executable file
@@ -0,0 +1,72 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: dataModel.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package bTreeHandling
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: DataModel
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// DataModel Contains the revision number, the metadata, and the JSON document
|
||||
// stored in a mapped interface structure
|
||||
type DataModel struct {
|
||||
RevNbr int `json:"rev_nbr"`
|
||||
MetaHeader *MetaData `json:"meta_header"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// Search picks up a string and views the identifier in the map
|
||||
func (slf *DataModel) Search(s string) (interface{}, error) {
|
||||
|
||||
// If a key exists but is NIL, this information will also be returned as Go
|
||||
// NIL. Otherwise an ERROR
|
||||
for mKeyName := range slf.Data {
|
||||
if s == mKeyName {
|
||||
return slf.Data[s], nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("There is no element in the values map with this name -> %v",
|
||||
s)
|
||||
}
|
||||
84
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/interfaces.go
Executable file
84
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/interfaces.go
Executable file
@@ -0,0 +1,84 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: interfaces.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package bTreeHandling
|
||||
|
||||
import knh "kvmstoreserver_utils/keyNameHandling"
|
||||
|
||||
// IBtreeController includes the logic that is needed from the
|
||||
// outside to use the tree
|
||||
type IBtreeController interface {
|
||||
|
||||
// Insert a dataModel in the tree. the position (nodeID) is
|
||||
// read from the key context.
|
||||
Insert(nodeCtx knh.IHandelWithIds, data *DataModel) (int, error)
|
||||
|
||||
// InsertContainer a complete container in the Tree.
|
||||
// Is it only used by the node loader -> stage0_ext1
|
||||
InsertContainer(ct IHandelWithNodes)
|
||||
|
||||
// Member Checks if a node exists with the passed key context in the tree.
|
||||
Member(nodeCtx knh.IHandelWithIds) error
|
||||
|
||||
// Get returns an interface to the node container.
|
||||
// This can be used to access data in the node contianer
|
||||
Get(nodeCtx knh.IHandelWithIds) IHandelWithNodes
|
||||
|
||||
// Del deletes a complete node Container from the tree
|
||||
Del(nodeCtx knh.IHandelWithIds) error
|
||||
|
||||
// GetBtreeStruct returns the structure of the tree mapped
|
||||
// into a slice. The slice is also converted into a JSON document
|
||||
GetBtreeStruct() []byte
|
||||
}
|
||||
|
||||
// IHandelWithNodes includes the logic that is needed to work
|
||||
// with node containers. The caller always keeps this interface,
|
||||
// never the non-exported node container structure
|
||||
type IHandelWithNodes interface {
|
||||
|
||||
// GetID returns the node container ID
|
||||
GetID() int
|
||||
|
||||
// GetOrigKeyName returns the origianl Key name
|
||||
GetOrigKeyName() string
|
||||
|
||||
// GetModelOrDefault provides the required revision of the
|
||||
// DataModel. Default is the last and most recent
|
||||
GetModelOrDefault(revNbr *int) (*DataModel, error)
|
||||
}
|
||||
75
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/metaData.go
Executable file
75
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/metaData.go
Executable file
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: metaData.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package bTreeHandling
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: metaData
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// MetaData Contains the meta information of a DataModel.
|
||||
type MetaData struct {
|
||||
// Address of the caller client
|
||||
RemoteAddr string `json:"remote_addr"`
|
||||
|
||||
// When was the data model created in this server?
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// NewMetaData Generates a new MetaData object and fills it with
|
||||
// the necessary infomations
|
||||
func NewMetaData(req *http.Request) *MetaData {
|
||||
|
||||
return &MetaData{
|
||||
RemoteAddr: req.RemoteAddr,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
334
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/nodeContainer.go
Executable file
334
kvmstoreserver_solution/src/kvmstoreserver_utils/bTreeHandling/nodeContainer.go
Executable file
@@ -0,0 +1,334 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: nodeContainer.go
|
||||
* Version: 1.0.0
|
||||
* Date: 1970-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package bTreeHandling
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
es "essentials"
|
||||
"fmt"
|
||||
knh "kvmstoreserver_utils/keyNameHandling"
|
||||
sh "kvmstoreserver_utils/serdeHandling"
|
||||
"sync"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: nodeContainer
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// nodeContainer includes all the elements necessary to store
|
||||
// data and create and maintain the node in the tree
|
||||
//
|
||||
// Implement: IHandelWithNodes, IHandelSerialization
|
||||
type nodeContainer struct {
|
||||
NodeID int `json:"node_id"`
|
||||
OrigKeyName string `json:"orig_key_name"`
|
||||
WriteLock sync.Mutex `json:"-"`
|
||||
|
||||
BranchLeft *nodeContainer `json:"-"`
|
||||
BranchRight *nodeContainer `json:"-"`
|
||||
|
||||
DataContainer []*DataModel `json:"data_container"`
|
||||
}
|
||||
|
||||
//******************** Methods ************************************************
|
||||
|
||||
// member checks if a node exists with the passed key context in the tree.
|
||||
func (slf *nodeContainer) member(nodeCtx knh.IHandelWithIds) error {
|
||||
|
||||
if slf.NodeID == nodeCtx.GetNodeID() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Left Handling
|
||||
if nodeCtx.GetNodeID() < slf.NodeID {
|
||||
if slf.BranchLeft != nil {
|
||||
return slf.BranchLeft.member(nodeCtx)
|
||||
}
|
||||
} else {
|
||||
// Right Handling
|
||||
if slf.BranchRight != nil {
|
||||
return slf.BranchRight.member(nodeCtx)
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("Tried to find a node, but it seems it is not a member -> (Node: %v) - (Origianl Key Name: %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
|
||||
return fmt.Errorf("Can not find a ressource with key name -> %v",
|
||||
nodeCtx.GetKeyStrName())
|
||||
}
|
||||
|
||||
// insertContainer a complete container in the Tree.
|
||||
// Is it only used by the node loader -> stage0_ext1
|
||||
func (slf *nodeContainer) insertContainer(ct IHandelWithNodes) {
|
||||
|
||||
// Left Handling
|
||||
if ct.GetID() < slf.NodeID {
|
||||
if slf.BranchLeft == nil {
|
||||
slf.BranchLeft = (ct).(*nodeContainer)
|
||||
return
|
||||
}
|
||||
slf.BranchLeft.insertContainer(ct)
|
||||
} else if ct.GetID() > slf.NodeID {
|
||||
// Right Handling
|
||||
if slf.BranchRight == nil {
|
||||
slf.BranchRight = (ct).(*nodeContainer)
|
||||
return
|
||||
}
|
||||
slf.BranchRight.insertContainer(ct)
|
||||
}
|
||||
}
|
||||
|
||||
// insert a dataModel in the tree. the position (nodeID) is
|
||||
// read from the key context.
|
||||
func (slf *nodeContainer) insert(nodeCtx knh.IHandelWithIds,
|
||||
data *DataModel) (int, error) {
|
||||
|
||||
if slf.NodeID == nodeCtx.GetNodeID() {
|
||||
return slf.insertData(data)
|
||||
}
|
||||
|
||||
// Left branch handling
|
||||
if nodeCtx.GetNodeID() < slf.NodeID {
|
||||
if slf.BranchLeft == nil {
|
||||
slf.BranchLeft = newNode(nodeCtx)
|
||||
|
||||
log.Infof("Create new node with (ID: %v) for (Key name: %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
|
||||
return slf.BranchLeft.insertData(data)
|
||||
}
|
||||
|
||||
return slf.BranchLeft.insert(nodeCtx, data)
|
||||
}
|
||||
// Right branch handling
|
||||
if slf.BranchRight == nil {
|
||||
slf.BranchRight = newNode(nodeCtx)
|
||||
|
||||
log.Infof("Create new node with (ID: %v) for (Key name: %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
|
||||
return slf.BranchRight.insertData(data)
|
||||
}
|
||||
|
||||
return slf.BranchRight.insert(nodeCtx, data)
|
||||
}
|
||||
|
||||
// get returns an interface to the node container.
|
||||
// This can be used to access data in the node contianer
|
||||
func (slf *nodeContainer) get(nodeCtx knh.IHandelWithIds) IHandelWithNodes {
|
||||
|
||||
if slf.NodeID == nodeCtx.GetNodeID() {
|
||||
log.Infof("Node found and returned -> (Node: %v) - (Origianl Key Name: %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
|
||||
return slf
|
||||
}
|
||||
|
||||
// Left Handling
|
||||
if nodeCtx.GetNodeID() < slf.NodeID {
|
||||
return slf.BranchLeft.get(nodeCtx)
|
||||
}
|
||||
|
||||
// Right Handling
|
||||
return slf.BranchRight.get(nodeCtx)
|
||||
}
|
||||
|
||||
// del empties the node container and deletes the information on the disk.
|
||||
// The Contian itself remains intact during the term of the program and
|
||||
// can be addressed and filled as needed
|
||||
func (slf *nodeContainer) del(nodeCtx knh.IHandelWithIds) error {
|
||||
|
||||
if slf.NodeID == nodeCtx.GetNodeID() {
|
||||
|
||||
if slf.DataContainer != nil {
|
||||
deleteStorage := sh.DriverFactory(es.Delete)
|
||||
if delErr := deleteStorage(slf); delErr != nil {
|
||||
|
||||
log.Infof("Internal storage problem, can not delete node with -> (ID: %v) | (Key name: %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
|
||||
return fmt.Errorf("Internal storage problem, can not delete node with -> (ID: %v) | (Key name: %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
}
|
||||
|
||||
slf.DataContainer = nil
|
||||
|
||||
log.Infof("Deleted all datas of -> (Node: %v) - (Origianl Key Name %v)",
|
||||
nodeCtx.GetNodeID(), nodeCtx.GetKeyStrName())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Infof("The container with the key \"%V\" is empty, there is nothing to delete in it",
|
||||
nodeCtx.GetKeyStrName())
|
||||
|
||||
return fmt.Errorf("The container with the key \"%v\" is empty, there is nothing to delete in it",
|
||||
nodeCtx.GetKeyStrName())
|
||||
}
|
||||
|
||||
// Left Handling
|
||||
if nodeCtx.GetNodeID() < slf.NodeID {
|
||||
return slf.BranchLeft.del(nodeCtx)
|
||||
}
|
||||
|
||||
// Right Handling
|
||||
return slf.BranchRight.del(nodeCtx)
|
||||
|
||||
}
|
||||
|
||||
// insertData writes the data (DataModel) into the slice of the container.
|
||||
// The container is locked during this operation (RW)
|
||||
func (slf *nodeContainer) insertData(data *DataModel) (int, error) {
|
||||
|
||||
defer slf.WriteLock.Unlock()
|
||||
slf.WriteLock.Lock()
|
||||
|
||||
lastRevNbr := len(slf.DataContainer)
|
||||
data.RevNbr = lastRevNbr
|
||||
slf.DataContainer = append(slf.DataContainer, data)
|
||||
|
||||
saveStorage := sh.DriverFactory(es.Save)
|
||||
|
||||
if saveErr := saveStorage(slf); saveErr != nil {
|
||||
slf.DataContainer[lastRevNbr] = nil
|
||||
|
||||
log.Infof("A storage medium error prevented the creation of the new revision -> (Rev: %v) -> (Current: %v)",
|
||||
lastRevNbr, lastRevNbr-1)
|
||||
|
||||
return 0, fmt.Errorf("A storage medium error prevented the creation of the new revision -> (Rev: %v) -> (Current: %v)",
|
||||
lastRevNbr, lastRevNbr-1)
|
||||
|
||||
}
|
||||
|
||||
log.Infof("Inserted new content into -> (Node: %v) - (Origianl Key Name: %v) | (Current RevNbr.: %v)",
|
||||
slf.NodeID, slf.OrigKeyName, lastRevNbr)
|
||||
|
||||
return lastRevNbr, nil
|
||||
}
|
||||
|
||||
//******************** Interface: IHandelWithNodes ****************************
|
||||
|
||||
// GetID returns the node container ID
|
||||
func (slf *nodeContainer) GetID() int { return slf.NodeID }
|
||||
|
||||
// GetOrigKeyName returns the origianl Key name
|
||||
func (slf *nodeContainer) GetOrigKeyName() string { return slf.OrigKeyName }
|
||||
|
||||
// GetModelOrDefault provides the required revision of the
|
||||
// DataModel. Default is the last and most recent
|
||||
func (slf *nodeContainer) GetModelOrDefault(revNbr *int) (*DataModel, error) {
|
||||
|
||||
if slf.DataContainer != nil {
|
||||
sliceLenght := len(slf.DataContainer)
|
||||
if revNbr != nil {
|
||||
if sliceLenght > *revNbr && *revNbr >= 0 {
|
||||
return slf.DataContainer[*revNbr], nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf(
|
||||
"Can not find the revision number - Valid range for this key -> 0 - %v",
|
||||
sliceLenght-1)
|
||||
}
|
||||
|
||||
return slf.DataContainer[sliceLenght-1], nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf(
|
||||
`The container with the name "%v" existed once, but its contents were deleted`,
|
||||
slf.OrigKeyName)
|
||||
}
|
||||
|
||||
//******************** Interface: IHandelSerialization ************************
|
||||
|
||||
// GetNodeID redirect to GetID() and retruns the node container ID
|
||||
func (slf *nodeContainer) GetNodeID() int {
|
||||
return slf.NodeID
|
||||
}
|
||||
|
||||
// Marshal generates a JSON document form its self
|
||||
func (slf *nodeContainer) Marshal() []byte {
|
||||
|
||||
jsonOutput, _ := json.Marshal(slf)
|
||||
|
||||
return jsonOutput
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// newNode generates a new empty node with the ID from key context
|
||||
func newNode(nodeCtx knh.IHandelWithIds) *nodeContainer {
|
||||
|
||||
return &nodeContainer{
|
||||
NodeID: nodeCtx.GetNodeID(),
|
||||
OrigKeyName: nodeCtx.GetKeyStrName(),
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// CreateContainerFromSource creates a complete new node container, which was
|
||||
// picked up by the filessystem loader and converted into a reader
|
||||
func CreateContainerFromSource(r *bytes.Reader) IHandelWithNodes {
|
||||
|
||||
var newContainer nodeContainer
|
||||
jsonDecoder := json.NewDecoder(r)
|
||||
|
||||
decodeErr := jsonDecoder.Decode(&newContainer)
|
||||
if decodeErr != nil {
|
||||
errMsg := fmt.Sprintf("Apparently, manipulations have been made to a file. Abort (OrigMsg)-> %v",
|
||||
decodeErr.Error())
|
||||
panic(errMsg)
|
||||
}
|
||||
|
||||
return &newContainer
|
||||
}
|
||||
86
kvmstoreserver_solution/src/kvmstoreserver_utils/errorHandling/catcher.go
Executable file
86
kvmstoreserver_solution/src/kvmstoreserver_utils/errorHandling/catcher.go
Executable file
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: catcher.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package errorHandling
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
es "essentials"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// IfErrBuildJSONAndOrPanic accepts the responewriter, the origianl error,
|
||||
// an HTTP congestion code and its own message. If the error !s= nil, you can
|
||||
// use the control enum to define whether this function should trigger a panic
|
||||
// or simply output an error per result
|
||||
func IfErrBuildJSONAndOrPanic(writer http.ResponseWriter,
|
||||
origErr error, statusCode int, customErrMsg string, doPanic es.Control) Result {
|
||||
|
||||
if origErr != nil {
|
||||
|
||||
if customErrMsg == "" {
|
||||
customErrMsg = "No further description"
|
||||
}
|
||||
|
||||
innerAswerStruct := &struct {
|
||||
StatusCode int `json:"status_code"`
|
||||
Description string `json:"description"`
|
||||
OriginalErrorMessage string `json:"original_error_message"`
|
||||
}{
|
||||
StatusCode: statusCode,
|
||||
Description: customErrMsg,
|
||||
OriginalErrorMessage: origErr.Error(),
|
||||
}
|
||||
|
||||
jsonOutput, err := json.Marshal(innerAswerStruct)
|
||||
if err != nil {
|
||||
panic("Can not recover panic, kill this routine without to give the client a answer")
|
||||
}
|
||||
|
||||
writer.WriteHeader(statusCode)
|
||||
writer.Write(jsonOutput)
|
||||
|
||||
if doPanic == es.DoPanic {
|
||||
panic(innerAswerStruct.OriginalErrorMessage)
|
||||
}
|
||||
|
||||
return Nok
|
||||
}
|
||||
|
||||
return Ok
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: checkErrAndForward.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package errorHandling
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// [OBSOLETE]
|
||||
// This is a future function. It is not integrated in this project
|
||||
|
||||
// CheckErrAndForward picks up an error and checks if it is != nil, if so then
|
||||
// you can add your own message and forward it. Allows the formation of error
|
||||
// chains (Error handling CI -> Caller Informed)
|
||||
func CheckErrAndForward(origErrMsg error, customMsg string) error {
|
||||
|
||||
if origErrMsg != nil {
|
||||
if customMsg != "" {
|
||||
return fmt.Errorf("(Additional Msg -> %v) | (Orig Msg)-> %v",
|
||||
customMsg, origErrMsg.Error())
|
||||
}
|
||||
return origErrMsg
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
52
kvmstoreserver_solution/src/kvmstoreserver_utils/errorHandling/result.go
Executable file
52
kvmstoreserver_solution/src/kvmstoreserver_utils/errorHandling/result.go
Executable file
@@ -0,0 +1,52 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: result.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package errorHandling
|
||||
|
||||
// Result is a type wrapper to a uint8. Is intended for situations where
|
||||
// there is a static error message and no error must be generated, but only
|
||||
// announced that one is present
|
||||
type Result uint8
|
||||
|
||||
const (
|
||||
// Ok result
|
||||
Ok Result = iota
|
||||
|
||||
// Nok result
|
||||
Nok
|
||||
)
|
||||
60
kvmstoreserver_solution/src/kvmstoreserver_utils/errorHandling/try.go
Executable file
60
kvmstoreserver_solution/src/kvmstoreserver_utils/errorHandling/try.go
Executable file
@@ -0,0 +1,60 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: try.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package errorHandling
|
||||
|
||||
import (
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
// Try can be used in a handler function via defer. In combination with
|
||||
// IfErrBuildJSONAndOrPanic you can panic an error directly from the code and
|
||||
// try prevents the goroutine to crash
|
||||
func Try(posText string) {
|
||||
|
||||
if err := recover(); err != nil {
|
||||
if posText == "" {
|
||||
posText = "Unknown Position!"
|
||||
}
|
||||
|
||||
log.Warnf("A PANIC was recovered: Position-> %v | (Orig Err Message)-> %v",
|
||||
posText, err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: interfaces.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package keyNameHandling
|
||||
|
||||
// IHandelWithIds works as a getter interface. This is
|
||||
// necessary so that the structure keyContext does not
|
||||
// have to be exported. So nobody can manipulate data
|
||||
// into the structure. This interface only realizes read
|
||||
// only capabilities
|
||||
type IHandelWithIds interface {
|
||||
// GetKeyStrName returns the value stored in the structure
|
||||
GetKeyStrName() string
|
||||
|
||||
// GetNodeID returns the value stored in the structure
|
||||
GetNodeID() int
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: keyNameToIdConverter.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package keyNameHandling contains all the logic needed to convert a key
|
||||
// (string) to an id (int).
|
||||
//
|
||||
// The transformation process was developed especially for this work
|
||||
package keyNameHandling
|
||||
|
||||
// nolint
|
||||
import (
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: keyContext
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// KeyContext takes the original key and forms or calculates
|
||||
// all necessary parameters. This holds it in, so you can access
|
||||
// it from the outside through the interface
|
||||
type keyContext struct {
|
||||
keyNameAsString string
|
||||
keyMd5Hash [16]byte
|
||||
|
||||
// Here is the calculated node ID where the data should be stored
|
||||
dataNodeID int
|
||||
}
|
||||
|
||||
/********************* Methods ************************************************/
|
||||
|
||||
// defDataNodeID - The functionality is described in detail in the documentation
|
||||
func (slf *keyContext) defDataNodeID() {
|
||||
|
||||
var uniqueIdentifierStr string
|
||||
|
||||
for idx := 0; idx < 6; idx++ {
|
||||
uniqueIdentifierStr += strconv.Itoa(int(slf.keyMd5Hash[idx]))
|
||||
}
|
||||
|
||||
uniqueIdentifier, _ := strconv.ParseInt(uniqueIdentifierStr, 10, 64)
|
||||
slf.dataNodeID = int(uniqueIdentifier)
|
||||
}
|
||||
|
||||
// nolint
|
||||
// defChkSum calc the checksum from the name (in string form)
|
||||
func (slf *keyContext) defChkSum() {
|
||||
slf.keyMd5Hash = md5.Sum([]byte(slf.keyNameAsString))
|
||||
}
|
||||
|
||||
/********************* Interface: IHandelWithIds ******************************/
|
||||
|
||||
// GetKeyStrName returns the plain text key name from the structure
|
||||
func (slf *keyContext) GetKeyStrName() string { return slf.keyNameAsString }
|
||||
|
||||
// GetNodeId returns the calculated Node ID from the structure
|
||||
func (slf *keyContext) GetNodeID() int { return slf.dataNodeID }
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// NewKeyContext Returns the interface IHandelWithIds, which
|
||||
// contains all information on the following points:
|
||||
//
|
||||
// - Original Key Name as string
|
||||
// - The ID of the node where to save or read data
|
||||
func NewKeyContext(key string) (IHandelWithIds, error) {
|
||||
|
||||
var kc keyContext
|
||||
|
||||
// A backup to prevent blank input
|
||||
secKey := strings.Trim(key, " ")
|
||||
if len(secKey) == 0 {
|
||||
return &kc, errors.New("Key name is a empty string")
|
||||
}
|
||||
|
||||
kc.keyNameAsString = key
|
||||
kc.defChkSum()
|
||||
kc.defDataNodeID()
|
||||
|
||||
return &kc, nil
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: keyNameToIdConverter_test.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-13
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package keyNameHandling
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewKeyContext(t *testing.T) {
|
||||
|
||||
// Crate comparative data
|
||||
var iHandelWithIdsTestsystem1000 IHandelWithIds = &keyContext{
|
||||
dataNodeID: 23451191704648,
|
||||
keyNameAsString: "Testsystem_Name_1000",
|
||||
}
|
||||
var iHandelWithIdsTheodor IHandelWithIds = &keyContext{
|
||||
dataNodeID: 8018417516249221,
|
||||
keyNameAsString: "Theodor",
|
||||
}
|
||||
var iHandelWithIdstheodor IHandelWithIds = &keyContext{
|
||||
dataNodeID: 25422015718236214,
|
||||
keyNameAsString: "theodor",
|
||||
}
|
||||
|
||||
// Create test data
|
||||
tests := []struct {
|
||||
name string
|
||||
key string
|
||||
want IHandelWithIds
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "Test 1: with key name -> Testsystem_Name_1000", key: "Testsystem_Name_1000", want: iHandelWithIdsTestsystem1000, wantErr: false},
|
||||
{name: "Test 2: with key name -> Theodor", key: "Theodor", want: iHandelWithIdsTheodor, wantErr: false},
|
||||
{name: "Test 3: with key name -> theodor", key: "theodor", want: iHandelWithIdstheodor, wantErr: false},
|
||||
}
|
||||
|
||||
// Execute the test series
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := NewKeyContext(tt.key)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewKeyContext() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
// Add the generated MD5 checksum to the comparative data
|
||||
// (only the checksum)
|
||||
(tt.want).(*keyContext).keyMd5Hash = (got).(*keyContext).keyMd5Hash
|
||||
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("NewKeyContext() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: componentFactory.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package serdeHandling contains everything necessary to access a storage
|
||||
// medium (currently only hard disk in this version). In later versions, the
|
||||
// area SQL will be covered. This package offers two functions to decide by
|
||||
// parameter which type of storage media should be used (Factory). A distinction
|
||||
// is made between driver factory and loader factory. Loader facory provides
|
||||
// functions that return pre-made readers.
|
||||
package serdeHandling
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
es "essentials"
|
||||
"utils/configMap"
|
||||
)
|
||||
|
||||
// DriverFactory returns a function suitable for the storage medium. A
|
||||
// distinction is made between saving and deleting. These functions are mainly
|
||||
// needed at runtime
|
||||
func DriverFactory(action es.Control) func(node IHandelSerialization) error {
|
||||
|
||||
switch configMap.GetStringOf("serde_driver") {
|
||||
|
||||
case "filesystem":
|
||||
if action == es.Delete {
|
||||
return deleteFromFileSystem
|
||||
}
|
||||
return saveToFileSystem
|
||||
|
||||
case "mssql":
|
||||
panic("The MSSql driver is not available in this version")
|
||||
|
||||
case "postgres":
|
||||
panic("The Postgres (CockroachDB) driver is not available in this version")
|
||||
|
||||
default:
|
||||
panic("Unknown store system driver - Please check the VAR -serde_driver- in your config file")
|
||||
}
|
||||
}
|
||||
|
||||
// LoaderFactory returns a function suitable for the storage medium.
|
||||
// These functions are mainly needed at start time (loader)
|
||||
func LoaderFactory() func(nodeID int) *bytes.Reader {
|
||||
|
||||
switch configMap.GetStringOf("serde_driver") {
|
||||
|
||||
case "filesystem":
|
||||
return loadContainerFormDisk
|
||||
case "mssql":
|
||||
panic("The MSSql driver is not available in this version")
|
||||
|
||||
case "postgres":
|
||||
panic("The Postgres (CockroachDB) driver is not available in this version")
|
||||
|
||||
default:
|
||||
panic("Unknown store system driver - Please check the VAR -serde_driver- in your config file")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: fileSystemDriver.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package serdeHandling
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"utils/configMap"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Exported through factory
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// SaveToFileSystem writes the node container to hard disk
|
||||
func saveToFileSystem(node IHandelSerialization) error {
|
||||
|
||||
if err := ioutil.WriteFile(defineFilePath(node.GetNodeID()),
|
||||
node.Marshal(), 0660); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// deleteFromFileSystem deletes the file which contains the content
|
||||
// of the node from the hard disk
|
||||
func deleteFromFileSystem(node IHandelSerialization) error {
|
||||
|
||||
if err := os.Remove(defineFilePath(node.GetNodeID())); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadContainer loads the JSON content of the complete node container
|
||||
// from the hard disk as byte array and puts all into a reader.
|
||||
func loadContainerFormDisk(nodeID int) *bytes.Reader {
|
||||
|
||||
fullPath := defineFilePath(nodeID)
|
||||
fileContent, loadErr := ioutil.ReadFile(fullPath)
|
||||
if loadErr != nil {
|
||||
log.Fatalf("Error by loading file from disk -> (%v)",
|
||||
fullPath)
|
||||
}
|
||||
|
||||
newReader := bytes.NewReader(fileContent)
|
||||
|
||||
return newReader
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// defineFilePath defines the full file path of the serialized
|
||||
// node container content based on the base path from the config file +
|
||||
// the node ID
|
||||
func defineFilePath(i int) string {
|
||||
|
||||
strNodeID := strconv.Itoa(i)
|
||||
fullPath := configMap.GetStringOf("storage_target") + "/" + strNodeID + ".json"
|
||||
|
||||
return fullPath
|
||||
}
|
||||
50
kvmstoreserver_solution/src/kvmstoreserver_utils/serdeHandling/interfaces.go
Executable file
50
kvmstoreserver_solution/src/kvmstoreserver_utils/serdeHandling/interfaces.go
Executable file
@@ -0,0 +1,50 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: interfaces.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-14
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package serdeHandling
|
||||
|
||||
// IHandelSerialization defines how the functions come to the node ID
|
||||
// and the finished JSON document
|
||||
type IHandelSerialization interface {
|
||||
|
||||
// GetNodeID return the node ID
|
||||
GetNodeID() int
|
||||
|
||||
// Marshal retruns a byte array from the node container
|
||||
Marshal() []byte
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: General use
|
||||
* File name: functionChainBuilder.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2017-08-20
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of functionChainBuilder.
|
||||
*
|
||||
* functionChainBuilder is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* functionChainBuilder is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with functionChainBuilder. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
/*
|
||||
Package functionChainBuilder ...
|
||||
*/
|
||||
package functionChainBuilder
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Declarations
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// First-Class-Function definitions
|
||||
// Here they serve as aliases to keep the signatures of methods / functions in
|
||||
// the code small
|
||||
type middlewareFuncAlias func(nextFunction http.Handler) http.Handler
|
||||
type finalHandlerAlias func(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure ChainContainer
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// ChainContainer includes the middleware funtions and the one
|
||||
// FinalHandler. From the outside, several chains can be formed
|
||||
type ChainContainer struct {
|
||||
middleware []middlewareFuncAlias
|
||||
finalHandler finalHandlerAlias
|
||||
}
|
||||
|
||||
/********************* Methods ************************************************/
|
||||
|
||||
// RegisterFunctions registered functions that correspond
|
||||
// to the signature-type middlewareAlias
|
||||
func (slf *ChainContainer) RegisterFunctions(mWareFuncs ...middlewareFuncAlias) *ChainContainer {
|
||||
|
||||
slf.middleware = append(slf.middleware, mWareFuncs...)
|
||||
|
||||
return slf
|
||||
}
|
||||
|
||||
// SetFinalHandler registers the final handler, which
|
||||
// must contain the central logic of the controller
|
||||
func (slf *ChainContainer) SetFinalHandler(fHandler finalHandlerAlias) *ChainContainer {
|
||||
|
||||
slf.finalHandler = fHandler
|
||||
|
||||
return slf
|
||||
}
|
||||
|
||||
// RunChain checks if a FinalHandler is set and starts
|
||||
// the function chain of the defined series.
|
||||
// If no middleware functions have been defined, the
|
||||
// final handler will always be executed
|
||||
func (slf *ChainContainer) RunChain() http.Handler {
|
||||
|
||||
if slf.finalHandler == nil {
|
||||
panic("Missing Final Handler in Function Chain!")
|
||||
}
|
||||
if slf.middleware != nil {
|
||||
return buildMiddlewareChain(&slf.finalHandler, slf.middleware)
|
||||
}
|
||||
return http.HandlerFunc(slf.finalHandler)
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Function
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// NewChainConatainer creates a new empty structure from type
|
||||
// ChainContainer and return it to the caller
|
||||
func NewChainConatainer() *ChainContainer {
|
||||
|
||||
var cContainer ChainContainer
|
||||
return &cContainer
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// buildMiddlewareChain is based on the standard pattern of go http middleware.
|
||||
func buildMiddlewareChain(fHandler *finalHandlerAlias, mWareFuncs []middlewareFuncAlias) http.Handler {
|
||||
|
||||
if len(mWareFuncs) == 0 {
|
||||
return http.HandlerFunc(*fHandler)
|
||||
}
|
||||
// Unlike the original, this function uses a simple incremental process
|
||||
// in the recursive call (see below). This always starts at 1 (not 0). 0 is
|
||||
// the original caller for the following recursive call. 1 is the new
|
||||
// function form Middleware slice.
|
||||
// Go modifies the static array under the slice for every call that does not
|
||||
// start from the beginning (ie 0). It cuts off the beginning to the defined
|
||||
// value and forms below a new array starting from 0 (in the slice the place
|
||||
// from where you started counting)
|
||||
return mWareFuncs[0](buildMiddlewareChain(fHandler, mWareFuncs[1:]))
|
||||
}
|
||||
250
kvmstoreserver_solution/src/utils/configMap/configMap.go
Executable file
250
kvmstoreserver_solution/src/utils/configMap/configMap.go
Executable file
@@ -0,0 +1,250 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: General use
|
||||
* File name: configMap.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2017-08-19
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of configMap.
|
||||
*
|
||||
* configMap is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* configMap is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with configMap. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package configMap includes the logic to read in a config file and
|
||||
// save it in a folder
|
||||
//
|
||||
// Configuration file pattern -> param name = value
|
||||
package configMap
|
||||
|
||||
// nolint
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"utils/configPoller"
|
||||
|
||||
log "github.com/judwhite/logrjack"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Declarations
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// configurationFile is always transferred to the outside by
|
||||
// reference. Definition takes place in this package.
|
||||
// Implementation of the -Singelton Patterns-
|
||||
var configurations settings
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: ConfigFile
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// settings includes all necessary information from this
|
||||
// package to a config file
|
||||
//
|
||||
// Implement: IUpdateConfig
|
||||
type settings struct {
|
||||
synchronous sync.Mutex
|
||||
isLoaded bool
|
||||
content map[string]string
|
||||
fullFilePath string
|
||||
}
|
||||
|
||||
/********************* Methods ************************************************/
|
||||
|
||||
// loadContent loads a config file as a byte slice and
|
||||
// restructures it as map[string]string
|
||||
func (slf *settings) loadContent() {
|
||||
|
||||
// The loading process is synchronized and all reading
|
||||
// processes have to wait in case of an update
|
||||
slf.synchronous.Lock()
|
||||
defer slf.synchronous.Unlock()
|
||||
|
||||
rawConfFileContent, err := ioutil.ReadFile(slf.fullFilePath)
|
||||
if err != nil {
|
||||
panic("Cannot read file")
|
||||
}
|
||||
|
||||
// Additional line break. Is necessary because of the parser
|
||||
// below. Otherwise the last value of the config file will not be read
|
||||
rawConfFileContent = append(rawConfFileContent, byte('\n'))
|
||||
|
||||
// Reading the byte slice and converting to string slice (raw format).
|
||||
// Separator is "="
|
||||
var newLine string
|
||||
var confFileArray []string
|
||||
for idx := 0; idx < len(rawConfFileContent); idx++ {
|
||||
if rawConfFileContent[idx] != byte('\n') &&
|
||||
rawConfFileContent[idx] != byte('\r') {
|
||||
newLine += string(rawConfFileContent[idx])
|
||||
} else {
|
||||
if strings.Contains(newLine, "\t") {
|
||||
newLine = strings.Replace(newLine, "\t", "", -1)
|
||||
}
|
||||
if strings.Contains(strings.TrimRight(strings.
|
||||
TrimLeft(newLine, " "), " "), "=") {
|
||||
if !strings.HasPrefix(newLine, "#") {
|
||||
newLine = strings.Split(newLine, "#")[0]
|
||||
confFileArray = append(confFileArray, newLine)
|
||||
newLine = ""
|
||||
} else {
|
||||
newLine = ""
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
newLine = ""
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Converting string slice to string-string map and cut all spaces
|
||||
// with function trimAndConvToSting(string, int)
|
||||
slf.content = make(map[string]string)
|
||||
for _, line := range confFileArray {
|
||||
slf.content[trimAndConvToSting(line, 0)] = trimAndConvToSting(line, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/********************* Interface: IUpdateConfig *******************************/
|
||||
|
||||
// GetMd5Sum returns the caller the CheckSum of the config file in
|
||||
// in byte slice shape
|
||||
// nolint
|
||||
func (slf *settings) GetMd5Sum() [16]byte {
|
||||
|
||||
rawConfFileContent, err := ioutil.ReadFile(slf.fullFilePath)
|
||||
if err != nil {
|
||||
panic("Cannot read file")
|
||||
}
|
||||
|
||||
return md5.Sum(rawConfFileContent)
|
||||
}
|
||||
|
||||
// UpdateConfig initialize the update process of this package
|
||||
func (slf *settings) UpdateConfig() error {
|
||||
|
||||
slf.loadContent()
|
||||
|
||||
log.Infof("The configuration has been updated for the following config file -> (%v)",
|
||||
slf.fullFilePath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// Settings generates one instance of the structure ConfigFile
|
||||
// and return it. Every further attempt provides a reference to the
|
||||
// already created instance -Singelton Pattern-
|
||||
func Settings(path string) {
|
||||
|
||||
if !configurations.isLoaded {
|
||||
if path == "" {
|
||||
panic("Need a path to a configuration file")
|
||||
}
|
||||
configurations.fullFilePath = path
|
||||
configurations.loadContent()
|
||||
configurations.isLoaded = true
|
||||
}
|
||||
}
|
||||
|
||||
// GetConfigMapRef ...
|
||||
func GetConfigMapRef() configPoller.IUpdateConfig { return &configurations }
|
||||
|
||||
// GetStringOf returns the search value as string
|
||||
func GetStringOf(search string) string { return configurations.content[search] }
|
||||
|
||||
// GetInt32Of tries to cast the search value into a
|
||||
// int32 and return the result
|
||||
func GetInt32Of(search string) int32 {
|
||||
|
||||
newValue, err := strconv.ParseInt(configurations.content[search], 10, 32)
|
||||
if err != nil {
|
||||
panicMsg := fmt.Sprintf("Cannot convert to INT32 -> %v", configurations.content[search])
|
||||
panic(panicMsg)
|
||||
}
|
||||
|
||||
return (int32)(newValue)
|
||||
}
|
||||
|
||||
// GetFloat32Of tries to cast the search value into a
|
||||
// float32 and return the result
|
||||
func GetFloat32Of(search string) float32 {
|
||||
|
||||
newValue, err := strconv.ParseFloat(configurations.content[search], 32)
|
||||
if err != nil {
|
||||
panicMsg := fmt.Sprintf("Cannot convert to FLOAT32 -> %v", configurations.content[search])
|
||||
panic(panicMsg)
|
||||
}
|
||||
|
||||
return (float32)(newValue)
|
||||
}
|
||||
|
||||
// GetBoolOf tries to cast the search value into a
|
||||
// boolen and return the result
|
||||
func GetBoolOf(search string) bool {
|
||||
|
||||
newValue, err := strconv.ParseBool(configurations.content[search])
|
||||
if err != nil {
|
||||
panicMsg := fmt.Sprintf("Cannot convert to Bool -> %v", configurations.content[search])
|
||||
panic(panicMsg)
|
||||
}
|
||||
|
||||
return newValue
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Private Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// trimAndConvToSting trims the input string from the right and
|
||||
// left side only
|
||||
func trimAndConvToSting(name string, pos int) string {
|
||||
|
||||
name = strings.Split(name, "=")[pos]
|
||||
name = strings.TrimLeft(name, " ")
|
||||
name = strings.TrimRight(name, " ")
|
||||
|
||||
return name
|
||||
}
|
||||
123
kvmstoreserver_solution/src/utils/configPoller/configPoller.go
Executable file
123
kvmstoreserver_solution/src/utils/configPoller/configPoller.go
Executable file
@@ -0,0 +1,123 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: General use
|
||||
* File name: configPoller.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2017-08-19
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of configPoller.
|
||||
*
|
||||
* configPoller is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* configPoller is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with configPoller. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package configPoller takes one ore more configMap per instance
|
||||
// and start a gouroutine that check in a fix interval if the config file
|
||||
// has changed
|
||||
package configPoller
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: confgReaderContainer
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// confgReaderContainer is the structure containing the
|
||||
// configReader and the CheckSum of the config files
|
||||
type confgReaderContainer struct {
|
||||
confReader IUpdateConfig
|
||||
checksum [16]byte
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Structure: configPoller
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// ConfigPoller contains a slice of various configReaders
|
||||
// isLocked regulates that always the same instance is
|
||||
// sent back after the creation (Singelton Pattern)
|
||||
type configPoller struct {
|
||||
readers []*confgReaderContainer
|
||||
|
||||
// Interval in seconds
|
||||
interval int
|
||||
}
|
||||
|
||||
/********************* Methods ************************************************/
|
||||
|
||||
// observeChanges is executed in a separate goroutine
|
||||
// and checks after specified time whether config files were changed
|
||||
func (slf *configPoller) observeChanges() {
|
||||
|
||||
for {
|
||||
for _, reader := range slf.readers {
|
||||
newChkSum := reader.confReader.GetMd5Sum()
|
||||
if reader.checksum != newChkSum {
|
||||
reader.confReader.UpdateConfig()
|
||||
reader.checksum = newChkSum
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Second * time.Duration(slf.interval))
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*
|
||||
//* Public Functions
|
||||
//*
|
||||
//*****************************************************************************
|
||||
|
||||
// RegisterReaders accepts one or more configReaders and stores
|
||||
// them in the structure configPoller, which is then executed by
|
||||
// method observeChanges() in a separate goroutine
|
||||
func RegisterReaders(intVal int, readers ...IUpdateConfig) {
|
||||
|
||||
if len(readers) == 0 {
|
||||
panic("No list of configReaders has been defined!")
|
||||
}
|
||||
|
||||
var cp configPoller
|
||||
|
||||
for _, reader := range readers {
|
||||
crc := &confgReaderContainer{
|
||||
confReader: reader,
|
||||
}
|
||||
crc.checksum = crc.confReader.GetMd5Sum()
|
||||
cp.readers = append(cp.readers, crc)
|
||||
}
|
||||
cp.interval = intVal
|
||||
|
||||
// Starts the poller in a separate goroutine
|
||||
go cp.observeChanges()
|
||||
}
|
||||
53
kvmstoreserver_solution/src/utils/configPoller/interfaces.go
Executable file
53
kvmstoreserver_solution/src/utils/configPoller/interfaces.go
Executable file
@@ -0,0 +1,53 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: General use
|
||||
* File name: interfaces.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2017-08-19
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of configPoller.
|
||||
*
|
||||
* configPoller is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* configPoller is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with configPoller. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
package configPoller
|
||||
|
||||
// IUpdateConfig defines how a configReader can be called to
|
||||
// output its CheckSum and how to invoke a config file update
|
||||
// from the outside
|
||||
type IUpdateConfig interface {
|
||||
// from what the checksum was
|
||||
// generated does not matter here
|
||||
GetMd5Sum() [16]byte
|
||||
|
||||
// What the update looks like in
|
||||
// the configReader is defined by
|
||||
// the reader with its own private method / function
|
||||
UpdateConfig() error
|
||||
}
|
||||
86
kvmstoreserver_solution/src/versionInfo/versionInfo.go
Executable file
86
kvmstoreserver_solution/src/versionInfo/versionInfo.go
Executable file
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************************
|
||||
*
|
||||
* Project: kvmstoreserver
|
||||
* File name: versionInfo.go
|
||||
* Version: 1.0.0
|
||||
* Date: 2018-01-17
|
||||
*
|
||||
* Autor: Bogdanovic Theodor
|
||||
* Contact: t.bogdanovic@hotmail.com
|
||||
*
|
||||
* License: GPLv3
|
||||
*
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Copyright 2018 Bogdanovic Theodor
|
||||
*
|
||||
* This file is part of kvmstoreserver.
|
||||
*
|
||||
* kvmstoreserver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* kvmstoreserver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with kvmstoreserver. If not, see <http://www.gnu.org/licenses/>.
|
||||
**************************************************************************************/
|
||||
/**************************************************************************************
|
||||
* Further explanations: This source code is under the license specified by the
|
||||
* Autor above. Core components or other packages are still
|
||||
* in source code form, under the license specified by the
|
||||
* respective author.
|
||||
**************************************************************************************/
|
||||
|
||||
// Package versionInfo contains constants and functions which
|
||||
// provide general program information
|
||||
package versionInfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"essentials"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Staticlly hard coded base information about the kvmstoreserver
|
||||
const (
|
||||
programName string = "kvmstoreserver"
|
||||
version string = "1.0.0"
|
||||
buildTime string = "2018-02-17__18:34.000"
|
||||
license string = "GPLv3"
|
||||
autor string = "Bogdanovic Theodor"
|
||||
contact string = "t.bogdanovic@hotmail.com"
|
||||
infos string = "HBU HF NDS, Diploma Project"
|
||||
)
|
||||
|
||||
// VerInfoFinalHandler return a JSON document which contains essentail
|
||||
// inforamtions about this program
|
||||
func VerInfoFinalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
essentials.InjectJSONTypeToHeader(w)
|
||||
|
||||
innerAswerStruct := &struct {
|
||||
ProgramName string `json:"program_name,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
BuildTime string `json:"build_time,omitempty"`
|
||||
License string `json:"license,omitempty"`
|
||||
Autor string `json:"autor,omitempty"`
|
||||
Contact string `json:"contact,omitempty"`
|
||||
Infos string `json:"infos,omitempty"`
|
||||
}{
|
||||
ProgramName: programName,
|
||||
Version: version,
|
||||
BuildTime: buildTime,
|
||||
License: license,
|
||||
Autor: autor,
|
||||
Contact: contact,
|
||||
Infos: infos,
|
||||
}
|
||||
|
||||
jsonOutput, _ := json.MarshalIndent(innerAswerStruct, "", "\t")
|
||||
|
||||
w.Write(jsonOutput)
|
||||
}
|
||||
Reference in New Issue
Block a user