mirror of
https://gitee.com/winc-link/hummingbird.git
synced 2025-04-21 17:02:43 +00:00
376 lines
10 KiB
Go
376 lines
10 KiB
Go
/*******************************************************************************
|
|
* Copyright 2017 Dell Inc.
|
|
* Copyright (c) 2019 Intel Corporation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
* in compliance with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
* or implied. See the License for the specific language governing permissions and limitations under
|
|
* the License.
|
|
*******************************************************************************/
|
|
package leveldb
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
|
"github.com/syndtr/goleveldb/leveldb/util"
|
|
"github.com/winc-link/hummingbird/internal/dtos"
|
|
interfaces "github.com/winc-link/hummingbird/internal/hummingbird/core/interface"
|
|
"github.com/winc-link/hummingbird/internal/models"
|
|
"github.com/winc-link/hummingbird/internal/pkg/constants"
|
|
"github.com/winc-link/hummingbird/internal/pkg/errort"
|
|
"github.com/winc-link/hummingbird/internal/pkg/logger"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
)
|
|
|
|
type Client struct {
|
|
client *LevelDB
|
|
loggingClient logger.LoggingClient
|
|
}
|
|
|
|
func (c *Client) AddDatabaseField(ctx context.Context, tableName string, specsType constants.SpecsType, code string, name string) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) DelDatabaseField(ctx context.Context, tableName, code string) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) ModifyDatabaseField(ctx context.Context, tableName string, specsType constants.SpecsType, code string, name string) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) GetDataDBType() constants.DataType {
|
|
return constants.LevelDB
|
|
}
|
|
|
|
func (c *Client) DropStable(ctx context.Context, table string) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) CreateStable(ctx context.Context, product models.Product) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) DropTable(ctx context.Context, table string) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) CreateTable(ctx context.Context, stable, table string) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func NewClient(config dtos.Configuration, lc logger.LoggingClient) (c interfaces.DataDBClient, errEdgeX error) {
|
|
dataSourceDir := filepath.Dir(config.DataSource)
|
|
_, fileErr := os.Stat(dataSourceDir)
|
|
if fileErr != nil || !os.IsExist(fileErr) {
|
|
_ = os.MkdirAll(dataSourceDir, os.ModePerm)
|
|
}
|
|
var (
|
|
client *leveldb.DB
|
|
err error
|
|
)
|
|
if client, err = leveldb.OpenFile(dataSourceDir, nil); err != nil {
|
|
if client, err = leveldb.RecoverFile(dataSourceDir, nil); err != nil {
|
|
errEdgeX = errort.NewCommonEdgeX(errort.KindDatabaseError, "database failed to init", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
ldb := &LevelDB{
|
|
DB: client,
|
|
}
|
|
c = &Client{
|
|
client: ldb,
|
|
loggingClient: lc,
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) CloseSession() {
|
|
c.client.Close()
|
|
}
|
|
|
|
func (c *Client) Insert(ctx context.Context, table string, data map[string]interface{}) (err error) {
|
|
batch := new(leveldb.Batch)
|
|
defer batch.Reset()
|
|
|
|
for k, v := range data {
|
|
b, ok := v.([]byte)
|
|
if ok {
|
|
batch.Put([]byte(k), b)
|
|
}
|
|
}
|
|
if err = c.client.Write(batch, &opt.WriteOptions{
|
|
//NoWriteMerge: true,
|
|
//Sync: true,
|
|
}); err != nil {
|
|
return errort.NewCommonEdgeX(errort.KindDatabaseError, "batch transaction write", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) GetDeviceService(req dtos.ThingModelServiceDataRequest, device models.Device, product models.Product) ([]dtos.SaveServiceIssueData, int, error) {
|
|
var baseKey string
|
|
var response []dtos.SaveServiceIssueData
|
|
var count int
|
|
if req.DeviceId == "" {
|
|
return response, count, fmt.Errorf("deviceId is nill")
|
|
}
|
|
if req.Code == "" {
|
|
baseKey = req.DeviceId + "-" + constants.Action + "-"
|
|
} else {
|
|
baseKey = req.DeviceId + "-" + constants.Action + "-" + req.Code + "-"
|
|
}
|
|
if len(req.Range) == 2 {
|
|
var firstTime, lastTime string
|
|
if req.Range[0] < req.Range[1] {
|
|
firstTime = strconv.Itoa(int(req.Range[0]))
|
|
lastTime = strconv.Itoa(int(req.Range[1]))
|
|
} else {
|
|
firstTime = strconv.Itoa(int(req.Range[1]))
|
|
lastTime = strconv.Itoa(int(req.Range[0]))
|
|
}
|
|
iter := c.client.NewIterator(&util.Range{Start: []byte(baseKey + firstTime), Limit: []byte(baseKey + lastTime)}, &opt.ReadOptions{
|
|
DontFillCache: true,
|
|
})
|
|
|
|
var start int
|
|
var end int
|
|
|
|
start = (req.Page-1)*req.PageSize + 1
|
|
end = (req.Page-1)*req.PageSize + req.PageSize
|
|
|
|
if iter.Last() {
|
|
count++
|
|
var dbvalue dtos.SaveServiceIssueData
|
|
err := json.Unmarshal(iter.Value(), &dbvalue)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
response = append(response, dbvalue)
|
|
for iter.Prev() {
|
|
count++
|
|
if count >= start && count <= end {
|
|
var dbvalue dtos.SaveServiceIssueData
|
|
err := json.Unmarshal(iter.Value(), &dbvalue)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
response = append(response, dbvalue)
|
|
}
|
|
|
|
}
|
|
}
|
|
iter.Release()
|
|
}
|
|
return response, count, nil
|
|
}
|
|
|
|
func (c *Client) GetDeviceEventCount(req dtos.ThingModelEventDataRequest) (int, error) {
|
|
var baseKey string
|
|
var count int
|
|
if req.DeviceId == "" {
|
|
return 0, fmt.Errorf("deviceId is nill")
|
|
}
|
|
if req.EventCode == "" {
|
|
baseKey = req.DeviceId + "-" + constants.Event + "-"
|
|
} else {
|
|
baseKey = req.DeviceId + "-" + constants.Event + "-" + req.EventCode + "-"
|
|
}
|
|
if len(req.Range) == 2 {
|
|
var firstTime, lastTime string
|
|
if req.Range[0] < req.Range[1] {
|
|
firstTime = strconv.Itoa(int(req.Range[0]))
|
|
lastTime = strconv.Itoa(int(req.Range[1]))
|
|
} else {
|
|
firstTime = strconv.Itoa(int(req.Range[1]))
|
|
lastTime = strconv.Itoa(int(req.Range[0]))
|
|
}
|
|
|
|
iter := c.client.NewIterator(&util.Range{Start: []byte(baseKey + firstTime), Limit: []byte(baseKey + lastTime)}, &opt.ReadOptions{
|
|
DontFillCache: true,
|
|
})
|
|
for iter.Next() {
|
|
count++
|
|
}
|
|
iter.Release()
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func (c *Client) GetDeviceEvent(req dtos.ThingModelEventDataRequest, device models.Device, product models.Product) ([]dtos.EventData, int, error) {
|
|
var baseKey string
|
|
var response []dtos.EventData
|
|
var count int
|
|
|
|
if req.DeviceId == "" {
|
|
return response, count, fmt.Errorf("deviceId is nill")
|
|
}
|
|
if req.EventCode == "" {
|
|
baseKey = req.DeviceId + "-" + constants.Event + "-"
|
|
} else {
|
|
baseKey = req.DeviceId + "-" + constants.Event + "-" + req.EventCode + "-"
|
|
}
|
|
if len(req.Range) == 2 {
|
|
var firstTime, lastTime string
|
|
if req.Range[0] < req.Range[1] {
|
|
firstTime = strconv.Itoa(int(req.Range[0]))
|
|
lastTime = strconv.Itoa(int(req.Range[1]))
|
|
} else {
|
|
firstTime = strconv.Itoa(int(req.Range[1]))
|
|
lastTime = strconv.Itoa(int(req.Range[0]))
|
|
}
|
|
|
|
iter := c.client.NewIterator(&util.Range{Start: []byte(baseKey + firstTime), Limit: []byte(baseKey + lastTime)}, &opt.ReadOptions{
|
|
DontFillCache: true,
|
|
})
|
|
var start int
|
|
var end int
|
|
|
|
start = (req.Page-1)*req.PageSize + 1
|
|
end = (req.Page-1)*req.PageSize + req.PageSize
|
|
|
|
if iter.Last() {
|
|
count++
|
|
var dbvalue dtos.EventData
|
|
_ = json.Unmarshal(iter.Value(), &dbvalue)
|
|
response = append(response, dbvalue)
|
|
for iter.Prev() {
|
|
count++
|
|
if count >= start && count <= end {
|
|
var dbvalue dtos.EventData
|
|
_ = json.Unmarshal(iter.Value(), &dbvalue)
|
|
response = append(response, dbvalue)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
iter.Release()
|
|
|
|
}
|
|
return response, count, nil
|
|
}
|
|
|
|
func (c *Client) GetDevicePropertyCount(req dtos.ThingModelPropertyDataRequest) (int, error) {
|
|
var baseKey string
|
|
var count int
|
|
if req.DeviceId == "" {
|
|
return 0, fmt.Errorf("deviceId is nill")
|
|
}
|
|
if req.Code == "" {
|
|
baseKey = req.DeviceId + "-" + constants.Property + "-"
|
|
} else {
|
|
baseKey = req.DeviceId + "-" + constants.Property + "-" + req.Code + "-"
|
|
}
|
|
|
|
if len(req.Range) == 2 {
|
|
var firstTime, lastTime string
|
|
if req.Range[0] < req.Range[1] {
|
|
firstTime = strconv.Itoa(int(req.Range[0]))
|
|
lastTime = strconv.Itoa(int(req.Range[1]))
|
|
} else {
|
|
firstTime = strconv.Itoa(int(req.Range[1]))
|
|
lastTime = strconv.Itoa(int(req.Range[0]))
|
|
}
|
|
iter := c.client.NewIterator(&util.Range{Start: []byte(baseKey + firstTime), Limit: []byte(baseKey + lastTime)}, &opt.ReadOptions{
|
|
DontFillCache: true,
|
|
})
|
|
for iter.Next() {
|
|
count++
|
|
}
|
|
iter.Release()
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func (c *Client) GetDeviceProperty(req dtos.ThingModelPropertyDataRequest, device models.Device) ([]dtos.ReportData, int, error) {
|
|
var baseKey string
|
|
var response []dtos.ReportData
|
|
var count int
|
|
if req.DeviceId == "" {
|
|
return response, count, fmt.Errorf("deviceId is nill")
|
|
}
|
|
if req.Code == "" {
|
|
baseKey = req.DeviceId + "-" + constants.Property + "-"
|
|
} else {
|
|
baseKey = req.DeviceId + "-" + constants.Property + "-" + req.Code + "-"
|
|
}
|
|
|
|
if len(req.Range) == 2 {
|
|
var firstTime, lastTime string
|
|
if req.Range[0] < req.Range[1] {
|
|
firstTime = strconv.Itoa(int(req.Range[0]))
|
|
lastTime = strconv.Itoa(int(req.Range[1]))
|
|
} else {
|
|
firstTime = strconv.Itoa(int(req.Range[1]))
|
|
lastTime = strconv.Itoa(int(req.Range[0]))
|
|
}
|
|
|
|
iter := c.client.NewIterator(&util.Range{Start: []byte(baseKey + firstTime), Limit: []byte(baseKey + lastTime)}, &opt.ReadOptions{
|
|
DontFillCache: true,
|
|
})
|
|
var start int
|
|
var end int
|
|
|
|
start = (req.Page-1)*req.PageSize + 1
|
|
end = (req.Page-1)*req.PageSize + req.PageSize
|
|
|
|
if iter.Last() {
|
|
count++
|
|
var dbvalue dtos.ReportData
|
|
_ = json.Unmarshal(iter.Value(), &dbvalue)
|
|
response = append(response, dbvalue)
|
|
for iter.Prev() {
|
|
count++
|
|
if count >= start && count <= end {
|
|
var dbvalue dtos.ReportData
|
|
_ = json.Unmarshal(iter.Value(), &dbvalue)
|
|
response = append(response, dbvalue)
|
|
}
|
|
|
|
}
|
|
}
|
|
iter.Release()
|
|
} else if req.First {
|
|
iter := c.client.NewIterator(util.BytesPrefix([]byte(baseKey)), &opt.ReadOptions{
|
|
DontFillCache: true,
|
|
})
|
|
if iter.First() {
|
|
var dbvalue dtos.ReportData
|
|
_ = json.Unmarshal(iter.Value(), &dbvalue)
|
|
response = append(response, dbvalue)
|
|
}
|
|
iter.Release()
|
|
} else if req.Last {
|
|
iter := c.client.NewIterator(util.BytesPrefix([]byte(baseKey)), nil)
|
|
if iter.Last() {
|
|
var dbvalue dtos.ReportData
|
|
_ = json.Unmarshal(iter.Value(), &dbvalue)
|
|
response = append(response, dbvalue)
|
|
//break
|
|
}
|
|
iter.Release()
|
|
} else {
|
|
|
|
}
|
|
return response, count, nil
|
|
}
|
|
|
|
func (c *Client) GetDeviceMsgCountByGiveTime(deviceId string, startTime, endTime int64) (int, error) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|