mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
126 lines
4.0 KiB
Go
126 lines
4.0 KiB
Go
/*
|
|
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
|
Copyright (C) ITsysCOM GmbH
|
|
This program 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.
|
|
This program 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 this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
package engine
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/cgrates/cgrates/config"
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
func newDynamicDP(resConns, stsConns, apiConns []string,
|
|
tenant string, initialDP utils.DataProvider) *dynamicDP {
|
|
return &dynamicDP{
|
|
resConns: resConns,
|
|
stsConns: stsConns,
|
|
apiConns: apiConns,
|
|
tenant: tenant,
|
|
initialDP: initialDP,
|
|
cache: utils.MapStorage{},
|
|
}
|
|
}
|
|
|
|
type dynamicDP struct {
|
|
resConns []string
|
|
stsConns []string
|
|
apiConns []string
|
|
tenant string
|
|
initialDP utils.DataProvider
|
|
|
|
cache utils.MapStorage
|
|
}
|
|
|
|
func (dDP *dynamicDP) String() string { return dDP.initialDP.String() }
|
|
|
|
func (dDP *dynamicDP) FieldAsString(fldPath []string) (string, error) {
|
|
val, err := dDP.FieldAsInterface(fldPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return utils.IfaceAsString(val), nil
|
|
}
|
|
|
|
func (dDP *dynamicDP) RemoteHost() net.Addr {
|
|
return utils.LocalAddr()
|
|
}
|
|
|
|
var initialDPPrefixes = utils.NewStringSet([]string{utils.MetaReq, utils.MetaVars,
|
|
utils.MetaCgreq, utils.MetaCgrep, utils.MetaRep, utils.MetaCGRAReq,
|
|
utils.MetaAct, utils.MetaEC, utils.MetaUCH, utils.MetaOpts})
|
|
|
|
func (dDP *dynamicDP) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
|
if len(fldPath) == 0 {
|
|
return nil, utils.ErrNotFound
|
|
}
|
|
if initialDPPrefixes.Has(fldPath[0]) {
|
|
return dDP.initialDP.FieldAsInterface(fldPath)
|
|
}
|
|
val, err = dDP.cache.FieldAsInterface(fldPath)
|
|
if err == utils.ErrNotFound { // in case not found in cache try to populate it
|
|
return dDP.fieldAsInterface(fldPath)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (dDP *dynamicDP) fieldAsInterface(fldPath []string) (val interface{}, err error) {
|
|
if len(fldPath) < 2 {
|
|
return nil, fmt.Errorf("invalid fieldname <%s>", fldPath)
|
|
}
|
|
switch fldPath[0] {
|
|
case utils.MetaAccounts:
|
|
// sample of fieldName : ~*accounts.1001.BalanceMap.*monetary[0].Value
|
|
// split the field name in 3 parts
|
|
// fieldNameType (~*accounts), accountID(1001) and queried part (BalanceMap.*monetary[0].Value)
|
|
|
|
var account Account
|
|
if err = connMgr.Call(dDP.apiConns, nil, utils.APIerSv2GetAccount,
|
|
&utils.AttrGetAccount{Tenant: dDP.tenant, Account: fldPath[1]}, &account); err != nil {
|
|
return
|
|
}
|
|
//construct dataProvider from account and set it further
|
|
dp := config.NewObjectDP(account)
|
|
dDP.cache.Set(fldPath[:2], dp)
|
|
return dp.FieldAsInterface(fldPath[2:])
|
|
case utils.MetaResources:
|
|
// sample of fieldName : ~*resources.ResourceID.Field
|
|
var reply *Resource
|
|
if err := connMgr.Call(dDP.resConns, nil, utils.ResourceSv1GetResource,
|
|
&utils.TenantID{Tenant: dDP.tenant, ID: fldPath[1]}, &reply); err != nil {
|
|
return nil, err
|
|
}
|
|
dp := config.NewObjectDP(reply)
|
|
dDP.cache.Set(fldPath[:2], dp)
|
|
return dp.FieldAsInterface(fldPath[2:])
|
|
case utils.MetaStats:
|
|
// sample of fieldName : ~*stats.StatID.*acd
|
|
var statValues map[string]float64
|
|
|
|
if err := connMgr.Call(dDP.stsConns, nil, utils.StatSv1GetQueueFloatMetrics,
|
|
&utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: dDP.tenant, ID: fldPath[1]}},
|
|
&statValues); err != nil {
|
|
return nil, err
|
|
}
|
|
for k, v := range statValues {
|
|
dDP.cache.Set([]string{utils.MetaStats, fldPath[1], k}, v)
|
|
}
|
|
return dDP.cache.FieldAsInterface(fldPath)
|
|
default: // in case of constant we give an empty DataProvider ( empty navigable map )
|
|
}
|
|
return nil, utils.ErrNotFound
|
|
}
|