Commit f38345e1 authored by Roshan Patil's avatar Roshan Patil
Browse files

Merge branch 'devbranch' into savedata_dalmdl

parents 55357295 1a1de11f
Branches
Tags
2 merge requests!23Devbranch to Master,!16Savedata dalmdl
Showing with 1031 additions and 120 deletions
......@@ -6,6 +6,8 @@ package dalmdl
import (
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/dalmdl/fdb"
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
"github.com/tidwall/gjson"
)
......@@ -30,14 +32,18 @@ func GetDAO() *DAOBuilder {
// Run : Execute Query
//TODO: Before Run() call validate method
func (db *DAOBuilder) Run() *gjson.Result {
func (db *DAOBuilder) Run() (*gjson.Result, error) {
db.Output = gjson.Result{}
var err error
for _, qry := range db.query {
// FIXME:Return error. Error handling remaining.
db.Output, _ = fdb.GetDataDAO(db.filePath, qry, db.isCacheable, db.Output)
db.Output, err = fdb.GetDataDAO(db.filePath, qry, db.isCacheable, db.Output)
if errormdl.CheckErr(err) != nil {
loggermdl.LogError("Error in executing query: ", qry, err)
return nil, errormdl.CheckErr(err)
}
}
return &db.Output
return &db.Output, nil
}
// FilePath to open File and get data from FDB
......
package filemdl
import (
"errors"
"io"
"io/ioutil"
"os"
......@@ -12,16 +13,62 @@ import (
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"
)
var (
backupPath = ""
dbPath = ""
)
// TODO: Symbolic link evelution for this package not supported in windows .symlink file
// SetBackPath set backup folder path
func SetBackPath(folderPath, dbFolderPath string) error {
if folderPath == "" || dbFolderPath == "" {
return errors.New("Backup folder path and DB Path must not be empty")
}
bFolder, bFile := filepath.Split(folderPath)
if bFile != "" {
return errors.New("Backup Path must be folder or you forget to provide slash at the end")
}
dbFolder, dbFile := filepath.Split(dbFolderPath)
if dbFile != "" {
return errors.New("DB Path must be folder or you forget to provide slash at the end")
}
backupPath = bFolder
dbPath = dbFolder
return nil
}
// createFileBackup createfile back in backup folder
func createFileBackup(filePath string) error {
if backupPath == "" || dbPath == "" {
loggermdl.LogError("Backup folder path not set")
return errors.New("Backup folder path not set")
}
backupFilePath := backupPath + strings.TrimPrefix(filePath, dbPath)
_, err := CopyFile(filePath, backupFilePath, true)
if errormdl.CheckErr(err) != nil {
return errormdl.CheckErr(err)
}
return nil
}
//FileHelperServiceObject FileHelperServiceObject must be created while calling FileSearh function
type FileHelperServiceObject struct {
searchResult []string
searchFileName string
}
// ReadFile reads contents from provided file path
// ReadFile reads contents from provided file path and retry when timeout occure
func ReadFile(filePath string) ([]byte, error) {
return ioutil.ReadFile(filePath)
path, linkErr := os.Readlink(filePath)
if errormdl.CheckErr1(linkErr) == nil {
filePath = path
}
ba, err := ioutil.ReadFile(filePath)
if errormdl.CheckErr(err) != nil && err.Error() == "i/o timeout" {
return ioutil.ReadFile(filePath)
}
return ba, nil
}
//createFile creates a new file
......@@ -31,9 +78,7 @@ func createFile(filePath string) (*os.File, error) {
}
func createRecursiveDirectoryForFile(filePath string) error {
// FIXME: use filepath.Split
basePath := filepath.Base(filePath)
dir := strings.TrimSuffix(filePath, basePath)
dir, _ := filepath.Split(filePath)
createError := CreateDirectoryRecursive(dir)
if errormdl.CheckErr(createError) != nil {
loggermdl.LogError(createError)
......@@ -43,7 +88,11 @@ func createRecursiveDirectoryForFile(filePath string) error {
}
// WriteFile writes provided bytes to file
func WriteFile(filePath string, data []byte, makeDir bool) error {
func WriteFile(filePath string, data []byte, makeDir bool, createBackup bool) error {
path, linkErr := os.Readlink(filePath)
if errormdl.CheckErr1(linkErr) == nil {
filePath = path
}
if makeDir {
createError := createRecursiveDirectoryForFile(filePath)
if errormdl.CheckErr(createError) != nil {
......@@ -51,12 +100,21 @@ func WriteFile(filePath string, data []byte, makeDir bool) error {
return errormdl.CheckErr(createError)
}
}
if createBackup {
backupErr := createFileBackup(filePath)
if backupErr != nil {
loggermdl.LogError(backupErr)
}
}
return ioutil.WriteFile(filePath, data, 0644)
}
//AppendFile appends provided data/text to file
func AppendFile(filename string, text string) (int, error) {
path, linkErr := os.Readlink(filename)
if errormdl.CheckErr1(linkErr) == nil {
filename = path
}
f, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if errormdl.CheckErr(err) != nil {
loggermdl.LogError(err)
......@@ -70,6 +128,10 @@ func AppendFile(filename string, text string) (int, error) {
//DeleteFile deletes provided file path
func DeleteFile(filePath string) error {
path, linkErr := os.Readlink(filePath)
if errormdl.CheckErr1(linkErr) == nil {
filePath = path
}
err := os.Remove(filePath)
if errormdl.CheckErr(err) != nil {
loggermdl.LogError(err)
......@@ -133,6 +195,10 @@ func MoveFileToOtherHost(source, destination string) error {
//CopyFile CopyFile
func CopyFile(source, destination string, makeDir bool) (int64, error) {
// return os.Rename(source, destination)
path, linkErr := os.Readlink(source)
if errormdl.CheckErr1(linkErr) == nil {
source = path
}
in, openError := os.Open(source)
defer in.Close()
if errormdl.CheckErr(openError) != nil {
......@@ -162,7 +228,10 @@ func CopyFile(source, destination string, makeDir bool) (int64, error) {
//CopyDir makes copy of source directory to the destination directory
func CopyDir(source string, dest string) (err error) {
path, linkErr := os.Readlink(source)
if errormdl.CheckErr2(linkErr) == nil {
source = path
}
// get properties of source dir
sourceinfo, err := os.Stat(source)
if errormdl.CheckErr(err) != nil {
......@@ -176,9 +245,8 @@ func CopyDir(source string, dest string) (err error) {
loggermdl.LogError(err)
return errormdl.CheckErr1(err)
}
// FIXME: close below filepointer
directory, _ := os.Open(source)
defer directory.Close()
objects, err := directory.Readdir(-1)
for _, obj := range objects {
......@@ -206,12 +274,20 @@ func CopyDir(source string, dest string) (err error) {
}
//ReplaceFile ReplaceFile
func ReplaceFile(data []byte, destination string) error {
return WriteFile(destination, data, false)
func ReplaceFile(data []byte, destination string, createBackup bool) error {
path, linkErr := os.Readlink(destination)
if errormdl.CheckErr(linkErr) == nil {
destination = path
}
return WriteFile(destination, data, false, createBackup)
}
//TruncateFile TruncateFile
func TruncateFile(path string, size int64) error {
tmp, linkErr := os.Readlink(path)
if errormdl.CheckErr(linkErr) == nil {
path = tmp
}
return os.Truncate(path, size)
}
......@@ -231,6 +307,10 @@ func TruncateFile(path string, size int64) error {
//FileInfo FileInfo
func FileInfo(path string) (os.FileInfo, error) {
tmp, linkErr := os.Readlink(path)
if errormdl.CheckErr(linkErr) == nil {
path = tmp
}
return os.Stat(path)
}
......@@ -299,6 +379,10 @@ func (fileHelperServiceObject *FileHelperServiceObject) findFile(path string, fi
//FileAvailabilityCheck checks whether file is available at given location
func FileAvailabilityCheck(filePath string) bool {
tmp, linkErr := os.Readlink(filePath)
if errormdl.CheckErr(linkErr) == nil {
filePath = tmp
}
fileInfo, err := os.Stat(filePath)
if fileInfo == nil && errormdl.CheckErr(err) != nil {
loggermdl.LogError(err)
......
......@@ -25,7 +25,6 @@ func Test1ReadFile(t *testing.T) {
want []byte
wantErr bool
}{
// TODO: Add test cases.
struct {
name string
args args
......@@ -54,9 +53,10 @@ func Test1ReadFile(t *testing.T) {
func TestWriteFile(t *testing.T) {
type args struct {
filePath string
data []byte
makeDir bool
filePath string
data []byte
makeDir bool
createFileBackup bool
}
ba, _ := dalhelper.GetDataFromFDB("../testingdata/users.json")
tests := []struct {
......@@ -70,7 +70,7 @@ func TestWriteFile(t *testing.T) {
wantErr bool
}{
name: "test1",
args: args{"../testingdata/testData/writeFile/tmp.json", ba, false},
args: args{"../testingdata/testData/writeFile/tmp.json", ba, false, false},
wantErr: false,
},
struct {
......@@ -79,7 +79,7 @@ func TestWriteFile(t *testing.T) {
wantErr bool
}{
name: "test2",
args: args{"../testingdata/testData/writeFile/test/tmp.json", ba, false},
args: args{"../testingdata/testData/writeFile/test/tmp.json", ba, false, false},
wantErr: true,
},
struct {
......@@ -88,7 +88,7 @@ func TestWriteFile(t *testing.T) {
wantErr bool
}{
name: "test3",
args: args{"../testingdata/testData/writeFile/test/tmp.json", ba, true},
args: args{"../testingdata/testData/writeFile/test/tmp.json", ba, true, false},
wantErr: false,
},
struct {
......@@ -97,7 +97,7 @@ func TestWriteFile(t *testing.T) {
wantErr bool
}{
name: "test4",
args: args{"../testingdata/testData/writeFile/test/", ba, true},
args: args{"../testingdata/testData/writeFile/test/", ba, true, false},
wantErr: true,
},
struct {
......@@ -106,13 +106,22 @@ func TestWriteFile(t *testing.T) {
wantErr bool
}{
name: "test5",
args: args{"../testingdata/testData/writeFile/test2?/tmp.json", ba, true},
args: args{"../testingdata/testData/writeFile/test2?/tmp.json", ba, true, false},
wantErr: true,
},
struct {
name string
args args
wantErr bool
}{
name: "test6",
args: args{"../testingdata/.symlink", ba, true, false},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := WriteFile(tt.args.filePath, tt.args.data, tt.args.makeDir); (err != nil) != tt.wantErr {
if err := WriteFile(tt.args.filePath, tt.args.data, tt.args.makeDir, tt.args.createFileBackup); (err != nil) != tt.wantErr {
t.Errorf("WriteFile() error = %v, wantErr %v", err, tt.wantErr)
}
})
......@@ -1115,7 +1124,7 @@ func TestMoveFile(t *testing.T) {
func TestReplaceFile(t *testing.T) {
ba, _ := dalhelper.GetDataFromFDB("../testingdata/users.json")
err := ReplaceFile(ba, "d:/output/ReplaceFile.json")
err := ReplaceFile(ba, "d:/output/ReplaceFile.json", false)
assert.NoError(t, err, "This should not thorw error")
}
......@@ -1129,3 +1138,57 @@ func TestFileInfo(t *testing.T) {
_, err := FileInfo("../testingdata/users.json")
assert.NoError(t, err, "This hsould not throw error")
}
func Test2WriteFile(t *testing.T) {
ba, _ := dalhelper.GetDataFromFDB("../testingdata/users.json")
err := WriteFile("../testingdata/users.json", ba, true, true)
assert.NoError(t, err, "Error expected Here")
}
func Test1_createFileBackup(t *testing.T) {
err := createFileBackup("../testingdata/tmp/tmp.json")
assert.Error(t, err, "Error expected Here")
}
func TestSetBackPath(t *testing.T) {
err := SetBackPath("D:/test/backup/", "D:/DB/")
assert.NoError(t, err, "No Error Here")
}
func Test1SetBackPath(t *testing.T) {
err := SetBackPath("", "D:/DB/")
assert.Error(t, err, "Error expected Here")
}
func Test2SetBackPath(t *testing.T) {
err := SetBackPath("D:/test/backup", "D:/DB/")
assert.Error(t, err, "Error expected Here")
}
func Test3SetBackPath(t *testing.T) {
err := SetBackPath("D:/test/backup/", "D:/DB")
assert.Error(t, err, "Error expected Here")
}
func Test4SetBackPath(t *testing.T) {
err := SetBackPath("../testingdata/backup/", "../testingdata/")
assert.NoError(t, err, "No Error Here")
}
func Test_createFileBackup(t *testing.T) {
SetBackPath("../testingdata/backup/", "../testingdata/")
err := createFileBackup("../testingdata/tmp/tmp.json")
assert.NoError(t, err, "No Error Here")
}
func Test2_createFileBackup(t *testing.T) {
SetBackPath("../testingdata/backup/", "../testingdata/")
errormdl.IsTestingNegetiveCaseOn = true
err := createFileBackup("../testingdata/tmp/tmp.json")
errormdl.IsTestingNegetiveCaseOn = false
assert.Error(t, err, "Error expected Here")
}
func Test1WriteFile(t *testing.T) {
ba, _ := dalhelper.GetDataFromFDB("../testingdata/users.json")
SetBackPath("../testingdata/backup/", "../testingdata/")
err := WriteFile("../testingdata/users.json", ba, true, true)
assert.NoError(t, err, "No Error Here")
}
......@@ -23,20 +23,20 @@ func init() {
}
// LoadData is a method sign for loader methods
type LoadData = func(ab *AbstractBusinessLogicHolder)
type LoadData = func(ab *AbstractBusinessLogicHolder) error
// FinalStepProcessOutput is a method sign for loader methods
type FinalStepProcessOutput = func(ab *AbstractBusinessLogicHolder) *interface{}
type FinalStepProcessOutput = func(ab *AbstractBusinessLogicHolder) (*interface{}, error)
// AbstractBusinessLogicHolder use this type to inheritance
type AbstractBusinessLogicHolder struct {
LocalServiceData map[string]interface{}
localServiceData map[string]interface{}
}
// GetDataString will give you string
func (ab *AbstractBusinessLogicHolder) GetDataString(key string) (string, bool) {
//check in map
temp, found := ab.LocalServiceData[key]
temp, found := ab.localServiceData[key]
if errormdl.CheckBool(!found) {
return "", false
}
......@@ -49,24 +49,24 @@ func (ab *AbstractBusinessLogicHolder) GetDataString(key string) (string, bool)
}
// GetDataInt will give you int
func (ab *AbstractBusinessLogicHolder) GetDataInt(key string) (int, bool) {
func (ab *AbstractBusinessLogicHolder) GetDataInt(key string) (int64, bool) {
//check in map
temp, found := ab.LocalServiceData[key]
temp, found := ab.localServiceData[key]
if errormdl.CheckBool(!found) {
return 0, false
}
// cast it
value, ok := temp.(int)
value, ok := temp.(int64)
if errormdl.CheckBool1(!ok) {
return 0, false
}
return value, true
}
// GetResultset will give you int
func (ab *AbstractBusinessLogicHolder) GetResultset(key string) (*gjson.Result, bool) {
// GetDataResultset will give you int
func (ab *AbstractBusinessLogicHolder) GetDataResultset(key string) (*gjson.Result, bool) {
//check in map
temp, found := ab.LocalServiceData[key]
temp, found := ab.localServiceData[key]
if errormdl.CheckBool(!found) {
loggermdl.LogWarn("Key not found -", key)
return &gjson.Result{}, false
......@@ -80,10 +80,10 @@ func (ab *AbstractBusinessLogicHolder) GetResultset(key string) (*gjson.Result,
return value, true
}
// GetBool will give you int
func (ab *AbstractBusinessLogicHolder) GetBool(key string) (bool, bool) {
// GetDataBool will give you int
func (ab *AbstractBusinessLogicHolder) GetDataBool(key string) (bool, bool) {
//check in map
temp, found := ab.LocalServiceData[key]
temp, found := ab.localServiceData[key]
if errormdl.CheckBool(!found) {
return false, false
}
......@@ -95,10 +95,10 @@ func (ab *AbstractBusinessLogicHolder) GetBool(key string) (bool, bool) {
return value, true
}
// GetInterface will give you string
func (ab *AbstractBusinessLogicHolder) GetInterface(key string) (interface{}, bool) {
// GetDataInterface will give you string
func (ab *AbstractBusinessLogicHolder) GetDataInterface(key string) (interface{}, bool) {
//check in map
temp, found := ab.LocalServiceData[key]
temp, found := ab.localServiceData[key]
if errormdl.CheckBool(!found) {
return 0, false
}
......@@ -108,41 +108,45 @@ func (ab *AbstractBusinessLogicHolder) GetInterface(key string) (interface{}, bo
// Build will create memory for your data
func (ab *AbstractBusinessLogicHolder) Build() {
ab.LocalServiceData = make(map[string]interface{})
ab.localServiceData = make(map[string]interface{})
}
// SetResultset will return map data with finaldata key
func (ab *AbstractBusinessLogicHolder) SetResultset(key string, obj *gjson.Result) {
ab.LocalServiceData[key] = obj
ab.localServiceData[key] = obj
}
// SetCustomData set custom user data in map
func (ab *AbstractBusinessLogicHolder) SetCustomData(key string, data interface{}) {
ab.localServiceData[key] = data
}
// GetFinalData will return map data with finaldata key
func (ab *AbstractBusinessLogicHolder) GetFinalData() *interface{} {
a := ab.LocalServiceData["finaldata"]
a := ab.localServiceData["finaldata"]
return &a
}
// SetFinalData will return map data with finaldata key
func (ab *AbstractBusinessLogicHolder) SetFinalData(data interface{}) {
ab.LocalServiceData["finaldata"] = data
ab.localServiceData["finaldata"] = data
}
// EchoBL sample EchoBL logic handler
func (ab *AbstractBusinessLogicHolder) EchoBL() map[string]interface{} {
func (ab *AbstractBusinessLogicHolder) EchoBL() (map[string]interface{}, error) {
// loggermdl.LogWarn("EchoBL called")
return map[string]interface{}{
"ok": int64(1),
}
}, nil
}
// Step help to maintain steps
type Step struct {
Stepname string
RawYQL string
expr conditions.Expr
processDataFunc LoadData
RunFunc func() map[string]interface{}
ErrorFunc func() map[string]interface{}
RunFunc func() (map[string]interface{}, error)
ErrorFunc func() (map[string]interface{}, error)
}
// ServiceBuilder will help you to run steps
......@@ -150,6 +154,7 @@ type ServiceBuilder struct {
ServiceName string
steps []Step
businessLogicHolder *AbstractBusinessLogicHolder
ServiceError error
}
// GetSB Gives you service builder from where you can run steps
......@@ -165,12 +170,17 @@ func GetSB(name string, ab *AbstractBusinessLogicHolder) *ServiceBuilder {
// Rule : Give Ybl rule
// blfunc : Give Business Logic function pointer
// errorfunc : Give Error function pointer
func (sb *ServiceBuilder) AddStep(stepname, rule string, ld LoadData, blfunc, errorfunc func() map[string]interface{}) *ServiceBuilder {
func (sb *ServiceBuilder) AddStep(stepname, rule string, ld LoadData, blfunc, errorfunc func() (map[string]interface{}, error)) *ServiceBuilder {
if errormdl.CheckErr(sb.ServiceError) != nil {
loggermdl.LogError(sb.ServiceError)
return sb
}
step := Step{}
step.RawYQL = rule
//Check rule in cache
mutex.Lock()
cachedRule, found := ruleCache[rule]
mutex.Unlock()
if errormdl.CheckBool(found) {
step.expr = cachedRule
} else {
......@@ -178,10 +188,11 @@ func (sb *ServiceBuilder) AddStep(stepname, rule string, ld LoadData, blfunc, er
// Parse the condition language and get expression
p := conditions.NewParser(strings.NewReader(rule))
expr, err := p.Parse()
if errormdl.CheckErr(err) != nil {
step.expr = expr
if errormdl.CheckErr1(err) != nil {
loggermdl.LogError("Error in step: ", stepname, err)
sb.ServiceError = errormdl.CheckErr1(err)
} else {
loggermdl.LogError("Error in step expr", err)
step.expr = expr
}
mutex.Lock()
ruleCache[rule] = expr
......@@ -197,31 +208,56 @@ func (sb *ServiceBuilder) AddStep(stepname, rule string, ld LoadData, blfunc, er
}
// Run all Steps one by one
func (sb *ServiceBuilder) Run() *ServiceBuilder {
func (sb *ServiceBuilder) Run(fn FinalStepProcessOutput) (*interface{}, error) {
if errormdl.CheckErr(sb.ServiceError) != nil {
loggermdl.LogError(sb.ServiceError)
return nil, errormdl.CheckErr(sb.ServiceError)
}
for _, step := range sb.steps {
//Load Data
if step.processDataFunc != nil {
step.processDataFunc(sb.businessLogicHolder)
daoError := step.processDataFunc(sb.businessLogicHolder)
if errormdl.CheckErr1(daoError) != nil {
loggermdl.LogError(daoError)
return nil, errormdl.CheckErr(daoError)
}
}
//Run step func
tmp := step.RunFunc()
// result, _ := yql.Match(step.RawYQL, tmp)
result, _ := conditions.Evaluate(step.expr, tmp)
tmp, blError := step.RunFunc()
if errormdl.CheckErr2(blError) != nil {
loggermdl.LogError(blError)
return nil, errormdl.CheckErr2(blError)
}
// Validation using conditions
result, evaluteError := conditions.Evaluate(step.expr, tmp)
if errormdl.CheckErr3(evaluteError) != nil {
loggermdl.LogError(evaluteError)
return nil, errormdl.CheckErr3(evaluteError)
}
// if validation fails
if !result {
// loggermdl.LogWarn(step.Stepname, "Failed", result)
step.ErrorFunc()
break
return sb.executeErrorFunction(step.ErrorFunc)
}
}
return sb
return sb.finalOutput(fn)
}
// executeErrorFunction exceute when validation failed for any step
func (sb *ServiceBuilder) executeErrorFunction(fn func() (map[string]interface{}, error)) (*interface{}, error) {
_, err := fn()
if errormdl.CheckErr(err) != nil {
loggermdl.LogError(err)
return nil, errormdl.CheckErr(err)
}
return nil, nil
}
// FinalOutput Step
func (sb *ServiceBuilder) FinalOutput(fn FinalStepProcessOutput) *interface{} {
// finalOutput return Final output
func (sb *ServiceBuilder) finalOutput(fn FinalStepProcessOutput) (*interface{}, error) {
if fn == nil {
return sb.businessLogicHolder.GetFinalData()
return sb.businessLogicHolder.GetFinalData(), nil
}
return fn(sb.businessLogicHolder)
}
This diff is collapsed.
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment