Merge fixes

This commit is contained in:
DanB
2017-10-13 14:20:29 +02:00
30 changed files with 929 additions and 656 deletions

View File

@@ -28,7 +28,7 @@ func (self *ApierV1) SetFilter(attrs *engine.Filter, reply *string) error {
if missing := utils.MissingStructFields(attrs, []string{"Tenant", "ID"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if err := self.DataManager.DataDB().SetFilter(attrs); err != nil {
if err := self.DataManager.SetFilter(attrs); err != nil {
return utils.APIErrorHandler(err)
}
*reply = utils.OK
@@ -40,7 +40,7 @@ func (self *ApierV1) GetFilter(arg utils.TenantID, reply *engine.Filter) error {
if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
return utils.NewErrMandatoryIeMissing(missing...)
}
if fltr, err := self.DataManager.DataDB().GetFilter(arg.Tenant, arg.ID, true, utils.NonTransactional); err != nil {
if fltr, err := self.DataManager.GetFilter(arg.Tenant, arg.ID, true, utils.NonTransactional); err != nil {
if err.Error() != utils.ErrNotFound.Error() {
err = utils.NewErrServerError(err)
}
@@ -56,7 +56,7 @@ func (self *ApierV1) RemFilter(arg utils.TenantID, reply *string) error {
if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
return utils.NewErrMandatoryIeMissing(missing...)
}
if err := self.DataManager.DataDB().RemoveFilter(arg.Tenant, arg.ID, utils.NonTransactional); err != nil {
if err := self.DataManager.RemoveFilter(arg.Tenant, arg.ID, utils.NonTransactional); err != nil {
if err.Error() != utils.ErrNotFound.Error() {
err = utils.NewErrServerError(err)
}

View File

@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package v1
/*
import (
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
@@ -30,172 +29,185 @@ import (
"path"
"reflect"
"testing"
"time"
)
var (
filterProfileCfgPath string
filterProfileCfg *config.CGRConfig
filterProfileRPC *rpc.Client
filterProfileDataDir = "/usr/share/cgrates"
filterProfile *engine.FilterProfile
filterProfileDelay int
filterProfileConfigDIR string //run tests for specific configuration
filterCfgPath string
filterCfg *config.CGRConfig
filterRPC *rpc.Client
filterDataDir = "/usr/share/cgrates"
filter *engine.Filter
filterDelay int
filterConfigDIR string //run tests for specific configuration
)
var sTestsFilterProfile = []func(t *testing.T){
testFilterProfileInitCfg,
testFilterProfileResetDataDB,
testFilterProfileStartEngine,
testFilterProfileRpcConn,
testFilterProfileGetFilterProfileBeforeSet,
testFilterProfileSetFilterProfile,
testFilterProfileGetFilterProfileAfterSet,
testFilterProfileUpdateFilterProfile,
testFilterProfileGetFilterProfileAfterUpdate,
testFilterProfileRemFilterProfile,
testFilterProfileGetFilterProfileAfterRemove,
testFilterProfileKillEngine,
var sTestsFilter = []func(t *testing.T){
testFilterInitCfg,
testFilterResetDataDB,
testFilterStartEngine,
testFilterRpcConn,
testFilterGetFilterBeforeSet,
testFilterSetFilter,
testFilterGetFilterAfterSet,
testFilterUpdateFilter,
testFilterGetFilterAfterUpdate,
testFilterRemFilter,
testFilterGetFilterAfterRemove,
testFilterKillEngine,
}
//Test start here
func TestFilterProfileITMySql(t *testing.T) {
filterProfileConfigDIR = "tutmysql"
for _, stest := range sTestsFilterProfile {
t.Run(filterProfileConfigDIR, stest)
func TestFilterITMySql(t *testing.T) {
filterConfigDIR = "tutmysql"
for _, stest := range sTestsFilter {
t.Run(filterConfigDIR, stest)
}
}
func TestFilterProfileITMongo(t *testing.T) {
filterProfileConfigDIR = "tutmongo"
for _, stest := range sTestsFilterProfile {
t.Run(filterProfileConfigDIR, stest)
func TestFilterITMongo(t *testing.T) {
filterConfigDIR = "tutmongo"
for _, stest := range sTestsFilter {
t.Run(filterConfigDIR, stest)
}
}
func TestFilterProfileITPG(t *testing.T) {
filterProfileConfigDIR = "tutpostgres"
for _, stest := range sTestsFilterProfile {
t.Run(filterProfileConfigDIR, stest)
func TestFilterITPG(t *testing.T) {
filterConfigDIR = "tutpostgres"
for _, stest := range sTestsFilter {
t.Run(filterConfigDIR, stest)
}
}
func testFilterProfileInitCfg(t *testing.T) {
func testFilterInitCfg(t *testing.T) {
var err error
filterProfileCfgPath = path.Join(filterProfileDataDir, "conf", "samples", filterProfileConfigDIR)
filterProfileCfg, err = config.NewCGRConfigFromFolder(filterProfileCfgPath)
filterCfgPath = path.Join(filterDataDir, "conf", "samples", filterConfigDIR)
filterCfg, err = config.NewCGRConfigFromFolder(filterCfgPath)
if err != nil {
t.Error(err)
}
filterProfileCfg.DataFolderPath = filterProfileDataDir // Share DataFolderPath through config towards StoreDb for Flush()
config.SetCgrConfig(filterProfileCfg)
switch filterProfileConfigDIR {
filterCfg.DataFolderPath = filterDataDir // Share DataFolderPath through config towards StoreDb for Flush()
config.SetCgrConfig(filterCfg)
switch filterConfigDIR {
case "tutmongo": // Mongo needs more time to reset db, need to investigate
filterProfileDelay = 2000
filterDelay = 2000
default:
filterProfileDelay = 1000
filterDelay = 1000
}
}
// Wipe out the cdr database
func testFilterProfileResetDataDB(t *testing.T) {
if err := engine.InitDataDb(filterProfileCfg); err != nil {
func testFilterResetDataDB(t *testing.T) {
if err := engine.InitDataDb(filterCfg); err != nil {
t.Fatal(err)
}
}
// Start CGR Engine
func testFilterProfileStartEngine(t *testing.T) {
if _, err := engine.StopStartEngine(filterProfileCfgPath, filterProfileDelay); err != nil {
func testFilterStartEngine(t *testing.T) {
if _, err := engine.StopStartEngine(filterCfgPath, filterDelay); err != nil {
t.Fatal(err)
}
}
// Connect rpc client to rater
func testFilterProfileRpcConn(t *testing.T) {
func testFilterRpcConn(t *testing.T) {
var err error
filterProfileRPC, err = jsonrpc.Dial("tcp", filterProfileCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
filterRPC, err = jsonrpc.Dial("tcp", filterCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
if err != nil {
t.Fatal(err)
}
}
func testFilterProfileGetFilterProfileBeforeSet(t *testing.T) {
var reply *engine.FilterProfile
if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
func testFilterGetFilterBeforeSet(t *testing.T) {
var reply *engine.Filter
if err := filterRPC.Call("ApierV1.GetFilter", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
t.Error(err)
}
}
func testFilterProfileSetFilterProfile(t *testing.T) {
filterProfile = &engine.FilterProfile{
Tenant: "cgrates.org",
ID: "Filter1",
FilterType: "*string_prefix",
FilterFieldName: "Account",
FilterFieldValues: []string{"10", "20"},
func testFilterSetFilter(t *testing.T) {
filter = &engine.Filter{
Tenant: "cgrates.org",
ID: "Filter1",
RequestFilters: []*engine.RequestFilter{
&engine.RequestFilter{
FieldName: "*string",
Type: "Account",
Values: []string{"1001", "1002"},
},
},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC).Local(),
ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC).Local(),
},
}
var result string
if err := filterProfileRPC.Call("ApierV1.SetFilterProfile", filterProfile, &result); err != nil {
if err := filterRPC.Call("ApierV1.SetFilter", filter, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
}
}
func testFilterProfileGetFilterProfileAfterSet(t *testing.T) {
var reply *engine.FilterProfile
if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err != nil {
func testFilterGetFilterAfterSet(t *testing.T) {
var reply *engine.Filter
if err := filterRPC.Call("ApierV1.GetFilter", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(filterProfile, reply) {
t.Errorf("Expecting : %+v, received: %+v", filterProfile, reply)
} else if !reflect.DeepEqual(filter, reply) {
t.Errorf("Expecting : %+v, received: %+v", filter, reply)
}
}
func testFilterProfileUpdateFilterProfile(t *testing.T) {
filterProfile = &engine.FilterProfile{
Tenant: "cgrates.org",
ID: "Filter1",
FilterType: "*string_prefix",
FilterFieldName: "Destination",
FilterFieldValues: []string{"1001", "1002"},
func testFilterUpdateFilter(t *testing.T) {
filter.RequestFilters = []*engine.RequestFilter{
&engine.RequestFilter{
FieldName: "*string",
Type: "Account",
Values: []string{"1001", "1002"},
},
&engine.RequestFilter{
FieldName: "*string_prefix",
Type: "Destination",
Values: []string{"10", "20"},
},
}
var result string
if err := filterProfileRPC.Call("ApierV1.SetFilterProfile", filterProfile, &result); err != nil {
if err := filterRPC.Call("ApierV1.SetFilter", filter, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
}
}
func testFilterProfileGetFilterProfileAfterUpdate(t *testing.T) {
var reply *engine.FilterProfile
if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err != nil {
func testFilterGetFilterAfterUpdate(t *testing.T) {
var reply *engine.Filter
if err := filterRPC.Call("ApierV1.GetFilter", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(filterProfile, reply) {
t.Errorf("Expecting : %+v, received: %+v", filterProfile, reply)
} else if !reflect.DeepEqual(filter, reply) {
t.Errorf("Expecting : %+v, received: %+v", filter, reply)
}
}
func testFilterProfileRemFilterProfile(t *testing.T) {
func testFilterRemFilter(t *testing.T) {
var resp string
if err := filterProfileRPC.Call("ApierV1.RemFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &resp); err != nil {
if err := filterRPC.Call("ApierV1.RemFilter", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &resp); err != nil {
t.Error(err)
} else if resp != utils.OK {
t.Error("Unexpected reply returned", resp)
}
}
func testFilterProfileGetFilterProfileAfterRemove(t *testing.T) {
var reply *engine.FilterProfile
if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
func testFilterGetFilterAfterRemove(t *testing.T) {
var reply *engine.Filter
if err := filterRPC.Call("ApierV1.GetFilter", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
t.Error(err)
}
}
func testFilterProfileKillEngine(t *testing.T) {
if err := engine.KillEngine(filterProfileDelay); err != nil {
func testFilterKillEngine(t *testing.T) {
if err := engine.KillEngine(filterDelay); err != nil {
t.Error(err)
}
}
*/

View File

@@ -507,8 +507,8 @@ func testV1RsSetResourceProfile(t *testing.T) {
rlsConfig = &engine.ResourceProfile{
Tenant: "cgrates.org",
ID: "RCFG1",
Filters: []*engine.Filter{
&engine.Filter{
Filters: []*engine.RequestFilter{
&engine.RequestFilter{
Type: "type",
FieldName: "Name",
Values: []string{"FilterValue1", "FilterValue2"},
@@ -546,13 +546,13 @@ func testV1RsGetResourceProfileAfterSet(t *testing.T) {
func testV1RsUpdateResourceProfile(t *testing.T) {
var result string
rlsConfig.Filters = []*engine.Filter{
&engine.Filter{
rlsConfig.Filters = []*engine.RequestFilter{
&engine.RequestFilter{
Type: "type",
FieldName: "Name",
Values: []string{"FilterValue1", "FilterValue2"},
},
&engine.Filter{
&engine.RequestFilter{
Type: "*string",
FieldName: "Accout",
Values: []string{"1001", "1002"},

View File

@@ -277,8 +277,8 @@ func testV1STSSetStatQueueProfile(t *testing.T) {
statConfig = &engine.StatQueueProfile{
Tenant: "cgrates.org",
ID: "TEST_PROFILE1",
Filters: []*engine.Filter{
&engine.Filter{
Filters: []*engine.RequestFilter{
&engine.RequestFilter{
Type: "type",
FieldName: "Name",
Values: []string{"FilterValue1", "FilterValue2"},
@@ -313,18 +313,18 @@ func testV1STSSetStatQueueProfile(t *testing.T) {
func testV1STSUpdateStatQueueProfile(t *testing.T) {
var result string
statConfig.Filters = []*engine.Filter{
&engine.Filter{
statConfig.Filters = []*engine.RequestFilter{
&engine.RequestFilter{
Type: "type",
FieldName: "Name",
Values: []string{"FilterValue1", "FilterValue2"},
},
&engine.Filter{
&engine.RequestFilter{
Type: "*string",
FieldName: "Accout",
Values: []string{"1001", "1002"},
},
&engine.Filter{
&engine.RequestFilter{
Type: "*string_prefix",
FieldName: "Destination",
Values: []string{"10", "20"},

View File

@@ -128,12 +128,20 @@ func ttestTPFilterGetTPFilterBeforeSet(t *testing.T) {
func testTPFilterSetTPFilter(t *testing.T) {
tpFilter = &utils.TPFilter{
TPid: "TP1",
Tenant: "cgrates.org",
ID: "Filter",
FilterType: "*string",
FilterFieldName: "Account",
FilterFielValues: []string{"1001", "1002"},
TPid: "TP1",
Tenant: "cgrates.org",
ID: "Filter",
Filters: []*utils.TPRequestFilter{
&utils.TPRequestFilter{
Type: "*string",
FieldName: "Account",
Values: []string{"1001", "1002"},
},
},
ActivationInterval: &utils.TPActivationInterval{
ActivationTime: "2014-07-29T15:00:00Z",
ExpiryTime: "",
},
}
var result string
@@ -166,15 +174,18 @@ func testTPFilterGetFilterIds(t *testing.T) {
}
func testTPFilterUpdateTPFilter(t *testing.T) {
tpFilter = &utils.TPFilter{
TPid: "TP1",
Tenant: "cgrates.org",
ID: "Filter",
FilterType: "*string_prefix",
FilterFieldName: "Account",
FilterFielValues: []string{"10", "20"},
tpFilter.Filters = []*utils.TPRequestFilter{
&utils.TPRequestFilter{
Type: "*string",
FieldName: "Account",
Values: []string{"1001", "1002"},
},
&utils.TPRequestFilter{
Type: "*string_prefix",
FieldName: "Destination",
Values: []string{"10", "20"},
},
}
var result string
if err := tpFilterRPC.Call("ApierV1.SetTPFilter", tpFilter, &result); err != nil {
t.Error(err)

View File

@@ -147,6 +147,7 @@ func testTPThreholdSetTPThrehold(t *testing.T) {
Blocker: true,
Weight: 10,
ActionIDs: []string{"Thresh1", "Thresh2"},
Async: true,
}
var result string
if err := tpThresholdRPC.Call("ApierV1.SetTPThreshold", tpThreshold, &result); err != nil {

View File

@@ -465,6 +465,7 @@ CREATE TABLE tp_thresholds (
`blocker` BOOLEAN NOT NULL,
`weight` decimal(8,2) NOT NULL,
`action_ids` varchar(64) NOT NULL,
`async` BOOLEAN NOT NULL,
`created_at` TIMESTAMP,
PRIMARY KEY (`pk`),
KEY `tpid` (`tpid`),
@@ -484,6 +485,7 @@ CREATE TABLE tp_filters (
`filter_type` varchar(16) NOT NULL,
`filter_field_name` varchar(64) NOT NULL,
`filter_field_values` varchar(256) NOT NULL,
`activation_interval` varchar(64) NOT NULL,
`created_at` TIMESTAMP,
PRIMARY KEY (`pk`),
KEY `tpid` (`tpid`),

View File

@@ -460,6 +460,7 @@ CREATE TABLE tp_thresholds (
"blocker" BOOLEAN NOT NULL,
"weight" decimal(8,2) NOT NULL,
"action_ids" varchar(64) NOT NULL,
"async" BOOLEAN NOT NULL,
"created_at" TIMESTAMP WITH TIME ZONE
);
CREATE INDEX tp_thresholds_idx ON tp_thresholds (tpid);
@@ -478,6 +479,7 @@ CREATE TABLE tp_filters (
"filter_type" varchar(16) NOT NULL,
"filter_field_name" varchar(64) NOT NULL,
"filter_field_values" varchar(256) NOT NULL,
"activation_interval" varchar(64) NOT NULL,
"created_at" TIMESTAMP WITH TIME ZONE
);
CREATE INDEX tp_filters_idx ON tp_filters (tpid);

View File

@@ -1,7 +1,7 @@
#Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4]
cgrates.org,FLTR_1,*string,Account,1001;1002
cgrates.org,FLTR_1,*string_prefix,Destination,10;20
cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002)
cgrates.org,FLTR_ACNT_dan,*string,Account,dan
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL
#Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5]
cgrates.org,FLTR_1,*string,Account,1001;1002,2014-07-29T15:00:00Z
cgrates.org,FLTR_1,*string_prefix,Destination,10;20,2014-07-29T15:00:00Z
cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),
cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL,2014-07-29T15:00:00Z
1 #Tenant[0] ID[1] FilterType[2] FilterFieldName[3] FilterFieldValues[4] ActivationInterval[5]
2 cgrates.org FLTR_1 *string Account 1001;1002 2014-07-29T15:00:00Z
3 cgrates.org FLTR_1 *string_prefix Destination 10;20 2014-07-29T15:00:00Z
4 cgrates.org FLTR_1 *rsr_fields Subject(~^1.*1$);Destination(1002)
5 cgrates.org FLTR_ACNT_dan *string Account dan 2014-07-29T15:00:00Z
6 cgrates.org FLTR_DST_DE *destinations Destination DST_DE 2014-07-29T15:00:00Z
7 cgrates.org FLTR_DST_NL *destinations Destination DST_NL 2014-07-29T15:00:00Z

View File

@@ -1,2 +1,2 @@
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],Recurrent[6],MinSleep[7],Blocker[8],Weight[9],ActionIDs[10]
cgrates.org,Threshold1,*string,Account,1001;1002,2014-07-29T15:00:00Z,true,1s,true,10,THRESH1;THRESH2
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],Recurrent[6],MinSleep[7],Blocker[8],Weight[9],ActionIDs[10],Async[11]
cgrates.org,Threshold1,*string,Account,1001;1002,2014-07-29T15:00:00Z,true,1s,true,10,THRESH1;THRESH2,true
1 #Tenant[0] Id[1] FilterType[2] FilterFieldName[3] FilterFieldValues[4] ActivationInterval[5] Recurrent[6] MinSleep[7] Blocker[8] Weight[9] ActionIDs[10] Async[11]
2 cgrates.org Threshold1 *string Account 1001;1002 2014-07-29T15:00:00Z true 1s true 10 THRESH1;THRESH2 true

View File

@@ -1,7 +1,7 @@
#Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5]
cgrates.org,FLTR_1,*string,Account,1001;1002
cgrates.org,FLTR_1,*string_prefix,Destination,10;20
cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002)
cgrates.org,FLTR_ACNT_dan,*string,Account,dan
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL
cgrates.org,FLTR_1,*string,Account,1001;1002,2014-07-29T15:00:00Z
cgrates.org,FLTR_1,*string_prefix,Destination,10;20,2014-07-29T15:00:00Z
cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),
cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL,2014-07-29T15:00:00Z
1 #Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5] #Tenant[0] ID[1] FilterType[2] FilterFieldName[3] FilterFieldValues[4] ActivationInterval[5]
2 cgrates.org,FLTR_1,*string,Account,1001;1002 cgrates.org FLTR_1 *string Account 1001;1002 2014-07-29T15:00:00Z
3 cgrates.org,FLTR_1,*string_prefix,Destination,10;20 cgrates.org FLTR_1 *string_prefix Destination 10;20 2014-07-29T15:00:00Z
4 cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002) cgrates.org FLTR_1 *rsr_fields Subject(~^1.*1$);Destination(1002)
5 cgrates.org,FLTR_ACNT_dan,*string,Account,dan cgrates.org FLTR_ACNT_dan *string Account dan 2014-07-29T15:00:00Z
6 cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE cgrates.org FLTR_DST_DE *destinations Destination DST_DE 2014-07-29T15:00:00Z
7 cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL cgrates.org FLTR_DST_NL *destinations Destination DST_NL 2014-07-29T15:00:00Z

View File

@@ -78,3 +78,37 @@ func (dm *DataManager) RemStatQueue(tenant, id string, transactionID string) (er
cache.RemKey(utils.StatQueuePrefix+utils.ConcatenatedKey(tenant, id), cacheCommit(transactionID), transactionID)
return
}
func (dm *DataManager) GetFilter(tenant, id string, skipCache bool, transactionID string) (fltr *Filter, err error) {
key := utils.FilterPrefix + utils.ConcatenatedKey(tenant, id)
if !skipCache {
if x, ok := cache.Get(key); ok {
if x == nil {
return nil, utils.ErrNotFound
}
return x.(*Filter), nil
}
}
fltr, err = dm.dataDB.GetFilterDrv(tenant, id)
if err != nil {
if err == utils.ErrNotFound {
cache.Set(key, nil, cacheCommit(transactionID), transactionID)
}
return nil, err
}
cache.Set(key, fltr, cacheCommit(transactionID), transactionID)
return
}
func (dm *DataManager) SetFilter(fltr *Filter) (err error) {
return dm.DataDB().SetFilterDrv(fltr)
}
func (dm *DataManager) RemoveFilter(tenant, id, transactionID string) (err error) {
if err = dm.DataDB().RemoveFilterDrv(tenant, id); err != nil {
return
}
cache.RemKey(utils.FilterPrefix+utils.ConcatenatedKey(tenant, id),
cacheCommit(transactionID), transactionID)
return
}

View File

@@ -1,17 +1,14 @@
/*
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/>
*/
@@ -29,13 +26,13 @@ func TestReqFilterPassString(t *testing.T) {
cd := &CallDescriptor{Direction: "*out", Category: "call", Tenant: "cgrates.org", Subject: "dan", Destination: "+4986517174963",
TimeStart: time.Date(2013, time.October, 7, 14, 50, 0, 0, time.UTC), TimeEnd: time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC),
DurationIndex: 132 * time.Second, ExtraFields: map[string]string{"navigation": "off"}}
rf := &Filter{Type: MetaString, FieldName: "Category", Values: []string{"call"}}
rf := &RequestFilter{Type: MetaString, FieldName: "Category", Values: []string{"call"}}
if passes, err := rf.passString(cd, ""); err != nil {
t.Error(err)
} else if !passes {
t.Error("Not passes filter")
}
rf = &Filter{Type: MetaString, FieldName: "Category", Values: []string{"cal"}}
rf = &RequestFilter{Type: MetaString, FieldName: "Category", Values: []string{"cal"}}
if passes, err := rf.passString(cd, ""); err != nil {
t.Error(err)
} else if passes {
@@ -47,37 +44,37 @@ func TestReqFilterPassStringPrefix(t *testing.T) {
cd := &CallDescriptor{Direction: "*out", Category: "call", Tenant: "cgrates.org", Subject: "dan", Destination: "+4986517174963",
TimeStart: time.Date(2013, time.October, 7, 14, 50, 0, 0, time.UTC), TimeEnd: time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC),
DurationIndex: 132 * time.Second, ExtraFields: map[string]string{"navigation": "off"}}
rf := &Filter{Type: MetaStringPrefix, FieldName: "Category", Values: []string{"call"}}
rf := &RequestFilter{Type: MetaStringPrefix, FieldName: "Category", Values: []string{"call"}}
if passes, err := rf.passStringPrefix(cd, ""); err != nil {
t.Error(err)
} else if !passes {
t.Error("Not passes filter")
}
rf = &Filter{Type: MetaStringPrefix, FieldName: "Category", Values: []string{"premium"}}
rf = &RequestFilter{Type: MetaStringPrefix, FieldName: "Category", Values: []string{"premium"}}
if passes, err := rf.passStringPrefix(cd, ""); err != nil {
t.Error(err)
} else if passes {
t.Error("Passes filter")
}
rf = &Filter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+49"}}
rf = &RequestFilter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+49"}}
if passes, err := rf.passStringPrefix(cd, ""); err != nil {
t.Error(err)
} else if !passes {
t.Error("Not passes filter")
}
rf = &Filter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+499"}}
rf = &RequestFilter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+499"}}
if passes, err := rf.passStringPrefix(cd, ""); err != nil {
t.Error(err)
} else if passes {
t.Error("Passes filter")
}
rf = &Filter{Type: MetaStringPrefix, FieldName: "navigation", Values: []string{"off"}}
rf = &RequestFilter{Type: MetaStringPrefix, FieldName: "navigation", Values: []string{"off"}}
if passes, err := rf.passStringPrefix(cd, "ExtraFields"); err != nil {
t.Error(err)
} else if !passes {
t.Error("Not passes filter")
}
rf = &Filter{Type: MetaStringPrefix, FieldName: "nonexisting", Values: []string{"off"}}
rf = &RequestFilter{Type: MetaStringPrefix, FieldName: "nonexisting", Values: []string{"off"}}
if passing, err := rf.passStringPrefix(cd, "ExtraFields"); err != nil {
t.Error(err)
} else if passing {
@@ -89,7 +86,7 @@ func TestReqFilterPassRSRFields(t *testing.T) {
cd := &CallDescriptor{Direction: "*out", Category: "call", Tenant: "cgrates.org", Subject: "dan", Destination: "+4986517174963",
TimeStart: time.Date(2013, time.October, 7, 14, 50, 0, 0, time.UTC), TimeEnd: time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC),
DurationIndex: 132 * time.Second, ExtraFields: map[string]string{"navigation": "off"}}
rf, err := NewFilter(MetaRSRFields, "", []string{"Tenant(~^cgr.*\\.org$)"})
rf, err := NewRequestFilter(MetaRSRFields, "", []string{"Tenant(~^cgr.*\\.org$)"})
if err != nil {
t.Error(err)
}
@@ -98,7 +95,7 @@ func TestReqFilterPassRSRFields(t *testing.T) {
} else if !passes {
t.Error("Not passing")
}
rf, err = NewFilter(MetaRSRFields, "", []string{"navigation(on)"})
rf, err = NewRequestFilter(MetaRSRFields, "", []string{"navigation(on)"})
if err != nil {
t.Error(err)
}
@@ -107,7 +104,7 @@ func TestReqFilterPassRSRFields(t *testing.T) {
} else if passes {
t.Error("Passing")
}
rf, err = NewFilter(MetaRSRFields, "", []string{"navigation(off)"})
rf, err = NewRequestFilter(MetaRSRFields, "", []string{"navigation(off)"})
if err != nil {
t.Error(err)
}
@@ -123,7 +120,7 @@ func TestReqFilterPassDestinations(t *testing.T) {
cd := &CallDescriptor{Direction: "*out", Category: "call", Tenant: "cgrates.org", Subject: "dan", Destination: "+4986517174963",
TimeStart: time.Date(2013, time.October, 7, 14, 50, 0, 0, time.UTC), TimeEnd: time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC),
DurationIndex: 132 * time.Second, ExtraFields: map[string]string{"navigation": "off"}}
rf, err := NewFilter(MetaDestinations, "Destination", []string{"DE"})
rf, err := NewRequestFilter(MetaDestinations, "Destination", []string{"DE"})
if err != nil {
t.Error(err)
}
@@ -132,7 +129,7 @@ func TestReqFilterPassDestinations(t *testing.T) {
} else if !passes {
t.Error("Not passing")
}
rf, err = NewFilter(MetaDestinations, "Destination", []string{"RO"})
rf, err = NewRequestFilter(MetaDestinations, "Destination", []string{"RO"})
if err != nil {
t.Error(err)
}

View File

@@ -50,7 +50,7 @@ func (rfi *ReqFilterIndexer) ChangedKeys() utils.StringMap {
}
// IndexFilters parses reqFltrs, adding itemID in the indexes and marks the changed keys in chngdIndxKeys
func (rfi *ReqFilterIndexer) IndexFilters(itemID string, reqFltrs []*Filter) {
func (rfi *ReqFilterIndexer) IndexFilters(itemID string, reqFltrs []*RequestFilter) {
var hasMetaString bool
for _, fltr := range reqFltrs {
if fltr.Type != MetaString {

View File

@@ -1,17 +1,14 @@
/*
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/>
*/
@@ -40,7 +37,7 @@ const (
MetaMaxCapPrefix = "*max_"
)
func NewFilter(rfType, fieldName string, vals []string) (*Filter, error) {
func NewRequestFilter(rfType, fieldName string, vals []string) (*RequestFilter, error) {
if !utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaRSRFields, MetaStatS, MetaDestinations}, rfType) {
return nil, fmt.Errorf("Unsupported filter Type: %s", rfType)
}
@@ -50,7 +47,7 @@ func NewFilter(rfType, fieldName string, vals []string) (*Filter, error) {
if len(vals) == 0 && utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaRSRFields, MetaDestinations, MetaDestinations}, rfType) {
return nil, fmt.Errorf("Values is mandatory for Type: %s", rfType)
}
rf := &Filter{Type: rfType, FieldName: fieldName, Values: vals}
rf := &RequestFilter{Type: rfType, FieldName: fieldName, Values: vals}
if err := rf.CompileValues(); err != nil {
return nil, err
}
@@ -63,16 +60,22 @@ type RFStatSThreshold struct {
ThresholdValue float64
}
// Filter filters requests coming into various places
// RequestFilter filters requests coming into various places
// Pass rule: default negative, one mathing rule should pass the filter
type RequestFilter struct {
Type string // Filter type (*string, *timing, *rsr_filters, *cdr_stats)
FieldName string // Name of the field providing us the Values to check (used in case of some )
Values []string // Filter definition
ActivationInterval *utils.ActivationInterval
rsrFields utils.RSRFields // Cache here the RSRFilter Values
statSThresholds []*RFStatSThreshold // Cached compiled RFStatsThreshold out of Values
}
type Filter struct {
Tenant string
ID string
Type string // Filter type (*string, *timing, *rsr_filters, *cdr_stats)
FieldName string // Name of the field providing us the Values to check (used in case of some )
Values []string // Filter definition
rsrFields utils.RSRFields // Cache here the RSRFilter Values
statSThresholds []*RFStatSThreshold // Cached compiled RFStatsThreshold out of Values
Tenant string
ID string
RequestFilters []*RequestFilter
ActivationInterval *utils.ActivationInterval
}
func (flt *Filter) TenantID() string {
@@ -80,7 +83,7 @@ func (flt *Filter) TenantID() string {
}
// Separate method to compile RSR fields
func (rf *Filter) CompileValues() (err error) {
func (rf *RequestFilter) CompileValues() (err error) {
if rf.Type == MetaRSRFields {
if rf.rsrFields, err = utils.ParseRSRFieldsFromSlice(rf.Values); err != nil {
return
@@ -110,7 +113,7 @@ func (rf *Filter) CompileValues() (err error) {
}
// Pass is the method which should be used from outside.
func (fltr *Filter) Pass(req interface{}, extraFieldsLabel string, rpcClnt rpcclient.RpcClientConnection) (bool, error) {
func (fltr *RequestFilter) Pass(req interface{}, extraFieldsLabel string, rpcClnt rpcclient.RpcClientConnection) (bool, error) {
switch fltr.Type {
case MetaString:
return fltr.passString(req, extraFieldsLabel)
@@ -129,7 +132,7 @@ func (fltr *Filter) Pass(req interface{}, extraFieldsLabel string, rpcClnt rpccl
}
}
func (fltr *Filter) passString(req interface{}, extraFieldsLabel string) (bool, error) {
func (fltr *RequestFilter) passString(req interface{}, extraFieldsLabel string) (bool, error) {
strVal, err := utils.ReflectFieldAsString(req, fltr.FieldName, extraFieldsLabel)
if err != nil {
if err == utils.ErrNotFound {
@@ -145,7 +148,7 @@ func (fltr *Filter) passString(req interface{}, extraFieldsLabel string) (bool,
return false, nil
}
func (fltr *Filter) passStringPrefix(req interface{}, extraFieldsLabel string) (bool, error) {
func (fltr *RequestFilter) passStringPrefix(req interface{}, extraFieldsLabel string) (bool, error) {
strVal, err := utils.ReflectFieldAsString(req, fltr.FieldName, extraFieldsLabel)
if err != nil {
if err == utils.ErrNotFound {
@@ -162,11 +165,11 @@ func (fltr *Filter) passStringPrefix(req interface{}, extraFieldsLabel string) (
}
// ToDo when Timings will be available in DataDb
func (fltr *Filter) passTimings(req interface{}, extraFieldsLabel string) (bool, error) {
func (fltr *RequestFilter) passTimings(req interface{}, extraFieldsLabel string) (bool, error) {
return false, utils.ErrNotImplemented
}
func (fltr *Filter) passDestinations(req interface{}, extraFieldsLabel string) (bool, error) {
func (fltr *RequestFilter) passDestinations(req interface{}, extraFieldsLabel string) (bool, error) {
dst, err := utils.ReflectFieldAsString(req, fltr.FieldName, extraFieldsLabel)
if err != nil {
if err == utils.ErrNotFound {
@@ -188,7 +191,7 @@ func (fltr *Filter) passDestinations(req interface{}, extraFieldsLabel string) (
return false, nil
}
func (fltr *Filter) passRSRFields(req interface{}, extraFieldsLabel string) (bool, error) {
func (fltr *RequestFilter) passRSRFields(req interface{}, extraFieldsLabel string) (bool, error) {
for _, rsrFld := range fltr.rsrFields {
if strVal, err := utils.ReflectFieldAsString(req, rsrFld.Id, extraFieldsLabel); err != nil {
if err == utils.ErrNotFound {
@@ -202,7 +205,7 @@ func (fltr *Filter) passRSRFields(req interface{}, extraFieldsLabel string) (boo
return false, nil
}
func (fltr *Filter) passStatS(req interface{}, extraFieldsLabel string, stats rpcclient.RpcClientConnection) (bool, error) {
func (fltr *RequestFilter) passStatS(req interface{}, extraFieldsLabel string, stats rpcclient.RpcClientConnection) (bool, error) {
if stats == nil || reflect.ValueOf(stats).IsNil() {
return false, errors.New("Missing StatS information")
}

View File

@@ -31,7 +31,7 @@ import (
type StatQueueProfile struct {
Tenant string
ID string // QueueID
Filters []*Filter
Filters []*RequestFilter
ActivationInterval *utils.ActivationInterval // Activation interval
QueueLength int
TTL time.Duration

View File

@@ -18,13 +18,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"github.com/cgrates/cgrates/cache"
"github.com/cgrates/cgrates/utils"
"log"
"reflect"
"testing"
"time"
"github.com/cgrates/cgrates/cache"
"github.com/cgrates/cgrates/utils"
)
var (
@@ -278,17 +277,17 @@ cgrates.org,Stats1,*string,Account,1001;1002,2014-07-29T15:00:00Z,100,1s,*asr;*a
`
thresholds = `
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],Recurrent[6],MinSleep[7],Blocker[8],Weight[9],ActionIDs[10]
cgrates.org,Threshold1,*string,Account,1001;1002,2014-07-29T15:00:00Z,true,1s,true,10,THRESH1;THRESH2
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],Recurrent[6],MinSleep[7],Blocker[8],Weight[9],ActionIDs[10],Async[11]
cgrates.org,Threshold1,*string,Account,1001;1002,2014-07-29T15:00:00Z,true,1s,true,10,THRESH1;THRESH2,true
`
filters = `
#Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4]
cgrates.org,FLTR_1,*string,Account,1001;1002
cgrates.org,FLTR_1,*string_prefix,Destination,10;20
cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002)
cgrates.org,FLTR_ACNT_dan,*string,Account,dan
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL
#Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5]
cgrates.org,FLTR_1,*string,Account,1001;1002,2014-07-29T15:00:00Z
cgrates.org,FLTR_1,*string_prefix,Destination,10;20,2014-07-29T15:00:00Z
cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),
cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL,2014-07-29T15:00:00Z
`
)
@@ -356,6 +355,9 @@ func init() {
if err := csvr.LoadThresholds(); err != nil {
log.Print("error in LoadThresholds:", err)
}
if err := csvr.LoadFilter(); err != nil {
log.Print("error in LoadFilter:", err)
}
csvr.WriteToDatabase(false, false, false)
cache.Flush()
dm.DataDB().LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
@@ -1441,12 +1443,11 @@ func TestLoadResourceProfiles(t *testing.T) {
t.Errorf("Failed to load resourceProfiles: %s", utils.ToIJSON(csvr.resProfiles))
} else if !reflect.DeepEqual(eResProfiles["cgrates.org"]["ResGroup22"], csvr.resProfiles["cgrates.org"]["ResGroup22"]) {
t.Errorf("Expecting: %+v, received: %+v", eResProfiles["cgrates.org"]["ResGroup22"], csvr.resProfiles["cgrates.org"]["ResGroup22"])
}
}
func TestLoadStats(t *testing.T) {
func TestLoadStatProfiles(t *testing.T) {
eStats := map[string]map[string]*utils.TPStats{
"cgrates.org": map[string]*utils.TPStats{
"Stats1": &utils.TPStats{
@@ -1479,7 +1480,7 @@ func TestLoadStats(t *testing.T) {
}
}
func TestLoadThresholds(t *testing.T) {
func TestLoadThresholdProfiles(t *testing.T) {
eThresholds := map[string]map[string]*utils.TPThreshold{
"cgrates.org": map[string]*utils.TPThreshold{
"Threshold1": &utils.TPThreshold{
@@ -1497,6 +1498,7 @@ func TestLoadThresholds(t *testing.T) {
Blocker: true,
Weight: 10,
ActionIDs: []string{"THRESH1", "THRESH2"},
Async: true,
},
},
}
@@ -1506,3 +1508,156 @@ func TestLoadThresholds(t *testing.T) {
t.Errorf("Expecting: %+v, received: %+v", eThresholds["cgrates.org"]["Threshold1"], csvr.thProfiles["cgrates.org"]["Threshold1"])
}
}
func TestLoadFilterProfiles(t *testing.T) {
eFilters := map[string]map[string]*utils.TPFilter{
"cgrates.org": map[string]*utils.TPFilter{
"FLTR_1": &utils.TPFilter{
TPid: testTPID,
Tenant: "cgrates.org",
ID: "FLTR_1",
Filters: []*utils.TPRequestFilter{
&utils.TPRequestFilter{
FieldName: "Account",
Type: "*string",
Values: []string{"1001", "1002"},
},
&utils.TPRequestFilter{
FieldName: "Destination",
Type: "*string_prefix",
Values: []string{"10", "20"},
},
&utils.TPRequestFilter{
FieldName: "",
Type: "*rsr_fields",
Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
},
},
ActivationInterval: &utils.TPActivationInterval{
ActivationTime: "2014-07-29T15:00:00Z",
},
},
"FLTR_ACNT_dan": &utils.TPFilter{
TPid: testTPID,
Tenant: "cgrates.org",
ID: "FLTR_ACNT_dan",
Filters: []*utils.TPRequestFilter{
&utils.TPRequestFilter{
FieldName: "Account",
Type: "*string",
Values: []string{"dan"},
},
},
ActivationInterval: &utils.TPActivationInterval{
ActivationTime: "2014-07-29T15:00:00Z",
},
},
"FLTR_DST_DE": &utils.TPFilter{
TPid: testTPID,
Tenant: "cgrates.org",
ID: "FLTR_DST_DE",
Filters: []*utils.TPRequestFilter{
&utils.TPRequestFilter{
FieldName: "Destination",
Type: "*destinations",
Values: []string{"DST_DE"},
},
},
ActivationInterval: &utils.TPActivationInterval{
ActivationTime: "2014-07-29T15:00:00Z",
},
},
"FLTR_DST_NL": &utils.TPFilter{
TPid: testTPID,
Tenant: "cgrates.org",
ID: "FLTR_DST_NL",
Filters: []*utils.TPRequestFilter{
&utils.TPRequestFilter{
FieldName: "Destination",
Type: "*destinations",
Values: []string{"DST_NL"},
},
},
ActivationInterval: &utils.TPActivationInterval{
ActivationTime: "2014-07-29T15:00:00Z",
},
},
},
}
if len(csvr.flProfiles["cgrates.org"]) != len(eFilters["cgrates.org"]) {
t.Errorf("Failed to load FilterProfiles: %s", utils.ToIJSON(csvr.flProfiles))
} else if !reflect.DeepEqual(eFilters["cgrates.org"]["FLTR_1"], csvr.flProfiles["cgrates.org"]["FLTR_1"]) {
t.Errorf("Expecting: %+v, received: %+v", eFilters["cgrates.org"]["FLTR_1"], csvr.flProfiles["cgrates.org"]["FLTR_1"])
}
}
func TestLoadResource(t *testing.T) {
eResources := []*utils.TenantID{
&utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup21",
},
&utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup22",
},
}
if len(csvr.resources) != len(eResources) {
t.Errorf("Failed to load resources: %s", utils.ToIJSON(csvr.resources))
}
}
func TestLoadstatQueues(t *testing.T) {
eStatQueues := []*utils.TenantID{
&utils.TenantID{
Tenant: "cgrates.org",
ID: "Stats1",
},
}
if len(csvr.statQueues) != len(eStatQueues) {
t.Errorf("Failed to load statQueues: %s", utils.ToIJSON(csvr.statQueues))
} else if !reflect.DeepEqual(eStatQueues, csvr.statQueues) {
t.Errorf("Expecting: %+v, received: %+v", eStatQueues, csvr.statQueues)
}
}
func TestLoadThresholds(t *testing.T) {
eThresholds := []*utils.TenantID{
&utils.TenantID{
Tenant: "cgrates.org",
ID: "Threshold1",
},
}
if len(csvr.thresholds) != len(eThresholds) {
t.Errorf("Failed to load thresholds: %s", utils.ToIJSON(csvr.thresholds))
} else if !reflect.DeepEqual(eThresholds, csvr.thresholds) {
t.Errorf("Expecting: %+v, received: %+v", eThresholds, csvr.thresholds)
}
}
func TestLoadFilters(t *testing.T) {
eFilters := []*utils.TenantID{
&utils.TenantID{
Tenant: "cgrates.org",
ID: "FLTR_1",
},
&utils.TenantID{
Tenant: "cgrates.org",
ID: "FLTR_ACNT_dan",
},
&utils.TenantID{
Tenant: "cgrates.org",
ID: "FLTR_DST_DE",
},
&utils.TenantID{
Tenant: "cgrates.org",
ID: "FLTR_DST_NL",
},
}
if len(csvr.filters) != len(eFilters) {
t.Errorf("Failed to load filters: %s", utils.ToIJSON(csvr.filters))
}
}

View File

@@ -1934,7 +1934,7 @@ func APItoResource(tpRL *utils.TPResource, timezone string) (rp *ResourceProfile
Weight: tpRL.Weight,
Blocker: tpRL.Blocker,
Stored: tpRL.Stored,
Filters: make([]*Filter, len(tpRL.Filters)),
Filters: make([]*RequestFilter, len(tpRL.Filters)),
}
if tpRL.UsageTTL != "" {
if rp.UsageTTL, err = utils.ParseDurationWithSecs(tpRL.UsageTTL); err != nil {
@@ -1942,7 +1942,7 @@ func APItoResource(tpRL *utils.TPResource, timezone string) (rp *ResourceProfile
}
}
for i, f := range tpRL.Filters {
rf := &Filter{Type: f.Type, FieldName: f.FieldName, Values: f.Values}
rf := &RequestFilter{Type: f.Type, FieldName: f.FieldName, Values: f.Values}
if err := rf.CompileValues(); err != nil {
return nil, err
}
@@ -2095,7 +2095,7 @@ func APItoStats(tpST *utils.TPStats, timezone string) (st *StatQueueProfile, err
Blocker: tpST.Blocker,
Stored: tpST.Stored,
MinItems: tpST.MinItems,
Filters: make([]*Filter, len(tpST.Filters)),
Filters: make([]*RequestFilter, len(tpST.Filters)),
}
if tpST.TTL != "" {
if st.TTL, err = utils.ParseDurationWithSecs(tpST.TTL); err != nil {
@@ -2110,7 +2110,7 @@ func APItoStats(tpST *utils.TPStats, timezone string) (st *StatQueueProfile, err
}
for i, f := range tpST.Filters {
rf := &Filter{Type: f.Type, FieldName: f.FieldName, Values: f.Values}
rf := &RequestFilter{Type: f.Type, FieldName: f.FieldName, Values: f.Values}
if err := rf.CompileValues(); err != nil {
return nil, err
}
@@ -2138,6 +2138,7 @@ func (tps TpThresholdS) AsTPThreshold() (result []*utils.TPThreshold) {
Blocker: tp.Blocker,
Recurrent: tp.Recurrent,
MinSleep: tp.MinSleep,
Async: tp.Async,
}
}
if tp.ActionIDs != "" {
@@ -2188,6 +2189,7 @@ func APItoModelTPThreshold(th *utils.TPThreshold) (mdls TpThresholdS) {
mdl.Weight = th.Weight
mdl.Recurrent = th.Recurrent
mdl.MinSleep = th.MinSleep
mdl.Async = th.Async
if th.ActivationInterval != nil {
if th.ActivationInterval.ActivationTime != "" {
mdl.ActivationInterval = th.ActivationInterval.ActivationTime
@@ -2209,10 +2211,9 @@ func APItoModelTPThreshold(th *utils.TPThreshold) (mdls TpThresholdS) {
mdl.FilterFieldName = fltr.FieldName
for i, val := range fltr.Values {
if i != 0 {
mdl.FilterFieldValues = mdl.FilterFieldValues + utils.INFIELD_SEP + val
} else {
mdl.FilterFieldValues = val
mdl.FilterFieldValues += utils.INFIELD_SEP
}
mdl.FilterFieldValues += val
}
mdls = append(mdls, mdl)
}
@@ -2226,7 +2227,8 @@ func APItoThresholdProfile(tpTH *utils.TPThreshold, timezone string) (th *Thresh
Recurrent: tpTH.Recurrent,
Weight: tpTH.Weight,
Blocker: tpTH.Blocker,
Filters: make([]*Filter, len(tpTH.Filters)),
Async: tpTH.Async,
Filters: make([]*RequestFilter, len(tpTH.Filters)),
}
if tpTH.MinSleep != "" {
if th.MinSleep, err = utils.ParseDurationWithSecs(tpTH.MinSleep); err != nil {
@@ -2238,7 +2240,7 @@ func APItoThresholdProfile(tpTH *utils.TPThreshold, timezone string) (th *Thresh
}
for i, f := range tpTH.Filters {
rf := &Filter{Type: f.Type, FieldName: f.FieldName, Values: f.Values}
rf := &RequestFilter{Type: f.Type, FieldName: f.FieldName, Values: f.Values}
if err := rf.CompileValues(); err != nil {
return nil, err
}
@@ -2260,15 +2262,26 @@ func (tps TpFilterS) AsTPFilter() (result []*utils.TPFilter) {
th, found := mst[tp.ID]
if !found {
th = &utils.TPFilter{
TPid: tp.Tpid,
Tenant: tp.Tenant,
ID: tp.ID,
FilterType: tp.Type,
FilterFieldName: tp.Name,
TPid: tp.Tpid,
Tenant: tp.Tenant,
ID: tp.ID,
}
}
if tp.Values != "" {
th.FilterFielValues = append(th.FilterFielValues, strings.Split(tp.Values, utils.INFIELD_SEP)...)
if len(tp.ActivationInterval) != 0 {
th.ActivationInterval = new(utils.TPActivationInterval)
aiSplt := strings.Split(tp.ActivationInterval, utils.INFIELD_SEP)
if len(aiSplt) == 2 {
th.ActivationInterval.ActivationTime = aiSplt[0]
th.ActivationInterval.ExpiryTime = aiSplt[1]
} else if len(aiSplt) == 1 {
th.ActivationInterval.ActivationTime = aiSplt[0]
}
}
if tp.FilterType != "" {
th.Filters = append(th.Filters, &utils.TPRequestFilter{
Type: tp.FilterType,
FieldName: tp.FilterFieldName,
Values: strings.Split(tp.FilterFieldValues, utils.INFIELD_SEP)})
}
mst[tp.ID] = th
}
@@ -2282,32 +2295,54 @@ func (tps TpFilterS) AsTPFilter() (result []*utils.TPFilter) {
}
func APItoModelTPFilter(th *utils.TPFilter) (mdls TpFilterS) {
mdl := &TpFilter{
Tpid: th.TPid,
Tenant: th.Tenant,
ID: th.ID,
Name: th.FilterFieldName,
Type: th.FilterType,
if len(th.Filters) == 0 {
return
}
for i, val := range th.FilterFielValues {
if i != 0 {
mdl.Values += utils.INFIELD_SEP
for _, fltr := range th.Filters {
mdl := &TpFilter{
Tpid: th.TPid,
Tenant: th.Tenant,
ID: th.ID,
}
mdl.Values += val
mdl.FilterType = fltr.Type
mdl.FilterFieldName = fltr.FieldName
if th.ActivationInterval != nil {
if th.ActivationInterval.ActivationTime != "" {
mdl.ActivationInterval = th.ActivationInterval.ActivationTime
}
if th.ActivationInterval.ExpiryTime != "" {
mdl.ActivationInterval += utils.INFIELD_SEP + th.ActivationInterval.ExpiryTime
}
}
for i, val := range fltr.Values {
if i != 0 {
mdl.FilterFieldValues += utils.INFIELD_SEP
}
mdl.FilterFieldValues += val
}
mdls = append(mdls, mdl)
}
mdls = append(mdls, mdl)
return
}
func APItoFilter(tpTH *utils.TPFilter) (th *Filter, err error) {
func APItoFilter(tpTH *utils.TPFilter, timezone string) (th *Filter, err error) {
th = &Filter{
Tenant: tpTH.Tenant,
ID: tpTH.ID,
FieldName: tpTH.FilterFieldName,
Type: tpTH.FilterType,
Tenant: tpTH.Tenant,
ID: tpTH.ID,
RequestFilters: make([]*RequestFilter, len(tpTH.Filters)),
}
for _, ati := range tpTH.FilterFielValues {
th.Values = append(th.Values, ati)
for i, f := range tpTH.Filters {
rf := &RequestFilter{Type: f.Type, FieldName: f.FieldName, Values: f.Values}
if err := rf.CompileValues(); err != nil {
return nil, err
}
th.RequestFilters[i] = rf
}
if tpTH.ActivationInterval != nil {
if th.ActivationInterval, err = tpTH.ActivationInterval.AsActivationInterval(timezone); err != nil {
return nil, err
}
}
return th, nil
}

View File

@@ -818,18 +818,18 @@ func TestAPItoResource(t *testing.T) {
Stored: tpRL.Stored,
Blocker: tpRL.Blocker,
Weight: tpRL.Weight,
Filters: make([]*Filter, len(tpRL.Filters))}
eRL.Filters[0] = &Filter{Type: MetaString,
Filters: make([]*RequestFilter, len(tpRL.Filters))}
eRL.Filters[0] = &RequestFilter{Type: MetaString,
FieldName: "Account", Values: []string{"1001", "1002"}}
eRL.Filters[1] = &Filter{Type: MetaStringPrefix,
eRL.Filters[1] = &RequestFilter{Type: MetaStringPrefix,
FieldName: "Destination", Values: []string{"10", "20"}}
eRL.Filters[2] = &Filter{Type: MetaStatS,
eRL.Filters[2] = &RequestFilter{Type: MetaStatS,
Values: []string{"CDRST1:*min_asr:34", "CDRST_1001:*min_asr:20"},
statSThresholds: []*RFStatSThreshold{
&RFStatSThreshold{QueueID: "CDRST1", ThresholdType: "*min_asr", ThresholdValue: 34},
&RFStatSThreshold{QueueID: "CDRST_1001", ThresholdType: "*min_asr", ThresholdValue: 20},
}}
eRL.Filters[3] = &Filter{Type: MetaRSRFields, Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
eRL.Filters[3] = &RequestFilter{Type: MetaRSRFields, Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
}
at, _ := utils.ParseTimeDetectLayout("2014-07-29T15:00:00Z", "UTC")
@@ -913,7 +913,7 @@ func TestAPItoTPStats(t *testing.T) {
QueueLength: tps.QueueLength,
Metrics: []string{"*asr", "*acd", "*acc"},
Thresholds: []string{"THRESH1", "THRESH2"},
Filters: make([]*Filter, len(tps.Filters)),
Filters: make([]*RequestFilter, len(tps.Filters)),
Stored: tps.Stored,
Blocker: tps.Blocker,
Weight: 20.0,
@@ -923,7 +923,7 @@ func TestAPItoTPStats(t *testing.T) {
t.Errorf("Got error: %+v", err)
}
eTPs.Filters[0] = &Filter{Type: MetaString,
eTPs.Filters[0] = &RequestFilter{Type: MetaString,
FieldName: "Account", Values: []string{"1001", "1002"}}
at, _ := utils.ParseTimeDetectLayout("2014-07-29T15:00:00Z", "UTC")
eTPs.ActivationInterval = &utils.ActivationInterval{ActivationTime: at}
@@ -995,7 +995,7 @@ func TestAPItoTPThreshold(t *testing.T) {
eTPs := &ThresholdProfile{
ID: tps.ID,
Filters: make([]*Filter, len(tps.Filters)),
Filters: make([]*RequestFilter, len(tps.Filters)),
Recurrent: tps.Recurrent,
Blocker: tps.Blocker,
Weight: tps.Weight,
@@ -1004,7 +1004,7 @@ func TestAPItoTPThreshold(t *testing.T) {
if eTPs.MinSleep, err = utils.ParseDurationWithSecs(tps.MinSleep); err != nil {
t.Errorf("Got error: %+v", err)
}
eTPs.Filters[0] = &Filter{Type: MetaString,
eTPs.Filters[0] = &RequestFilter{Type: MetaString,
FieldName: "Account", Values: []string{"1001", "1002"}}
at, _ := utils.ParseTimeDetectLayout("2014-07-29T15:00:00Z", "UTC")
eTPs.ActivationInterval = &utils.ActivationInterval{ActivationTime: at}
@@ -1018,20 +1018,24 @@ func TestAPItoTPThreshold(t *testing.T) {
func TestTPFilterAsTPFilter(t *testing.T) {
tps := []*TpFilter{
&TpFilter{
Tpid: "TEST_TPID",
ID: "Filter1",
Type: MetaStringPrefix,
Name: "Account",
Values: "1001;1002",
Tpid: "TEST_TPID",
ID: "Filter1",
FilterType: MetaStringPrefix,
FilterFieldName: "Account",
FilterFieldValues: "1001;1002",
},
}
eTPs := []*utils.TPFilter{
&utils.TPFilter{
TPid: tps[0].Tpid,
ID: tps[0].ID,
FilterType: tps[0].Type,
FilterFieldName: tps[0].Name,
FilterFielValues: []string{"1001", "1002"},
TPid: tps[0].Tpid,
ID: tps[0].ID,
Filters: []*utils.TPRequestFilter{
&utils.TPRequestFilter{
Type: MetaStringPrefix,
FieldName: "Account",
Values: []string{"1001", "1002"},
},
},
},
}
@@ -1043,22 +1047,30 @@ func TestTPFilterAsTPFilter(t *testing.T) {
func TestAPItoTPFilter(t *testing.T) {
tps := &utils.TPFilter{
TPid: testTPID,
Tenant: "cgrates.org",
ID: "Filter1",
FilterType: "*string",
FilterFieldName: "Acount",
FilterFielValues: []string{"1001", "1002"},
TPid: testTPID,
Tenant: "cgrates.org",
ID: "Filter1",
Filters: []*utils.TPRequestFilter{
&utils.TPRequestFilter{
FieldName: "Account",
Type: "*string",
Values: []string{"1001", "1002"},
},
},
}
eTPs := &Filter{
Tenant: "cgrates.org",
ID: tps.ID,
FieldName: tps.FilterFieldName,
Type: tps.FilterType,
Values: tps.FilterFielValues,
Tenant: "cgrates.org",
ID: tps.ID,
RequestFilters: []*RequestFilter{
&RequestFilter{
FieldName: "Account",
Type: "*string",
Values: []string{"1001", "1002"},
},
},
}
if st, err := APItoFilter(tps); err != nil {
if st, err := APItoFilter(tps, "UTC"); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eTPs, st) {
t.Errorf("Expecting: %+v, received: %+v", eTPs, st)

View File

@@ -514,16 +514,18 @@ type TpThreshold struct {
Blocker bool `index:"8" re:""`
Weight float64 `index:"9" re:"\d+\.?\d*"`
ActionIDs string `index:"10" re:""`
Async bool `index:"8" re:""`
CreatedAt time.Time
}
type TpFilter struct {
PK uint `gorm:"primary_key"`
Tpid string
Tenant string `index:"0" re:""`
ID string `index:"1" re:""`
Type string `index:"2" re:"^\*[A-Za-z].*"`
Name string `index:"3" re:""`
Values string `index:"4" re:""`
CreatedAt time.Time
PK uint `gorm:"primary_key"`
Tpid string
Tenant string `index:"0" re:""`
ID string `index:"1" re:""`
FilterType string `index:"2" re:"^\*[A-Za-z].*"`
FilterFieldName string `index:"3" re:""`
FilterFieldValues string `index:"4" re:""`
ActivationInterval string `index:"5" re:""`
CreatedAt time.Time
}

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ func init() {
type ResourceProfile struct {
Tenant string
ID string // identifier of this resource
Filters []*Filter // filters for the request
Filters []*RequestFilter // filters for the request
ActivationInterval *utils.ActivationInterval // time when this resource becomes active and expires
UsageTTL time.Duration // auto-expire the usage after this duration
Limit float64 // limit value

View File

@@ -53,13 +53,13 @@ func TestRSRecordUsage1(t *testing.T) {
rPrf: &ResourceProfile{
Tenant: "cgrates.org",
ID: "RL1",
Filters: []*Filter{
&Filter{
Filters: []*RequestFilter{
&RequestFilter{
Type: MetaString,
FieldName: "Account",
Values: []string{"1001", "1002"},
},
&Filter{
&RequestFilter{
Type: MetaRSRFields,
Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
@@ -134,13 +134,13 @@ func TestRSRsort(t *testing.T) {
ID: "RL2",
rPrf: &ResourceProfile{
ID: "RL2",
Filters: []*Filter{
&Filter{
Filters: []*RequestFilter{
&RequestFilter{
Type: MetaString,
FieldName: "Account",
Values: []string{"1001", "1002"},
},
&Filter{
&RequestFilter{
Type: MetaRSRFields,
Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
@@ -249,13 +249,13 @@ func TestRSCacheSetGet(t *testing.T) {
rPrf: &ResourceProfile{
Tenant: "cgrates.org",
ID: "RL",
Filters: []*Filter{
&Filter{
Filters: []*RequestFilter{
&RequestFilter{
Type: MetaString,
FieldName: "Account",
Values: []string{"1001", "1002"},
},
&Filter{
&RequestFilter{
Type: MetaRSRFields,
Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),

View File

@@ -126,9 +126,9 @@ type DataDB interface {
GetThreshold(string, string, bool, string) (*Threshold, error)
SetThreshold(*Threshold) error
RemoveThreshold(string, string, string) error
GetFilter(string, string, bool, string) (*Filter, error)
SetFilter(*Filter) error
RemoveFilter(string, string, string) error
GetFilterDrv(string, string) (*Filter, error)
SetFilterDrv(*Filter) error
RemoveFilterDrv(string, string) error
// CacheDataFromDB loads data to cache, prefix represents the cache prefix, IDs should be nil if all available data should be loaded
CacheDataFromDB(prefix string, IDs []string, mustBeCached bool) error // ToDo: Move this to dataManager
}

View File

@@ -317,7 +317,7 @@ func (ms *MapStorage) HasData(categ, subject string) (bool, error) {
switch categ {
case utils.DESTINATION_PREFIX, utils.RATING_PLAN_PREFIX, utils.RATING_PROFILE_PREFIX,
utils.ACTION_PREFIX, utils.ACTION_PLAN_PREFIX, utils.ACCOUNT_PREFIX, utils.DERIVEDCHARGERS_PREFIX,
utils.ResourcesPrefix, utils.StatQueuePrefix, utils.ThresholdPrefix:
utils.ResourcesPrefix, utils.StatQueuePrefix, utils.ThresholdPrefix, utils.FilterPrefix:
_, exists := ms.dict[categ+subject]
return exists, nil
}
@@ -1669,32 +1669,18 @@ func (ms *MapStorage) RemoveThreshold(tenant, id string, transactionID string) (
return
}
func (ms *MapStorage) GetFilter(tenant, id string, skipCache bool, transactionID string) (r *Filter, err error) {
func (ms *MapStorage) GetFilterDrv(tenant, id string) (r *Filter, err error) {
ms.mu.RLock()
defer ms.mu.RUnlock()
key := utils.FilterPrefix + utils.ConcatenatedKey(tenant, id)
if !skipCache {
if x, ok := cache.Get(key); ok {
if x != nil {
return x.(*Filter), nil
}
return nil, utils.ErrNotFound
}
}
values, ok := ms.dict[key]
values, ok := ms.dict[utils.FilterPrefix+utils.ConcatenatedKey(tenant, id)]
if !ok {
cache.Set(key, nil, cacheCommit(transactionID), transactionID)
return nil, utils.ErrNotFound
}
err = ms.ms.Unmarshal(values, r)
if err != nil {
return nil, err
}
cache.Set(key, r, cacheCommit(transactionID), transactionID)
err = ms.ms.Unmarshal(values, &r)
return
}
func (ms *MapStorage) SetFilter(r *Filter) (err error) {
func (ms *MapStorage) SetFilterDrv(r *Filter) (err error) {
ms.mu.Lock()
defer ms.mu.Unlock()
result, err := ms.ms.Marshal(r)
@@ -1705,12 +1691,12 @@ func (ms *MapStorage) SetFilter(r *Filter) (err error) {
return
}
func (ms *MapStorage) RemoveFilter(tenant, id string, transactionID string) (err error) {
func (ms *MapStorage) RemoveFilterDrv(tenant, id string) (err error) {
ms.mu.Lock()
defer ms.mu.Unlock()
key := utils.FilterPrefix + utils.ConcatenatedKey(tenant, id)
delete(ms.dict, key)
cache.RemKey(key, cacheCommit(transactionID), transactionID)
return
}

View File

@@ -546,7 +546,7 @@ func (ms *MongoStorage) CacheDataFromDB(prfx string, ids []string, mustBeCached
_, err = ms.GetThreshold(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
case utils.FilterPrefix:
tntID := utils.NewTenantID(dataID)
_, err = ms.GetFilter(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
_, err = ms.GetFilterDrv(tntID.Tenant, tntID.ID)
}
if err != nil {
return utils.NewCGRError(utils.MONGO,
@@ -2253,44 +2253,30 @@ func (ms *MongoStorage) RemoveThreshold(tenant, id string, transactionID string)
return nil
}
func (ms *MongoStorage) GetFilter(tenant, id string, skipCache bool, transactionID string) (r *Filter, err error) {
key := utils.FilterPrefix + utils.ConcatenatedKey(tenant, id)
if !skipCache {
if x, ok := cache.Get(key); ok {
if x == nil {
return nil, utils.ErrNotFound
}
return x.(*Filter), nil
}
}
func (ms *MongoStorage) GetFilterDrv(tenant, id string) (r *Filter, err error) {
session, col := ms.conn(colFlt)
defer session.Close()
r = new(Filter)
if err = col.Find(bson.M{"tenant": tenant, "id": id}).One(r); err != nil {
if err = col.Find(bson.M{"tenant": tenant, "id": id}).One(&r); err != nil {
if err == mgo.ErrNotFound {
err = utils.ErrNotFound
cache.Set(key, nil, cacheCommit(transactionID), transactionID)
}
return nil, err
}
cache.Set(key, r, cacheCommit(transactionID), transactionID)
return
}
func (ms *MongoStorage) SetFilter(r *Filter) (err error) {
func (ms *MongoStorage) SetFilterDrv(r *Filter) (err error) {
session, col := ms.conn(colFlt)
defer session.Close()
_, err = col.Upsert(bson.M{"tenant": r.Tenant, "id": r.ID}, r)
return
}
func (ms *MongoStorage) RemoveFilter(tenant, id string, transactionID string) (err error) {
func (ms *MongoStorage) RemoveFilterDrv(tenant, id string) (err error) {
session, col := ms.conn(colFlt)
defer session.Close()
if err = col.Remove(bson.M{"tenant": tenant, "id": id}); err != nil {
return
}
cache.RemKey(utils.FilterPrefix+utils.ConcatenatedKey(tenant, id),
cacheCommit(transactionID), transactionID)
return nil
}

View File

@@ -1776,20 +1776,11 @@ func (rs *RedisStorage) RemoveThreshold(tenant, id string, transactionID string)
return
}
func (rs *RedisStorage) GetFilter(tenant, id string, skipCache bool, transactionID string) (r *Filter, err error) {
func (rs *RedisStorage) GetFilterDrv(tenant, id string) (r *Filter, err error) {
key := utils.FilterPrefix + utils.ConcatenatedKey(tenant, id)
if !skipCache {
if x, ok := cache.Get(key); ok {
if x == nil {
return nil, utils.ErrNotFound
}
return x.(*Filter), nil
}
}
var values []byte
if values, err = rs.Cmd("GET", key).Bytes(); err != nil {
if err == redis.ErrRespNil { // did not find the destination
cache.Set(key, nil, cacheCommit(transactionID), transactionID)
err = utils.ErrNotFound
}
return
@@ -1797,11 +1788,10 @@ func (rs *RedisStorage) GetFilter(tenant, id string, skipCache bool, transaction
if err = rs.ms.Unmarshal(values, &r); err != nil {
return
}
cache.Set(key, r, cacheCommit(transactionID), transactionID)
return
}
func (rs *RedisStorage) SetFilter(r *Filter) (err error) {
func (rs *RedisStorage) SetFilterDrv(r *Filter) (err error) {
result, err := rs.ms.Marshal(r)
if err != nil {
return err
@@ -1809,12 +1799,11 @@ func (rs *RedisStorage) SetFilter(r *Filter) (err error) {
return rs.Cmd("SET", utils.FilterPrefix+utils.ConcatenatedKey(r.Tenant, r.ID), result).Err
}
func (rs *RedisStorage) RemoveFilter(tenant, id string, transactionID string) (err error) {
func (rs *RedisStorage) RemoveFilterDrv(tenant, id string) (err error) {
key := utils.FilterPrefix + utils.ConcatenatedKey(tenant, id)
if err = rs.Cmd("DEL", key).Err; err != nil {
return
}
cache.RemKey(key, cacheCommit(transactionID), transactionID)
return
}

View File

@@ -35,13 +35,14 @@ import (
type ThresholdProfile struct {
Tenant string
ID string
Filters []*Filter // Filters for the request
Filters []*RequestFilter // Filters for the request
ActivationInterval *utils.ActivationInterval // Time when this limit becomes active and expires
Recurrent bool
MinSleep time.Duration
Blocker bool // blocker flag to stop processing on filters matched
Weight float64 // Weight to sort the thresholds
ActionIDs []string
Async bool
}
func (tp *ThresholdProfile) TenantID() string {

View File

@@ -153,10 +153,10 @@ func (tpr *TpReader) LoadDestinationsFiltered(tag string) (bool, error) {
for _, tpDst := range tpDests {
dst := NewDestinationFromTPDestination(tpDst)
// ToDo: Fix transactions at onlineDB level
if err = tpr.dataStorage.SetDestination(dst, transID); err != nil {
if err = tpr.dm.DataDB().SetDestination(dst, transID); err != nil {
cache.RollbackTransaction(transID)
}
if err = tpr.dataStorage.SetReverseDestination(dst, transID); err != nil {
if err = tpr.dm.DataDB().SetReverseDestination(dst, transID); err != nil {
cache.RollbackTransaction(transID)
}
}
@@ -239,7 +239,7 @@ func (tpr *TpReader) LoadDestinationRates() (err error) {
_, destinationExists = tpr.destinations[dr.DestinationId]
}
if !destinationExists && tpr.dataStorage != nil {
if destinationExists, err = tpr.dataStorage.HasData(utils.DESTINATION_PREFIX, dr.DestinationId); err != nil {
if destinationExists, err = tpr.dm.DataDB().HasData(utils.DESTINATION_PREFIX, dr.DestinationId); err != nil {
return err
}
}
@@ -308,7 +308,7 @@ func (tpr *TpReader) LoadRatingPlansFiltered(tag string) (bool, error) {
}
destsExist := len(dms) != 0
if !destsExist && tpr.dataStorage != nil {
if dbExists, err := tpr.dataStorage.HasData(utils.DESTINATION_PREFIX, drate.DestinationId); err != nil {
if dbExists, err := tpr.dm.DataDB().HasData(utils.DESTINATION_PREFIX, drate.DestinationId); err != nil {
return false, err
} else if dbExists {
destsExist = true
@@ -319,12 +319,12 @@ func (tpr *TpReader) LoadRatingPlansFiltered(tag string) (bool, error) {
return false, fmt.Errorf("could not get destination for tag %v", drate.DestinationId)
}
for _, destination := range dms {
tpr.dataStorage.SetDestination(destination, utils.NonTransactional)
tpr.dataStorage.SetReverseDestination(destination, utils.NonTransactional)
tpr.dm.DataDB().SetDestination(destination, utils.NonTransactional)
tpr.dm.DataDB().SetReverseDestination(destination, utils.NonTransactional)
}
}
}
if err := tpr.dataStorage.SetRatingPlan(ratingPlan, utils.NonTransactional); err != nil {
if err := tpr.dm.DataDB().SetRatingPlan(ratingPlan, utils.NonTransactional); err != nil {
return false, err
}
}
@@ -381,7 +381,7 @@ func (tpr *TpReader) LoadRatingProfilesFiltered(qriedRpf *utils.TPRatingProfile)
}
_, exists := tpr.ratingPlans[tpRa.RatingPlanId]
if !exists && tpr.dataStorage != nil {
if exists, err = tpr.dataStorage.HasData(utils.RATING_PLAN_PREFIX, tpRa.RatingPlanId); err != nil {
if exists, err = tpr.dm.DataDB().HasData(utils.RATING_PLAN_PREFIX, tpRa.RatingPlanId); err != nil {
return err
}
}
@@ -396,7 +396,7 @@ func (tpr *TpReader) LoadRatingProfilesFiltered(qriedRpf *utils.TPRatingProfile)
CdrStatQueueIds: strings.Split(tpRa.CdrStatQueueIds, utils.INFIELD_SEP),
})
}
if err := tpr.dataStorage.SetRatingProfile(resultRatingProfile, utils.NonTransactional); err != nil {
if err := tpr.dm.DataDB().SetRatingProfile(resultRatingProfile, utils.NonTransactional); err != nil {
return err
}
}
@@ -421,7 +421,7 @@ func (tpr *TpReader) LoadRatingProfiles() (err error) {
}
_, exists := tpr.ratingPlans[tpRa.RatingPlanId]
if !exists && tpr.dataStorage != nil { // Only query if there is a connection, eg on dry run there is none
if exists, err = tpr.dataStorage.HasData(utils.RATING_PLAN_PREFIX, tpRa.RatingPlanId); err != nil {
if exists, err = tpr.dm.DataDB().HasData(utils.RATING_PLAN_PREFIX, tpRa.RatingPlanId); err != nil {
return err
}
}
@@ -465,7 +465,7 @@ func (tpr *TpReader) LoadSharedGroupsFiltered(tag string, save bool) (err error)
}
if save {
for _, sg := range tpr.sharedGroups {
if err := tpr.dataStorage.SetSharedGroup(sg, utils.NonTransactional); err != nil {
if err := tpr.dm.DataDB().SetSharedGroup(sg, utils.NonTransactional); err != nil {
return err
}
}
@@ -495,7 +495,7 @@ func (tpr *TpReader) LoadLCRs() (err error) {
}
}
if !found && tpr.dataStorage != nil {
if keys, err := tpr.dataStorage.GetKeysForPrefix(utils.RATING_PROFILE_PREFIX + ratingProfileSearchKey); err != nil {
if keys, err := tpr.dm.DataDB().GetKeysForPrefix(utils.RATING_PROFILE_PREFIX + ratingProfileSearchKey); err != nil {
return fmt.Errorf("[LCR] error querying dataDb %s", err.Error())
} else if len(keys) != 0 {
found = true
@@ -509,7 +509,7 @@ func (tpr *TpReader) LoadLCRs() (err error) {
if rule.DestinationId != "" && rule.DestinationId != utils.ANY {
_, found := tpr.destinations[rule.DestinationId]
if !found && tpr.dataStorage != nil {
if found, err = tpr.dataStorage.HasData(utils.DESTINATION_PREFIX, rule.DestinationId); err != nil {
if found, err = tpr.dm.DataDB().HasData(utils.DESTINATION_PREFIX, rule.DestinationId); err != nil {
return fmt.Errorf("[LCR] error querying dataDb %s", err.Error())
}
}
@@ -675,7 +675,7 @@ func (tpr *TpReader) LoadActionPlans() (err error) {
_, exists := tpr.actions[at.ActionsId]
if !exists && tpr.dataStorage != nil {
if exists, err = tpr.dataStorage.HasData(utils.ACTION_PREFIX, at.ActionsId); err != nil {
if exists, err = tpr.dm.DataDB().HasData(utils.ACTION_PREFIX, at.ActionsId); err != nil {
return fmt.Errorf("[ActionPlans] Error querying actions: %v - %s", at.ActionsId, err.Error())
}
}
@@ -829,7 +829,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
if accountAction.ActionPlanId != "" {
// get old userBalanceIds
exitingAccountIds := make(utils.StringMap)
existingActionPlan, err := tpr.dataStorage.GetActionPlan(accountAction.ActionPlanId, true, utils.NonTransactional)
existingActionPlan, err := tpr.dm.DataDB().GetActionPlan(accountAction.ActionPlanId, true, utils.NonTransactional)
if err == nil && existingActionPlan != nil {
exitingAccountIds = existingActionPlan.AccountIDs
}
@@ -899,20 +899,20 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
AccountID: accID,
ActionsID: at.ActionsID,
}
if err = tpr.dataStorage.PushTask(t); err != nil {
if err = tpr.dm.DataDB().PushTask(t); err != nil {
return err
}
}
}
}
// write action plan
if err = tpr.dataStorage.SetActionPlan(accountAction.ActionPlanId, actionPlan, false, utils.NonTransactional); err != nil {
if err = tpr.dm.DataDB().SetActionPlan(accountAction.ActionPlanId, actionPlan, false, utils.NonTransactional); err != nil {
return errors.New(err.Error() + " (SetActionPlan): " + accountAction.ActionPlanId)
}
if err = tpr.dataStorage.SetAccountActionPlans(id, []string{accountAction.ActionPlanId}, false); err != nil {
if err = tpr.dm.DataDB().SetAccountActionPlans(id, []string{accountAction.ActionPlanId}, false); err != nil {
return err
}
if err = tpr.dataStorage.CacheDataFromDB(utils.AccountActionPlansPrefix, []string{id}, true); err != nil {
if err = tpr.dm.DataDB().CacheDataFromDB(utils.AccountActionPlansPrefix, []string{id}, true); err != nil {
return err
}
}
@@ -1012,7 +1012,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
actionIDs = append(actionIDs, atr.ActionsID)
}
// write action triggers
err = tpr.dataStorage.SetActionTriggers(accountAction.ActionTriggersId, actionTriggers, utils.NonTransactional)
err = tpr.dm.DataDB().SetActionTriggers(accountAction.ActionTriggersId, actionTriggers, utils.NonTransactional)
if err != nil {
return errors.New(err.Error() + " (SetActionTriggers): " + accountAction.ActionTriggersId)
}
@@ -1124,12 +1124,12 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
}
// write actions
for k, as := range facts {
err = tpr.dataStorage.SetActions(k, as, utils.NonTransactional)
err = tpr.dm.DataDB().SetActions(k, as, utils.NonTransactional)
if err != nil {
return err
}
}
ub, err := tpr.dataStorage.GetAccount(id)
ub, err := tpr.dm.DataDB().GetAccount(id)
if err != nil {
ub = &Account{
ID: id,
@@ -1138,7 +1138,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
ub.ActionTriggers = actionTriggers
// init counters
ub.InitCounters()
if err := tpr.dataStorage.SetAccount(ub); err != nil {
if err := tpr.dm.DataDB().SetAccount(ub); err != nil {
return err
}
}
@@ -1224,7 +1224,7 @@ func (tpr *TpReader) LoadDerivedChargersFiltered(filter *utils.TPDerivedChargers
}
if save {
for dcsKey, dcs := range tpr.derivedChargers {
if err := tpr.dataStorage.SetDerivedChargers(dcsKey, dcs, utils.NonTransactional); err != nil {
if err := tpr.dm.DataDB().SetDerivedChargers(dcsKey, dcs, utils.NonTransactional); err != nil {
return err
}
}
@@ -1352,7 +1352,7 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
return fmt.Errorf("could not get action triggers for cdr stats id %s: %s", cs.Id, triggerTag)
}
// write action triggers
err = tpr.dataStorage.SetActionTriggers(triggerTag, triggers, utils.NonTransactional)
err = tpr.dm.DataDB().SetActionTriggers(triggerTag, triggers, utils.NonTransactional)
if err != nil {
return errors.New(err.Error() + " (SetActionTriggers): " + triggerTag)
}
@@ -1453,13 +1453,13 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
if save {
// write actions
for k, as := range tpr.actions {
err = tpr.dataStorage.SetActions(k, as, utils.NonTransactional)
err = tpr.dm.DataDB().SetActions(k, as, utils.NonTransactional)
if err != nil {
return err
}
}
for _, stat := range tpr.cdrStats {
if err := tpr.dataStorage.SetCdrStats(stat); err != nil {
if err := tpr.dm.DataDB().SetCdrStats(stat); err != nil {
return err
}
}
@@ -1485,7 +1485,7 @@ func (tpr *TpReader) LoadUsersFiltered(filter *utils.TPUsers) (bool, error) {
for _, up := range tpUser.Profile {
user.Profile[up.AttrName] = up.AttrValue
}
tpr.dataStorage.SetUser(user)
tpr.dm.DataDB().SetUser(user)
}
return len(tpUsers) > 0, err
}
@@ -1546,8 +1546,8 @@ func (tpr *TpReader) LoadAliasesFiltered(filter *utils.TPAliases) (bool, error)
}
}
tpr.dataStorage.SetAlias(alias, utils.NonTransactional)
tpr.dataStorage.SetReverseAlias(alias, utils.NonTransactional)
tpr.dm.DataDB().SetAlias(alias, utils.NonTransactional)
tpr.dm.DataDB().SetReverseAlias(alias, utils.NonTransactional)
return len(tpAliases) > 0, err
}
@@ -1615,7 +1615,7 @@ func (tpr *TpReader) LoadResourceProfilesFiltered(tag string) error {
for tenant, mpID := range mapRsPfls {
for id := range mpID {
rTid := &utils.TenantID{tenant, id}
if has, err := tpr.dataStorage.HasData(utils.ResourcesPrefix, rTid.TenantID()); err != nil {
if has, err := tpr.dm.DataDB().HasData(utils.ResourcesPrefix, rTid.TenantID()); err != nil {
return err
} else if !has {
tpr.resources = append(tpr.resources, rTid)
@@ -1645,7 +1645,7 @@ func (tpr *TpReader) LoadStatsFiltered(tag string) error {
for tenant, mpID := range mapSTs {
for sqID := range mpID {
sqTntID := &utils.TenantID{tenant, sqID}
if has, err := tpr.dataStorage.HasData(utils.StatQueuePrefix, sqTntID.TenantID()); err != nil {
if has, err := tpr.dm.DataDB().HasData(utils.StatQueuePrefix, sqTntID.TenantID()); err != nil {
return err
} else if !has {
tpr.statQueues = append(tpr.statQueues, sqTntID)
@@ -1675,7 +1675,7 @@ func (tpr *TpReader) LoadThresholdsFiltered(tag string) error {
for tenant, mpID := range mapTHs {
for thID := range mpID {
thTntID := &utils.TenantID{Tenant: tenant, ID: thID}
if has, err := tpr.dataStorage.HasData(utils.ThresholdPrefix, thTntID.TenantID()); err != nil {
if has, err := tpr.dm.DataDB().HasData(utils.ThresholdPrefix, thTntID.TenantID()); err != nil {
return err
} else if !has {
tpr.thresholds = append(tpr.thresholds, thTntID)
@@ -1705,7 +1705,7 @@ func (tpr *TpReader) LoadFilterFiltered(tag string) error {
for tenant, mpID := range mapTHs {
for thID := range mpID {
thTntID := &utils.TenantID{Tenant: tenant, ID: thID}
if has, err := tpr.dataStorage.HasData(utils.FilterPrefix, thTntID.TenantID()); err != nil {
if has, err := tpr.dm.DataDB().HasData(utils.FilterPrefix, thTntID.TenantID()); err != nil {
return err
} else if !has {
tpr.filters = append(tpr.filters, thTntID)
@@ -1807,13 +1807,13 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
return errors.New("no database connection")
}
if flush { // ToDo
//tpr.dataStorage.Flush("")
//tpr.dm.DataDB().Flush("")
}
if verbose {
log.Print("Destinations:")
}
for _, d := range tpr.destinations {
err = tpr.dataStorage.SetDestination(d, utils.NonTransactional)
err = tpr.dm.DataDB().SetDestination(d, utils.NonTransactional)
if err != nil {
return err
}
@@ -1831,7 +1831,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Rating Plans:")
}
for _, rp := range tpr.ratingPlans {
err = tpr.dataStorage.SetRatingPlan(rp, utils.NonTransactional)
err = tpr.dm.DataDB().SetRatingPlan(rp, utils.NonTransactional)
if err != nil {
return err
}
@@ -1843,7 +1843,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Rating Profiles:")
}
for _, rp := range tpr.ratingProfiles {
err = tpr.dataStorage.SetRatingProfile(rp, utils.NonTransactional)
err = tpr.dm.DataDB().SetRatingProfile(rp, utils.NonTransactional)
if err != nil {
return err
}
@@ -1866,7 +1866,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if verbose {
log.Println("\tTask: ", t)
}
if err = tpr.dataStorage.PushTask(t); err != nil {
if err = tpr.dm.DataDB().PushTask(t); err != nil {
return err
}
}
@@ -1878,13 +1878,13 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if verbose {
log.Println("\tTask: ", t)
}
if err = tpr.dataStorage.PushTask(t); err != nil {
if err = tpr.dm.DataDB().PushTask(t); err != nil {
return err
}
}
}
}
err = tpr.dataStorage.SetActionPlan(k, ap, false, utils.NonTransactional)
err = tpr.dm.DataDB().SetActionPlan(k, ap, false, utils.NonTransactional)
if err != nil {
return err
}
@@ -1902,7 +1902,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Action Triggers:")
}
for k, atrs := range tpr.actionsTriggers {
err = tpr.dataStorage.SetActionTriggers(k, atrs, utils.NonTransactional)
err = tpr.dm.DataDB().SetActionTriggers(k, atrs, utils.NonTransactional)
if err != nil {
return err
}
@@ -1914,7 +1914,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Shared Groups:")
}
for k, sg := range tpr.sharedGroups {
err = tpr.dataStorage.SetSharedGroup(sg, utils.NonTransactional)
err = tpr.dm.DataDB().SetSharedGroup(sg, utils.NonTransactional)
if err != nil {
return err
}
@@ -1926,7 +1926,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("LCR Rules:")
}
for k, lcr := range tpr.lcrs {
err = tpr.dataStorage.SetLCR(lcr, utils.NonTransactional)
err = tpr.dm.DataDB().SetLCR(lcr, utils.NonTransactional)
if err != nil {
return err
}
@@ -1938,7 +1938,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Actions:")
}
for k, as := range tpr.actions {
err = tpr.dataStorage.SetActions(k, as, utils.NonTransactional)
err = tpr.dm.DataDB().SetActions(k, as, utils.NonTransactional)
if err != nil {
return err
}
@@ -1950,7 +1950,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Account Actions:")
}
for _, ub := range tpr.accountActions {
err = tpr.dataStorage.SetAccount(ub)
err = tpr.dm.DataDB().SetAccount(ub)
if err != nil {
return err
}
@@ -1962,7 +1962,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Derived Chargers:")
}
for key, dcs := range tpr.derivedChargers {
err = tpr.dataStorage.SetDerivedChargers(key, dcs, utils.NonTransactional)
err = tpr.dm.DataDB().SetDerivedChargers(key, dcs, utils.NonTransactional)
if err != nil {
return err
}
@@ -1974,7 +1974,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("CDR Stats Queues:")
}
for _, sq := range tpr.cdrStats {
err = tpr.dataStorage.SetCdrStats(sq)
err = tpr.dm.DataDB().SetCdrStats(sq)
if err != nil {
return err
}
@@ -1986,7 +1986,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Users:")
}
for _, u := range tpr.users {
err = tpr.dataStorage.SetUser(u)
err = tpr.dm.DataDB().SetUser(u)
if err != nil {
return err
}
@@ -1998,7 +1998,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Aliases:")
}
for _, al := range tpr.aliases {
err = tpr.dataStorage.SetAlias(al, utils.NonTransactional)
err = tpr.dm.DataDB().SetAlias(al, utils.NonTransactional)
if err != nil {
return err
}
@@ -2021,7 +2021,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if err != nil {
return err
}
if err = tpr.dataStorage.SetResourceProfile(rsp); err != nil {
if err = tpr.dm.DataDB().SetResourceProfile(rsp); err != nil {
return err
}
if verbose {
@@ -2033,7 +2033,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Resources:")
}
for _, rTid := range tpr.resources {
if err = tpr.dataStorage.SetResource(&Resource{Tenant: rTid.Tenant, ID: rTid.ID, Usages: make(map[string]*ResourceUsage)}); err != nil {
if err = tpr.dm.DataDB().SetResource(&Resource{Tenant: rTid.Tenant, ID: rTid.ID, Usages: make(map[string]*ResourceUsage)}); err != nil {
return
}
if verbose {
@@ -2049,7 +2049,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if err != nil {
return err
}
if err = tpr.dataStorage.SetStatQueueProfile(st); err != nil {
if err = tpr.dm.DataDB().SetStatQueueProfile(st); err != nil {
return err
}
if verbose {
@@ -2086,7 +2086,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if err != nil {
return err
}
if err = tpr.dataStorage.SetThresholdProfile(th); err != nil {
if err = tpr.dm.DataDB().SetThresholdProfile(th); err != nil {
return err
}
if verbose {
@@ -2098,7 +2098,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
log.Print("Thresholds:")
}
for _, thd := range tpr.thresholds {
if err = tpr.dataStorage.SetThreshold(&Threshold{Tenant: thd.Tenant, ID: thd.ID}); err != nil {
if err = tpr.dm.DataDB().SetThreshold(&Threshold{Tenant: thd.Tenant, ID: thd.ID}); err != nil {
return err
}
if verbose {
@@ -2106,15 +2106,15 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
}
}
if verbose {
log.Print("Filters:")
log.Print("FilterProfile:")
}
for _, mpID := range tpr.flProfiles {
for _, tpTH := range mpID {
th, err := APItoFilter(tpTH)
th, err := APItoFilter(tpTH, tpr.timezone)
if err != nil {
return err
}
if err = tpr.dataStorage.SetFilter(th); err != nil {
if err = tpr.dm.SetFilter(th); err != nil {
return err
}
if verbose {
@@ -2122,11 +2122,22 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
}
}
}
if verbose {
log.Print("Filters:")
}
for _, thd := range tpr.filters {
if err = tpr.dm.SetFilter(&Filter{Tenant: thd.Tenant, ID: thd.ID}); err != nil {
return err
}
if verbose {
log.Print("\t", thd.TenantID())
}
}
if verbose {
log.Print("Timings:")
}
for _, t := range tpr.timings {
if err = tpr.dataStorage.SetTiming(t, utils.NonTransactional); err != nil {
if err = tpr.dm.DataDB().SetTiming(t, utils.NonTransactional); err != nil {
return err
}
if verbose {
@@ -2138,7 +2149,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if verbose {
log.Print("Rebuilding reverse destinations")
}
if err = tpr.dataStorage.RebuildReverseForPrefix(utils.REVERSE_DESTINATION_PREFIX); err != nil {
if err = tpr.dm.DataDB().RebuildReverseForPrefix(utils.REVERSE_DESTINATION_PREFIX); err != nil {
return err
}
}
@@ -2146,7 +2157,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if verbose {
log.Print("Rebuilding account action plans")
}
if err = tpr.dataStorage.RebuildReverseForPrefix(utils.AccountActionPlansPrefix); err != nil {
if err = tpr.dm.DataDB().RebuildReverseForPrefix(utils.AccountActionPlansPrefix); err != nil {
return err
}
}
@@ -2154,7 +2165,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
if verbose {
log.Print("Rebuilding reverse aliases")
}
if err = tpr.dataStorage.RebuildReverseForPrefix(utils.REVERSE_ALIASES_PREFIX); err != nil {
if err = tpr.dm.DataDB().RebuildReverseForPrefix(utils.REVERSE_ALIASES_PREFIX); err != nil {
return err
}
}
@@ -2230,6 +2241,31 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
}
}
}
if len(tpr.flProfiles) > 0 {
if verbose {
log.Print("Indexing Filters")
}
for tenant, mpID := range tpr.flProfiles {
stIdxr, err := NewReqFilterIndexer(tpr.dm, utils.FilterIndex+tenant)
if err != nil {
return err
}
for _, tpTH := range mpID {
if th, err := APItoFilter(tpTH, tpr.timezone); err != nil {
return err
} else {
stIdxr.IndexFilters(th.ID, th.RequestFilters)
}
}
if verbose {
log.Printf("Indexed filters tenant: %s, keys %+v", tenant, stIdxr.ChangedKeys().Slice())
}
if err := stIdxr.StoreIndexes(); err != nil {
return err
}
}
}
}
return
}
@@ -2297,6 +2333,8 @@ func (tpr *TpReader) ShowStatistics() {
log.Print("Stats: ", len(tpr.sqProfiles))
// thresholds
log.Print("Thresholds: ", len(tpr.thProfiles))
// filters
log.Print("Filters: ", len(tpr.flProfiles))
}
// Returns the identities loaded for a specific category, useful for cache reloads

View File

@@ -1366,14 +1366,13 @@ type TPThreshold struct {
Blocker bool // blocker flag to stop processing on filters matched
Weight float64 // Weight to sort the thresholds
ActionIDs []string
Async bool
}
type TPFilter struct {
TPid string
Tenant string
ID string
FilterType string // Filter type (*string, *timing, *rsr_filters, *cdr_stats)
FilterFieldName string // Name of the field providing us the Values to check (used in case of some )
FilterFielValues []string // Filter definition
TPid string
Tenant string
ID string
Filters []*TPRequestFilter
ActivationInterval *TPActivationInterval // Time when this limit becomes active and expires
}