[INIT+STANDALONE] fresh init of this project from original without specific confidential documents

This commit is contained in:
2026-02-18 18:52:52 +01:00
parent 18db789421
commit 751bafa38e
63 changed files with 6356 additions and 2 deletions

4
.gitignore vendored
View File

@@ -5,7 +5,8 @@
.LSOverride .LSOverride
# Icon must end with two \r # Icon must end with two \r
Icon Icon
# Thumbnails # Thumbnails
._* ._*
@@ -26,3 +27,4 @@ Network Trash Folder
Temporary Items Temporary Items
.apdisk .apdisk
**/Dokumentation.pdf

View File

@@ -1,3 +1,11 @@
# KVM-Store-Server # KVM-Store-Server
This repository contains my diploma thesis for the postgraduate studies program at the Higher Education Institute (HF). It is a specialized key-value in-memory store, which was developed for a problem domain of a sponsoring company. **Attention, this project was created in 2018 and has never been ported to a more recent Go version.**
**This project is for educational purposes only and should not be actively used. The project is not archived, but development is no longer ongoing.**
**This project should no longer be used; there are far better alternatives available (etcd etc.).**
*To protect the data privacy of the project sponsor, the entire documentation cannot be published here. However, the documentation has been reduced to an absolute minimum (user manual) to still be of some help.__*
This repository contains my diploma thesis for the postgraduate studies program at the Higher Education Institute (HF). It is a specialized key-value in-memory store, which was developed for a problem domain of a sponsoring company.

View File

@@ -0,0 +1,70 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: getLastEntry.go
* Version: 1.0.0
* Date: 2018-01-15
*
* Autor: Bogdanovic Theodor
* Contact: t.bogdanovic@hotmail.com
*
* License: GPLv3
*
**************************************************************************************/
/**************************************************************************************
* Copyright 2018 Bogdanovic Theodor
*
* This file is part of kvmstoreserver-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 checker
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strconv"
)
// GetRandomEntry ...
func GetRandomEntry(url string, lastEntry int) string {
partialURL := url + "/get/System_Name_" + strconv.Itoa(lastEntry)
resp, err := http.Get(partialURL)
if err != nil {
log.Printf("\nERROR: Destination URL (%v) does not answer (Error-> %v)",
partialURL, err)
os.Exit(1)
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
body, _ := ioutil.ReadAll(resp.Body)
return string(body)
}
return fmt.Sprintf("Error: The status of the received message is unequal 200 (Received: %v)",
resp.StatusCode)
}

View File

@@ -0,0 +1,61 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: urlChecker.go
* Version: 1.0.0
* Date: 2018-01-15
*
* Autor: Bogdanovic Theodor
* Contact: t.bogdanovic@hotmail.com
*
* License: GPLv3
*
**************************************************************************************/
/**************************************************************************************
* Copyright 2018 Bogdanovic Theodor
*
* This file is part of kvmstoreserver-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 checker
import (
"fmt"
"net/http"
)
// IsURLValid ...
func IsURLValid(url string) error {
fullURL := url + "/version"
resp, err := http.Get(fullURL)
if err != nil {
return fmt.Errorf("Destination URL (%v) does not answer", url)
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
return nil
}
return fmt.Errorf("Something seems to be wrong with the server - Abort")
}

View File

@@ -0,0 +1,145 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: client.go
* Version: 1.0.0
* Date: 2018-01-15
*
* Autor: Bogdanovic Theodor
* Contact: t.bogdanovic@hotmail.com
*
* License: GPLv3
*
**************************************************************************************/
/**************************************************************************************
* Copyright 2018 Bogdanovic Theodor
*
* This file is part of kvmstoreserver-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 client
import (
"bytes"
"fmt"
"net/http"
"strconv"
"sync"
"time"
)
//*****************************************************************************
//*
//* Structure: Synchronizer
//*
//*****************************************************************************
// ParaController ...
type ParaController struct {
Wg sync.WaitGroup
}
//*****************************************************************************
//*
//* Structure: InjClient
//*
//*****************************************************************************
// InjClient ...
type InjClient struct {
clientID int
url string
}
//******************** Methods ************************************************
// generateKeyName ...
func (slf *InjClient) generateKeyName() string {
return "System_Name_" + strconv.Itoa(slf.clientID)
}
// GenerateRequest ...
func (slf *InjClient) generateRequest() *bytes.Reader {
newName := slf.generateKeyName()
newNbr := slf.clientID
newVers := float64(slf.clientID) + 0.99999999
newAct := slf.clientID%2 == 0
newNull := "null"
return bytes.NewReader([]byte(
fmt.Sprintf(`{"system_name": "%v","system_number": %v,"system_version": %v,"system_active": %v,"system_null": %v}`,
newName, newNbr, newVers, newAct, newNull),
))
}
// StartRequest ...
func (slf *InjClient) StartRequest(syncer *ParaController) {
defer func() {
err := recover()
if err != nil {
fmt.Printf("(RECOVER) Worker ID: %v - failed: Reason -> [Program Error: %v]\n",
slf.clientID, err)
syncer.Wg.Add(-1)
}
}()
client := &http.Client{Timeout: time.Second * 60}
callURL := slf.url + "/add/" + slf.generateKeyName()
req, _ := http.NewRequest("POST", callURL, slf.generateRequest())
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 {
fmt.Printf("Worker ID: %v - failed: Reason -> [Connection Error -> (%v)]\n",
slf.clientID, err)
return
}
if resp.StatusCode != 201 {
fmt.Printf("Worker ID: %v - failed: Reason -> [Status != 201 | (Received: %v)]\n",
resp.StatusCode, slf.clientID)
return
}
resp.Body.Close()
syncer.Wg.Add(-1)
}
//*****************************************************************************
//*
//* Public Functions
//*
//*****************************************************************************
// NewWorker ...
func NewWorker(clientID int, url string) *InjClient {
return &InjClient{
clientID: clientID,
url: url,
}
}

View File

@@ -0,0 +1,89 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: main.go
* Version: 1.0.0
* Date: 2018-01-15
*
* Autor: Bogdanovic Theodor
* Contact: t.bogdanovic@hotmail.com
*
* License: GPLv3
*
**************************************************************************************/
/**************************************************************************************
* Copyright 2018 Bogdanovic Theodor
*
* This file is part of kvmstoreserver-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 (
"checker"
"client"
"fmt"
"runtime"
"time"
"utils"
)
func main() {
const maxParaReqs int = 6000
var endNbr int
cmdArgs := utils.NewCmdController()
synchronizer := client.ParaController{}
start := time.Now()
if cmdArgs.GetStart() != 0 {
endNbr = cmdArgs.GetStart() + 6000
} else {
endNbr = maxParaReqs
}
for idx := cmdArgs.GetStart(); idx < endNbr; idx++ {
synchronizer.Wg.Add(1)
go client.NewWorker(idx, cmdArgs.GetTarget()).StartRequest(&synchronizer)
}
synchronizer.Wg.Wait()
runtime.GC()
fmt.Printf("\nToral duration of all (%v) parallel requests -> %v\n",
maxParaReqs, time.Since(start))
fmt.Printf("\nThe default key pattern is \"System_Name_<%v - %v>\"", cmdArgs.GetStart(), endNbr-1)
fmt.Printf(`
EXAMPLE:
http://<IP or domain name>:3344/get/System_Name_0
`)
fmt.Printf("Start trying to get the last entry from kvmstoreserver:")
fmt.Printf("\nRESULT -> %v",
checker.GetRandomEntry(cmdArgs.GetTarget(), endNbr-1))
}

View File

@@ -0,0 +1,98 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: cmdParser.go
* Version: 1.0.0
* Date: 2018-01-15
*
* Autor: Bogdanovic Theodor
* Contact: t.bogdanovic@hotmail.com
*
* License: GPLv3
*
**************************************************************************************/
/**************************************************************************************
* Copyright 2018 Bogdanovic Theodor
*
* This file is part of kvmstoreserver-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 utils
import (
"checker"
"flag"
"fmt"
"log"
"os"
)
//*****************************************************************************
//*
//* Structure: CmdController
//*
//*****************************************************************************
// CmdController ...
type CmdController struct {
target *string
start *int
}
//******************** Methods ************************************************
// GetTarget ...
func (slf *CmdController) GetTarget() string { return *slf.target }
// GetStart ...
func (slf *CmdController) GetStart() int { return *slf.start }
//*****************************************************************************
//*
//* Public Functions
//*
//*****************************************************************************
// NewCmdController ...
func NewCmdController() *CmdController {
var cmdController CmdController
cmdController.target = flag.String("target", "",
"The URL to the storeserver -> EXAMPLE: http://<IP or domain name>:3344")
cmdController.start = flag.Int("start", 0,
"Please enter the start number. At this point + 6000 will be added")
if cmdController.target == nil {
fmt.Println("Please enter the address of the server -> EXAMPLE: inject_client -target http://<IP or domain name>:3344")
os.Exit(1)
}
flag.Parse()
if err := checker.IsURLValid(*cmdController.target); err != nil {
log.Fatal(err)
}
return &cmdController
}

View File

@@ -0,0 +1,121 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: jsonObjGenerator.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-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 generator
import (
"fmt"
"io/ioutil"
"keyNameHandling"
"log"
"strconv"
"utils"
)
//*****************************************************************************
//*
//* Declarations
//*
//*****************************************************************************
const namePattern string = "System_Name_"
//*****************************************************************************
//*
//* Structure: JObjGenerator
//*
//*****************************************************************************
// JObjGenerator ...
type JObjGenerator struct {
objNbr int
jObj []byte
wPath string
fullPath string
syncer *utils.ParaController
}
//******************** Methods ************************************************
func (slf *JObjGenerator) generateJObj() {
keyName := namePattern + strconv.Itoa(slf.objNbr)
nodeID, _ := keyNameHandling.NewKeyContext(keyName)
slf.fullPath = slf.wPath + "/" + strconv.Itoa(nodeID.GetNodeID()) + ".json"
dataNbr := slf.objNbr
dataVers := float64(slf.objNbr) + 0.99999999
dataAct := slf.objNbr%2 == 0
dataNull := "null"
slf.jObj = []byte(
fmt.Sprintf(`{"node_id":%v,"orig_key_name":"%v","data_container":[{"rev_nbr":0,"meta_header":{"remote_addr":"0.0.0.0:65535","created_at":"1970-01-01T00:00:00.3889558+01:00"},"data":{"system_name": "%v","system_number": %v,"system_version": %v,"system_active": %v,"system_null": %v}}]}`,
nodeID.GetNodeID(), nodeID.GetKeyStrName(), nodeID.GetKeyStrName(), dataNbr, dataVers, dataAct, dataNull),
)
}
// WriteIntoTarget ...
func (slf *JObjGenerator) WriteIntoTarget() {
if err := ioutil.WriteFile(slf.fullPath, slf.jObj, 0660); err != nil {
log.Printf("Write for %v failed: Reason -> [%v]", slf.fullPath, err)
}
slf.syncer.Wg.Add(-1)
}
//*****************************************************************************
//*
//* Public Functions
//*
//*****************************************************************************
// NewWorker ...
func NewWorker(objNbr int, wPath *string, syncer *utils.ParaController) *JObjGenerator {
newObj := JObjGenerator{
objNbr: objNbr,
wPath: *wPath,
syncer: syncer,
}
newObj.generateJObj()
return &newObj
}

View File

@@ -0,0 +1,101 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* 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-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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"
"generator"
"time"
"utils"
)
func main() {
var (
chunkSize int
outerLoops int
rest int
objCounter int
)
chunkSize = 10000
cmdArgs := utils.NewCmdController()
synchronizer := utils.NewParaController()
if cmdArgs.GetObjects() < chunkSize {
chunkSize = cmdArgs.GetObjects()
outerLoops = 1
rest = 0
} else {
outerLoops = cmdArgs.GetObjects() / chunkSize
rest = cmdArgs.GetObjects() % chunkSize
}
start := time.Now()
for outerIdx := 0; outerIdx < outerLoops; outerIdx++ {
for innerIdx := 0; innerIdx < chunkSize; innerIdx++ {
synchronizer.Wg.Add(1)
generator.NewWorker(objCounter, cmdArgs.GetTargetRef(), synchronizer).
WriteIntoTarget()
objCounter++
}
synchronizer.Wg.Wait()
}
if rest > 0 {
for innerIdx := 0; innerIdx < rest; innerIdx++ {
synchronizer.Wg.Add(1)
generator.NewWorker(objCounter, cmdArgs.GetTargetRef(), synchronizer).
WriteIntoTarget()
objCounter++
}
synchronizer.Wg.Wait()
}
fmt.Printf("%v generic JSON objects were generated in %v and stored in path -> %v\n",
objCounter, time.Since(start), *cmdArgs.GetTargetRef())
}

View File

@@ -0,0 +1,123 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* 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-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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
// 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
type keyContext struct {
keyNameAsString string
keyMd5Hash [16]byte
// Here is the calculated node ID where the data should be stored
dataNodeID int
}
/********************* Methods ************************************************/
// defDataNodeID ...
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 a reference to the structure, which
// contains all information on the following points:
//
// - Original Key Name as string
// - MD5 hash of the key name
// - The ID of RootTree
// - 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
}

View File

@@ -0,0 +1,52 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* 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-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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
}

View File

@@ -0,0 +1,85 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: cmdParser.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-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 utils
import (
"flag"
)
//*****************************************************************************
//*
//* Structure: CmdController
//*
//*****************************************************************************
// CmdController ...
type CmdController struct {
target *string
objects *int
}
//******************** Methods ************************************************
// GetTargetRef ...
func (slf *CmdController) GetTargetRef() *string { return slf.target }
// GetObjects ...
func (slf *CmdController) GetObjects() int { return *slf.objects }
//*****************************************************************************
//*
//* Public Functions
//*
//*****************************************************************************
// NewCmdController ...
func NewCmdController() *CmdController {
var cmdController CmdController
cmdController.target = flag.String("target", "/home/kvmstoreserver/kvmstoreserver/warehouse",
"The path to the warehouse folder")
cmdController.objects = flag.Int("objects", 1,
"How many json objects should be generated")
flag.Parse()
return &cmdController
}

View File

@@ -0,0 +1,53 @@
/**************************************************************************************
*
* Project: kvmstoreserver-tools
* File name: paraController.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-tools.
*
* kvmstoreserver-tools 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-tools 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-tools. 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 utils
import (
"sync"
)
// ParaController ...
type ParaController struct {
Wg sync.WaitGroup
}
// NewParaController ...
func NewParaController() *ParaController {
return &ParaController{}
}

Binary file not shown.

View 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 = /home/kvmstoreserver/kvmstoreserver/warehouse
# DINAMIC
serde_driver = filesystem
# All log file parameters -> STATIC
default_log_file = /home/kvmstoreserver/kvmstoreserver/var/log/kvmstoreserver.log
log_max_size_mb = 100
log_max_age_days = 30
log_write_to_console = false
######################### HTTP Server settings ###############################
# All HTTP Server Settings -> STATIC
http_hostname =
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

View File

@@ -0,0 +1,37 @@
#**************************************************************************************
#*
#* Project: kvmstoreserver
#* File name: kvmstoreserver.service
#* Version: 1.0.0
#* Date: 2018-02-06
#*
#* Autor: Bogdanovic Theodor
#* Contact: t.bogdanovic@hotmail.com
#*
#* License: GPLv3
#*
#**************************************************************************************
#**************************************************************************************
#* 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.
#*
#**************************************************************************************
[Unit]
Description=KVM Store Server
Wants=network.target network-online.target autofs.service
After=network.target network-online.target autofs.service
[Service]
Type=simple
User=kvmstoreserver
ExecStart=/home/kvmstoreserver/kvmstoreserver/bin/kvmstoreserver -config /home/kvmstoreserver/kvmstoreserver/etc/kvmstoreserver.conf
LimitNOFILE=500000
LimitNPROC=500000
Nice=-10
PIDFile=/var/run/kvmstoreserver.pid
[Install]
WantedBy=multi-user.target

Binary file not shown.

View File

@@ -0,0 +1,301 @@
#!/usr/bin/env bash
#**************************************************************************************
#*
#* Project: kvmstoreserver
#* File name: kvmss-installer.sh
#* Version: 1.0.0
#* Date: 2018-02-06
#*
#* 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.
#*
#**************************************************************************************
### Variables ###
IP_OR_DOMNAME=""
INSTALL_ROOT="/home/kvmstoreserver/kvmstoreserver"
USERNAME="kvmstoreserver"
USER_PASSWD=""
SELECT_ANSWER=""
EXIST_AN_INSTALLATION=100
### Functions ###
function window::if_user_root()
{
if [ `id -u` -ne 0 ]
then
whiptail --title "KVM Store Server Installer" --msgbox "You need root rights to run this installer. Please try again with sudo kvmss-installer" 10 70
exit 1
fi
}
function window::run_installer()
{
local kind=$1
if [ $kind == "install" ]
then
if (! whiptail --title "KVM Store Server Installer" --yesno "Do you want to start installing of the KVM Store Server" 8 70)
then
exit 0
fi
elif [ $kind == "delete" ]
then
if (! whiptail --title "KVM Store Server Installer" --yesno "Do you want to start deletion of the KVM Store Server - Attention, this will also erase the stored data!" 8 70)
then
exit 0
fi
else
exit 1
fi
}
function window::enter_ip_or_name()
{
name=$(whiptail --inputbox "Please enter the IP address of your computer on which the KVM Store Server should listen, alternatively you can also use the valid domain name of your computer - Example -> 192.168.0.5 or my-computer.my-domain.com You can also leave this field blank, then the server listens to all interfaces - THIS CONFIGURATION IS NOT RECOMMENDED!" 12 90 --title "KVM Store Server Installer" 3>&1 1>&2 2>&3)
answer=$?
if [ $answer = 0 ]; then
IP_OR_DOMNAME=$name
else
exit 0
fi
}
function core::exist_an_installation()
{
if [ -d $INSTALL_ROOT ]
then
EXIST_AN_INSTALLATION=1
else
EXIST_AN_INSTALLATION=0
fi
}
function window::enter_passwd()
{
for (( ; ; ))
do
passwd_1=$(whiptail --passwordbox "Please enter a password for the new linux user kvmstoreserver - Please do not use backslash" 8 60 --title "KVM Store Server Installer" 3>&1 1>&2 2>&3)
answer=$?
[ $answer != 0 ] && exit 0
passwd_2=$(whiptail --passwordbox "Please enter the password again" 8 60 --title "KVM Store Server Installer" 3>&1 1>&2 2>&3)
answer=$?
if [ $answer = 0 ]
then
if [ ${passwd_1} == ${passwd_2} ] && [ ! -z ${passwd_2} ]
then
USER_PASSWD=$passwd_2
break
else
whiptail --title "KVM Store Server Installer" --msgbox "The passwords do not match. Try again" 8 45
continue
fi
else
exit 0
fi
done
}
function core::create_kvmss_user()
{
sudo useradd $USERNAME -m
echo -e "$USER_PASSWD\n$USER_PASSWD\n" | sudo passwd $USERNAME
}
function core::create_folder_struct()
{
sudo mkdir $INSTALL_ROOT
sudo mkdir $INSTALL_ROOT/bin
sudo mkdir $INSTALL_ROOT/etc
sudo mkdir $INSTALL_ROOT/warehouse
sudo mkdir $INSTALL_ROOT/utils
sudo mkdir $INSTALL_ROOT/var
sudo mkdir $INSTALL_ROOT/var/log
}
function core::change_rights()
{
sudo chmod u+rw $INSTALL_ROOT/var/log
sudo chmod g+rw $INSTALL_ROOT/var/log
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/var/log
sudo chmod u+rw $INSTALL_ROOT/var
sudo chmod g+rw $INSTALL_ROOT/var
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/var
sudo chmod u+rw $INSTALL_ROOT/warehouse
sudo chmod g+rw $INSTALL_ROOT/warehouse
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/warehouse
sudo chmod u+rw $INSTALL_ROOT/utils
sudo chmod g+rw $INSTALL_ROOT/utils
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/utils
sudo chmod u+rw $INSTALL_ROOT/etc
sudo chmod g+rw $INSTALL_ROOT/etc
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/etc
sudo chmod u+rw $INSTALL_ROOT/bin
sudo chmod g+rw $INSTALL_ROOT/bin
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/bin
sudo chmod u+rwx $INSTALL_ROOT/utils/inject_disk
sudo chmod g+rwx $INSTALL_ROOT/utils/inject_disk
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/utils/inject_disk
sudo chmod u+rwx $INSTALL_ROOT/bin/kvmstoreserver
sudo chmod g+rwx $INSTALL_ROOT/bin/kvmstoreserver
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/bin/kvmstoreserver
sudo chmod u+rw $INSTALL_ROOT/etc/kvmstoreserver.conf
sudo chmod g+rw $INSTALL_ROOT/etc/kvmstoreserver.conf
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT/etc/kvmstoreserver.conf
sudo chmod u+rw $INSTALL_ROOT
sudo chmod g+rw $INSTALL_ROOT
sudo chown $USERNAME:$USERNAME $INSTALL_ROOT
}
function core::copy_files()
{
sudo cp ./data/bin/kvmstoreserver $INSTALL_ROOT/bin/kvmstoreserver
sudo cp ./data/utils/inject_disk $INSTALL_ROOT/utils/inject_disk
sudo cp ./data/etc/kvmstoreserver.conf $INSTALL_ROOT/etc/kvmstoreserver.conf
sudo cp ./data/init/kvmstoreserver.service /etc/systemd/system/kvmstoreserver.service
}
function core::install_and_run_daemon()
{
sudo systemctl daemon-reload
sudo systemctl start kvmstoreserver.service
sudo systemctl enable kvmstoreserver.service
}
function core::replace_server_name()
{
sudo sed -i -e "s/http_hostname = /http_hostname = $IP_OR_DOMNAME/g" $INSTALL_ROOT/etc/kvmstoreserver.conf
}
function window::select_action()
{
if [ $EXIST_AN_INSTALLATION = 0 ]
then
selection=$(whiptail --title "KVM Store Server Installer" --menu "Choose an option" 9 70 2 \
"Install" "Installs the KVM Store Server on the hard disk" 3>&1 1>&2 2>&3)
answer=$?
[ $answer != 0 ] && exit 0
elif [ $EXIST_AN_INSTALLATION = 1 ]
then
selection=$(whiptail --title "KVM Store Server Installer" --menu "Choose an option" 9 70 2 \
"Remove " "Delete the KVM Store Server completely from the hard disk" 3>&1 1>&2 2>&3)
answer=$?
[ $answer != 0 ] && exit 0
fi
SELECT_ANSWER=$selection
}
function window::finish_text()
{
local kind=$1
if [ $kind == "install" ]
then
if (whiptail --title "KVM Store Server Installer" --msgbox "The installation is complete, the server is now running - The configuration file can be found at /home/kvmstoreserver/kvmstoreserver/etc/kvmstoreserver.conf. There you can make all relevant settings. After a change in the configuration file, you may need to run - sudo systemctl restart kvmstoreserver.service - in the console" 13 90)
then
exit 0
fi
elif [ $kind == "delete" ]
then
if (whiptail --title "KVM Store Server Installer" --msgbox "The KVM Store Server is completlly deleted from your Harddisk" 8 70)
then
exit 0
fi
fi
}
function main::install()
{
window::run_installer "install"
window::enter_ip_or_name
window::enter_passwd
{
echo XXX && echo 10 && echo "Creating kvmstoreserver user" && echo XXX && core::create_kvmss_user > /dev/null 2>&1
echo XXX && echo 20 && echo "Creating folder structure" && echo XXX && core::create_folder_struct > /dev/null 2>&1
echo XXX && echo 40 && echo "Copy files" && echo XXX && core::copy_files > /dev/null 2>&1
echo XXX && echo 50 && echo "Configure config file" && echo XXX && core::replace_server_name > /dev/null 2>&1
echo XXX && echo 70 && echo "Changing rights" && echo XXX && core::change_rights > /dev/null 2>&1
echo XXX && echo 100 && echo "Install an run kvmstoreserver daemon" && echo XXX && core::install_and_run_daemon > /dev/null 2>&1
} | whiptail --title "Please wait KVM Store Server will be installed" --gauge "Start" 6 60 0
window::finish_text "install"
}
function main::remove()
{
window::run_installer "delete"
{
echo XXX && echo 10 && echo "Killing all processes of user kvmstoreserver" && echo XXX && sudo killall --user $USERNAME > /dev/null 2>&1
echo XXX && echo 20 && echo "Stopping kvmstoreserver service" && echo XXX && sudo systemctl stop kvmstoreserver.service -f > /dev/null 2>&1
echo XXX && echo 40 && echo "Deactivating kvmstoreserver service" && echo XXX && sudo systemctl disable kvmstoreserver.service -f > /dev/null 2>&1
echo XXX && echo 50 && echo "Removing kvmstoreserver service" && echo XXX && sudo rm /etc/systemd/system/kvmstoreserver.service > /dev/null 2>&1
echo XXX && echo 80 && echo "Reloading Systemd init system" && echo XXXsudo systemctl daemon-reload > /dev/null 2>&1
echo XXX && echo 100 && echo "Deleting kvmstoreserver user and DATA" && echo XXX && sudo deluser $USERNAME --remove-home > /dev/null 2>&1
} | whiptail --title "Please wait, KVM Store Server will be deleted" --gauge "Start" 6 60 0
window::finish_text "delete"
}
### MAIN ###
window::if_user_root
core::exist_an_installation
window::select_action
case $selection in
"Install") main::install
;;
"Remove ") main::remove
;;
*) echo "Unknown"
;;
esac

View 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

View 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

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

View 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")
}

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

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

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

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

View 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"))
}

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

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

View 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, "")
}

View 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"`
}

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View 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(),
}
}

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

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

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

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

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

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

BIN
user-manual-de.pdf Executable file

Binary file not shown.