mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 02:26:26 +05:00
Merge branch 'master' of https://github.com/cgrates/cgrates
Conflicts: engine/loader_csv_test.go
This commit is contained in:
@@ -81,16 +81,17 @@ func (rsv1 *ResourceSV1) ReleaseResource(args utils.AttrRLsResourceUsage, reply
|
||||
return rsv1.rls.V1ReleaseResource(args, reply)
|
||||
}
|
||||
|
||||
type AttrGetResPrf struct {
|
||||
ID string
|
||||
type ArgGetResPrf struct {
|
||||
Tenant string
|
||||
ID string
|
||||
}
|
||||
|
||||
// GetResourceProfile returns a resource configuration
|
||||
func (apierV1 *ApierV1) GetResourceProfile(attr AttrGetResPrf, reply *engine.ResourceProfile) error {
|
||||
if missing := utils.MissingStructFields(&attr, []string{"ID"}); len(missing) != 0 { //Params missing
|
||||
func (apierV1 *ApierV1) GetResourceProfile(arg ArgGetResPrf, reply *engine.ResourceProfile) error {
|
||||
if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if rcfg, err := apierV1.DataDB.GetResourceProfile(attr.ID, true, utils.NonTransactional); err != nil {
|
||||
if rcfg, err := apierV1.DataDB.GetResourceProfile(arg.Tenant, arg.ID, true, utils.NonTransactional); err != nil {
|
||||
if err.Error() != utils.ErrNotFound.Error() {
|
||||
err = utils.NewErrServerError(err)
|
||||
}
|
||||
@@ -102,11 +103,11 @@ func (apierV1 *ApierV1) GetResourceProfile(attr AttrGetResPrf, reply *engine.Res
|
||||
}
|
||||
|
||||
//SetResourceProfile add a new resource configuration
|
||||
func (apierV1 *ApierV1) SetResourceProfile(attr *engine.ResourceProfile, reply *string) error {
|
||||
if missing := utils.MissingStructFields(attr, []string{"ID"}); len(missing) != 0 {
|
||||
func (apierV1 *ApierV1) SetResourceProfile(res *engine.ResourceProfile, reply *string) error {
|
||||
if missing := utils.MissingStructFields(res, []string{"Tenant", "ID"}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if err := apierV1.DataDB.SetResourceProfile(attr, utils.NonTransactional); err != nil {
|
||||
if err := apierV1.DataDB.SetResourceProfile(res, utils.NonTransactional); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
@@ -114,11 +115,11 @@ func (apierV1 *ApierV1) SetResourceProfile(attr *engine.ResourceProfile, reply *
|
||||
}
|
||||
|
||||
//RemResourceProfile remove a specific resource configuration
|
||||
func (apierV1 *ApierV1) RemResourceProfile(attrs AttrGetResPrf, reply *string) error {
|
||||
if missing := utils.MissingStructFields(&attrs, []string{"ID"}); len(missing) != 0 { //Params missing
|
||||
func (apierV1 *ApierV1) RemResourceProfile(arg ArgGetResPrf, reply *string) error {
|
||||
if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if err := apierV1.DataDB.RemoveResourceProfile(attrs.ID, utils.NonTransactional); err != nil {
|
||||
if err := apierV1.DataDB.RemoveResourceProfile(arg.Tenant, arg.ID, utils.NonTransactional); err != nil {
|
||||
if err.Error() != utils.ErrNotFound.Error() {
|
||||
err = utils.NewErrServerError(err)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],TTL[6],Limit[7],AllocationMessage[8],Blocker[9],Stored[10],Weight[11],Thresholds[12]
|
||||
Tester,ResGroup1,*string,Account,1001;1002,2014-07-29T15:00:00Z,1s,7,,true,true,20,
|
||||
Tester,ResGroup1,*string_prefix,Destination,10;20,,,,,,,,
|
||||
Tester,ResGroup1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),,,,,,,,
|
||||
Tester,ResGroup2,*destinations,Destination,DST_FS,2014-07-29T15:00:00Z,3600s,8,SPECIAL_1002,true,true,10,
|
||||
Tester,ResGroup3,*string,Account,3001,2014-07-29T15:00:00Z,1s,3,,true,true,20,
|
||||
#ResGroup3,*timings,SetupTime,PEAK,,,,,,,,
|
||||
#ResGroup3,*cdr_stats,,CDRST1:*min_ASR:34;CDRST_1001:*min_ASR:20,,,,,,,,
|
||||
cgrates.org,ResGroup1,*string,Account,1001;1002,2014-07-29T15:00:00Z,1s,7,,true,true,20,
|
||||
cgrates.org,ResGroup1,*string_prefix,Destination,10;20,,,,,,,,
|
||||
cgrates.org,ResGroup1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),,,,,,,,
|
||||
cgrates.org,ResGroup2,*destinations,Destination,DST_FS,2014-07-29T15:00:00Z,3600s,8,SPECIAL_1002,true,true,10,
|
||||
cgrates.org,ResGroup3,*string,Account,3001,2014-07-29T15:00:00Z,1s,3,,true,true,20,
|
||||
#cgrates.org,ResGroup3,*timings,SetupTime,PEAK,,,,,,,,
|
||||
#cgrates.org,ResGroup3,*cdr_stats,,CDRST1:*min_ASR:34;CDRST_1001:*min_ASR:20,,,,,,,,
|
||||
|
||||
|
@@ -266,11 +266,19 @@ cgrates.org,mas,true,another,value,10
|
||||
*out,cgrates.org,call,remo,remo,*any,*rating,Account,remo,minu,10
|
||||
`
|
||||
resProfiles = `
|
||||
<<<<<<< HEAD
|
||||
#Id[0]Tenant[1],,FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],TTL[6],Limit[7],AllocationMessage[8],Blocker[9],Stored[10],Weight[11],Thresholds[12]
|
||||
ResGroup21,cgrates.org,*string,HdrAccount,1001;1002,2014-07-29T15:00:00Z,1s,2,call,true,true,10,
|
||||
ResGroup21,cgrates.org,*string_prefix,HdrDestination,10;20,,,,,,,,
|
||||
ResGroup21,cgrates.org,*rsr_fields,,HdrSubject(~^1.*1$);HdrDestination(1002),,,,,,,,
|
||||
ResGroup22,cgrates.org,*destinations,HdrDestination,DST_FS,2014-07-29T15:00:00Z,3600s,2,premium_call,true,true,10,
|
||||
=======
|
||||
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],TTL[6],Limit[7],AllocationMessage[8],Blocker[9],Stored[10],Weight[11],Thresholds[12]
|
||||
cgrates.org,ResGroup21,*string,HdrAccount,1001;1002,2014-07-29T15:00:00Z,1s,2,call,true,true,10,
|
||||
cgrates.org,ResGroup21,*string_prefix,HdrDestination,10;20,,,,,,,,
|
||||
cgrates.org,ResGroup21,*rsr_fields,,HdrSubject(~^1.*1$);HdrDestination(1002),,,,,,,,
|
||||
cgrates.org,ResGroup22,*destinations,HdrDestination,DST_FS,2014-07-29T15:00:00Z,3600s,2,premium_call,true,true,10,
|
||||
>>>>>>> 72be574e2485078deacebbbd01c7df1d05991615
|
||||
`
|
||||
stats = `
|
||||
#Tenant[0],Id[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5],QueueLength[6],TTL[7],Metrics[8],Blocker[9],Stored[10],Weight[11],Thresholds[12]
|
||||
@@ -1390,6 +1398,7 @@ func TestLoadReverseAliases(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadResourceProfiles(t *testing.T) {
|
||||
<<<<<<< HEAD
|
||||
eResProfiles := map[string]*utils.TPResource{
|
||||
"ResGroup21": &utils.TPResource{
|
||||
TPid: testTPID,
|
||||
@@ -1414,20 +1423,48 @@ func TestLoadResourceProfiles(t *testing.T) {
|
||||
ID: "ResGroup22",
|
||||
Filters: []*utils.TPRequestFilter{
|
||||
&utils.TPRequestFilter{Type: MetaDestinations, FieldName: "HdrDestination", Values: []string{"DST_FS"}},
|
||||
=======
|
||||
eResProfiles := map[string]map[string]*utils.TPResource{
|
||||
"cgrates.org": map[string]*utils.TPResource{
|
||||
"ResGroup21": &utils.TPResource{
|
||||
TPid: testTPID,
|
||||
Tenant: "cgrates.org",
|
||||
ID: "ResGroup21",
|
||||
Filters: []*utils.TPRequestFilter{
|
||||
&utils.TPRequestFilter{Type: MetaString, FieldName: "HdrAccount", Values: []string{"1001", "1002"}},
|
||||
&utils.TPRequestFilter{Type: MetaStringPrefix, FieldName: "HdrDestination", Values: []string{"10", "20"}},
|
||||
&utils.TPRequestFilter{Type: MetaRSRFields, Values: []string{"HdrSubject(~^1.*1$)", "HdrDestination(1002)"}},
|
||||
},
|
||||
ActivationInterval: &utils.TPActivationInterval{
|
||||
ActivationTime: "2014-07-29T15:00:00Z",
|
||||
},
|
||||
UsageTTL: "1s",
|
||||
AllocationMessage: "call",
|
||||
Weight: 10,
|
||||
Limit: "2",
|
||||
>>>>>>> 72be574e2485078deacebbbd01c7df1d05991615
|
||||
},
|
||||
ActivationInterval: &utils.TPActivationInterval{
|
||||
ActivationTime: "2014-07-29T15:00:00Z",
|
||||
"ResGroup22": &utils.TPResource{
|
||||
TPid: testTPID,
|
||||
Tenant: "cgrates.org",
|
||||
ID: "ResGroup22",
|
||||
Filters: []*utils.TPRequestFilter{
|
||||
&utils.TPRequestFilter{Type: MetaDestinations, FieldName: "HdrDestination", Values: []string{"DST_FS"}},
|
||||
},
|
||||
ActivationInterval: &utils.TPActivationInterval{
|
||||
ActivationTime: "2014-07-29T15:00:00Z",
|
||||
},
|
||||
UsageTTL: "3600s",
|
||||
AllocationMessage: "premium_call",
|
||||
Blocker: true,
|
||||
Stored: true,
|
||||
Weight: 10,
|
||||
Limit: "2",
|
||||
},
|
||||
UsageTTL: "3600s",
|
||||
AllocationMessage: "premium_call",
|
||||
Blocker: true,
|
||||
Stored: true,
|
||||
Weight: 10,
|
||||
Limit: "2",
|
||||
},
|
||||
}
|
||||
if len(csvr.resProfiles) != len(eResProfiles) {
|
||||
t.Error("Failed to load resourceProfiles: ", len(csvr.resProfiles))
|
||||
if len(csvr.resProfiles["cgrates.org"]) != len(eResProfiles["cgrates.org"]) {
|
||||
t.Errorf("Failed to load resourceProfiles: %s", utils.ToIJSON(csvr.resProfiles))
|
||||
} else if !reflect.DeepEqual(eResProfiles["ResGroup22"], csvr.resProfiles["ResGroup22"]) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eResProfiles["ResGroup22"], csvr.resProfiles["ResGroup22"])
|
||||
|
||||
|
||||
@@ -309,17 +309,19 @@ func TestLoaderITWriteToDatabase(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
for k, rl := range loader.resProfiles {
|
||||
rcv, err := loader.dataStorage.GetResourceProfile(k, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
t.Error("Failed GetResourceProfile: ", err.Error())
|
||||
}
|
||||
rlT, err := APItoResource(rl, "UTC")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !reflect.DeepEqual(rlT, rcv) {
|
||||
t.Errorf("Expecting: %v, received: %v", rlT, rcv)
|
||||
for _, mapIDs := range loader.resProfiles {
|
||||
for _, rl := range mapIDs {
|
||||
rcv, err := loader.dataStorage.GetResourceProfile(rl.Tenant, rl.ID, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
t.Error("Failed GetResourceProfile: ", err.Error())
|
||||
}
|
||||
rlT, err := APItoResource(rl, "UTC")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !reflect.DeepEqual(rlT, rcv) {
|
||||
t.Errorf("Expecting: %v, received: %v", rlT, rcv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -782,6 +782,7 @@ func testOnStorITCacheReverseAlias(t *testing.T) {
|
||||
|
||||
func testOnStorITCacheResourceProfile(t *testing.T) {
|
||||
rCfg := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "RL_TEST",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
@@ -799,19 +800,19 @@ func testOnStorITCacheResourceProfile(t *testing.T) {
|
||||
if err := onStor.SetResourceProfile(rCfg, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
expectedR := []string{"rsp_RL_TEST"}
|
||||
expectedR := []string{"rsp_cgrates.org:RL_TEST"}
|
||||
if itm, err := onStor.GetKeysForPrefix(utils.ResourceProfilesPrefix); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(expectedR, itm) {
|
||||
t.Errorf("Expected : %+v, but received %+v", expectedR, itm)
|
||||
}
|
||||
if _, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.ID); hasIt {
|
||||
if _, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.TenantID()); hasIt {
|
||||
t.Error("Already in cache")
|
||||
}
|
||||
if err := onStor.CacheDataFromDB(utils.ResourceProfilesPrefix, []string{rCfg.ID}, false); err != nil {
|
||||
if err := onStor.CacheDataFromDB(utils.ResourceProfilesPrefix, []string{rCfg.TenantID()}, false); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if itm, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.ID); !hasIt {
|
||||
if itm, hasIt := cache.Get(utils.ResourceProfilesPrefix + rCfg.TenantID()); !hasIt {
|
||||
t.Error("Did not cache")
|
||||
} else if rcv := itm.(*ResourceProfile); !reflect.DeepEqual(rCfg, rcv) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", rCfg, rcv)
|
||||
@@ -853,7 +854,8 @@ func testOnStorITCacheTiming(t *testing.T) {
|
||||
|
||||
func testOnStorITCacheResource(t *testing.T) {
|
||||
res := &Resource{
|
||||
ID: "RL1",
|
||||
Tenant: "cgrates.org",
|
||||
ID: "RL1",
|
||||
Usages: map[string]*ResourceUsage{
|
||||
"RU1": &ResourceUsage{
|
||||
ID: "RU1",
|
||||
@@ -866,20 +868,20 @@ func testOnStorITCacheResource(t *testing.T) {
|
||||
if err := onStor.SetResource(res); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
expectedT := []string{"res_RL1"}
|
||||
expectedT := []string{"res_cgrates.org:RL1"}
|
||||
if itm, err := onStor.GetKeysForPrefix(utils.ResourcesPrefix); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(expectedT, itm) {
|
||||
t.Errorf("Expected : %+v, but received %+v", expectedT, itm)
|
||||
}
|
||||
|
||||
if _, hasIt := cache.Get(utils.ResourcesPrefix + res.ID); hasIt {
|
||||
if _, hasIt := cache.Get(utils.ResourcesPrefix + res.TenantID()); hasIt {
|
||||
t.Error("Already in cache")
|
||||
}
|
||||
if err := onStor.CacheDataFromDB(utils.ResourcesPrefix, []string{res.ID}, false); err != nil {
|
||||
if err := onStor.CacheDataFromDB(utils.ResourcesPrefix, []string{res.TenantID()}, false); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if itm, hasIt := cache.Get(utils.ResourcesPrefix + res.ID); !hasIt {
|
||||
if itm, hasIt := cache.Get(utils.ResourcesPrefix + res.TenantID()); !hasIt {
|
||||
t.Error("Did not cache")
|
||||
} else if rcv := itm.(*Resource); !reflect.DeepEqual(res, rcv) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", res, rcv)
|
||||
@@ -1798,13 +1800,13 @@ func testOnStorITCRUDResourceProfile(t *testing.T) {
|
||||
Thresholds: []string{"TEST_ACTIONS"},
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
}
|
||||
if _, rcvErr := onStor.GetResourceProfile(rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound {
|
||||
if _, rcvErr := onStor.GetResourceProfile(rL.Tenant, rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound {
|
||||
t.Error(rcvErr)
|
||||
}
|
||||
if err := onStor.SetResourceProfile(rL, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if rcv, err := onStor.GetResourceProfile(rL.ID, true, utils.NonTransactional); err != nil {
|
||||
if rcv, err := onStor.GetResourceProfile(rL.Tenant, rL.ID, true, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rL, rcv) {
|
||||
t.Errorf("Expecting: %v, received: %v", rL, rcv)
|
||||
@@ -1817,7 +1819,7 @@ func testOnStorITCRUDResourceProfile(t *testing.T) {
|
||||
// t.Error(rcvErr)
|
||||
// }
|
||||
//
|
||||
if rcv, err := onStor.GetResourceProfile(rL.ID, false, utils.NonTransactional); err != nil {
|
||||
if rcv, err := onStor.GetResourceProfile(rL.Tenant, rL.ID, false, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rL, rcv) {
|
||||
t.Errorf("Expecting: %v, received: %v", rL, rcv)
|
||||
@@ -1825,17 +1827,18 @@ func testOnStorITCRUDResourceProfile(t *testing.T) {
|
||||
// if err = onStor.SelectDatabase(onStorCfg); err != nil {
|
||||
// t.Error(err)
|
||||
// }
|
||||
if err := onStor.RemoveResourceProfile(rL.ID, utils.NonTransactional); err != nil {
|
||||
if err := onStor.RemoveResourceProfile(rL.Tenant, rL.ID, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if _, rcvErr := onStor.GetResourceProfile(rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound {
|
||||
if _, rcvErr := onStor.GetResourceProfile(rL.Tenant, rL.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound {
|
||||
t.Error(rcvErr)
|
||||
}
|
||||
}
|
||||
|
||||
func testOnStorITCRUDResource(t *testing.T) {
|
||||
res := &Resource{
|
||||
ID: "RL1",
|
||||
Tenant: "cgrates.org",
|
||||
ID: "RL1",
|
||||
Usages: map[string]*ResourceUsage{
|
||||
"RU1": &ResourceUsage{
|
||||
ID: "RU1",
|
||||
@@ -1845,26 +1848,26 @@ func testOnStorITCRUDResource(t *testing.T) {
|
||||
},
|
||||
TTLIdx: []string{"RU1"},
|
||||
}
|
||||
if _, rcvErr := onStor.GetResource("RL1", true, utils.NonTransactional); rcvErr != nil && rcvErr != utils.ErrNotFound {
|
||||
if _, rcvErr := onStor.GetResource("cgrates.org", "RL1", true, utils.NonTransactional); rcvErr != nil && rcvErr != utils.ErrNotFound {
|
||||
t.Error(rcvErr)
|
||||
}
|
||||
if err := onStor.SetResource(res); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if rcv, err := onStor.GetResource("RL1", true, utils.NonTransactional); err != nil {
|
||||
if rcv, err := onStor.GetResource("cgrates.org", "RL1", true, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
} else if !(reflect.DeepEqual(res, rcv)) {
|
||||
t.Errorf("Expecting: %v, received: %v", res, rcv)
|
||||
}
|
||||
if rcv, err := onStor.GetResource("RL1", false, utils.NonTransactional); err != nil {
|
||||
if rcv, err := onStor.GetResource("cgrates.org", "RL1", false, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(res, rcv) {
|
||||
t.Errorf("Expecting: %v, received: %v", res, rcv)
|
||||
}
|
||||
if err := onStor.RemoveResource(res.ID, utils.NonTransactional); err != nil {
|
||||
if err := onStor.RemoveResource(res.Tenant, res.ID, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if _, rcvErr := onStor.GetResource(res.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound {
|
||||
if _, rcvErr := onStor.GetResource(res.Tenant, res.ID, true, utils.NonTransactional); rcvErr != utils.ErrNotFound {
|
||||
t.Error(rcvErr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,11 @@ type ResourceProfile struct {
|
||||
Thresholds []string // Thresholds to check after changing Limit
|
||||
}
|
||||
|
||||
// TenantID returns unique identifier of the ResourceProfile in a multi-tenant environment
|
||||
func (rp *ResourceProfile) TenantID() string {
|
||||
return utils.ConcatenatedKey(rp.Tenant, rp.ID)
|
||||
}
|
||||
|
||||
// ResourceUsage represents an usage counted
|
||||
type ResourceUsage struct {
|
||||
Tenant string
|
||||
@@ -77,6 +82,11 @@ type Resource struct {
|
||||
rPrf *ResourceProfile // for ordering purposes
|
||||
}
|
||||
|
||||
// TenantID returns the unique ID in a multi-tenant environment
|
||||
func (r *Resource) TenantID() string {
|
||||
return utils.ConcatenatedKey(r.Tenant, r.ID)
|
||||
}
|
||||
|
||||
// removeExpiredUnits removes units which are expired from the resource
|
||||
func (r *Resource) removeExpiredUnits() {
|
||||
var firstActive int
|
||||
@@ -182,13 +192,21 @@ func (rs Resources) clearUsage(ruID string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ids returns list of resource IDs in resources
|
||||
func (rs Resources) ids() (ids []string) {
|
||||
ids = make([]string, len(rs))
|
||||
// tenantIDs returns list of TenantIDs in resources
|
||||
func (rs Resources) tenantIDs() []*utils.TenantID {
|
||||
tntIDs := make([]*utils.TenantID, len(rs))
|
||||
for i, r := range rs {
|
||||
ids[i] = r.ID
|
||||
tntIDs[i] = &utils.TenantID{r.Tenant, r.ID}
|
||||
}
|
||||
return
|
||||
return tntIDs
|
||||
}
|
||||
|
||||
func (rs Resources) tenatIDsStr() []string {
|
||||
ids := make([]string, len(rs))
|
||||
for i, r := range rs {
|
||||
ids[i] = r.TenantID()
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// AllocateResource attempts allocating resources for a *ResourceUsage
|
||||
@@ -198,7 +216,7 @@ func (rs Resources) AllocateResource(ru *ResourceUsage, dryRun bool) (alcMessage
|
||||
if len(rs) == 0 {
|
||||
return "", utils.ErrResourceUnavailable
|
||||
}
|
||||
lockIDs := utils.PrefixSliceItems(rs.ids(), utils.ResourcesPrefix)
|
||||
lockIDs := utils.PrefixSliceItems(rs.tenatIDsStr(), utils.ResourcesPrefix)
|
||||
guardian.Guardian.GuardIDs(config.CgrConfig().LockingTimeout, lockIDs...)
|
||||
defer guardian.Guardian.UnguardIDs(lockIDs...)
|
||||
// Simulate resource usage
|
||||
@@ -229,7 +247,7 @@ func NewResourceService(dataDB DataDB, storeInterval time.Duration,
|
||||
statS = nil
|
||||
}
|
||||
return &ResourceService{dataDB: dataDB, statS: statS,
|
||||
lcEventResources: make(map[string][]string),
|
||||
lcEventResources: make(map[string][]*utils.TenantID),
|
||||
storedResources: make(utils.StringMap),
|
||||
storeInterval: storeInterval, stopBackup: make(chan struct{})}, nil
|
||||
}
|
||||
@@ -238,7 +256,7 @@ func NewResourceService(dataDB DataDB, storeInterval time.Duration,
|
||||
type ResourceService struct {
|
||||
dataDB DataDB // So we can load the data in cache and index it
|
||||
statS rpcclient.RpcClientConnection // allows applying filters based on stats
|
||||
lcEventResources map[string][]string // cache recording resources for events in alocation phase
|
||||
lcEventResources map[string][]*utils.TenantID // cache recording resources for events in alocation phase
|
||||
lcERMux sync.RWMutex // protects the lcEventResources
|
||||
storedResources utils.StringMap // keep a record of resources which need saving, map[resID]bool
|
||||
srMux sync.RWMutex // protects storedResources
|
||||
@@ -335,7 +353,7 @@ func (rS *ResourceService) cachedResourcesForEvent(evUUID string) (rs Resources)
|
||||
if rIDsIf, has := cache.Get(utils.EventResourcesPrefix + evUUID); !has {
|
||||
return nil
|
||||
} else if rIDsIf != nil {
|
||||
rIDs = rIDsIf.([]string)
|
||||
rIDs = rIDsIf.([]*utils.TenantID)
|
||||
}
|
||||
shortCached = true
|
||||
}
|
||||
@@ -343,11 +361,14 @@ func (rS *ResourceService) cachedResourcesForEvent(evUUID string) (rs Resources)
|
||||
if len(rIDs) == 0 {
|
||||
return
|
||||
}
|
||||
lockIDs := utils.PrefixSliceItems(rIDs, utils.ResourcesPrefix)
|
||||
lockIDs := make([]string, len(rIDs))
|
||||
for i, rTid := range rIDs {
|
||||
lockIDs[i] = utils.ResourcesPrefix + rTid.TenantID()
|
||||
}
|
||||
guardian.Guardian.GuardIDs(config.CgrConfig().LockingTimeout, lockIDs...)
|
||||
defer guardian.Guardian.UnguardIDs(lockIDs...)
|
||||
for i, rID := range rIDs {
|
||||
if r, err := rS.dataDB.GetResource(rID, false, ""); err != nil {
|
||||
for i, rTid := range rIDs {
|
||||
if r, err := rS.dataDB.GetResource(rTid.Tenant, rTid.ID, false, ""); err != nil {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<ResourceS> force-uncaching resources for evUUID: <%s>, error: <%s>",
|
||||
evUUID, err.Error()))
|
||||
@@ -378,7 +399,8 @@ func (rS *ResourceService) matchingResourcesForEvent(ev map[string]interface{})
|
||||
guardian.Guardian.GuardIDs(config.CgrConfig().LockingTimeout, lockIDs...)
|
||||
defer guardian.Guardian.UnguardIDs(lockIDs...)
|
||||
for resName := range rIDs {
|
||||
rPrf, err := rS.dataDB.GetResourceProfile(resName, false, utils.NonTransactional)
|
||||
rTntID := utils.NewTenantID(resName)
|
||||
rPrf, err := rS.dataDB.GetResourceProfile(rTntID.Tenant, rTntID.ID, false, utils.NonTransactional)
|
||||
if err != nil {
|
||||
if err == utils.ErrNotFound {
|
||||
continue
|
||||
@@ -401,7 +423,7 @@ func (rS *ResourceService) matchingResourcesForEvent(ev map[string]interface{})
|
||||
if !passAllFilters {
|
||||
continue
|
||||
}
|
||||
r, err := rS.dataDB.GetResource(rPrf.ID, false, "")
|
||||
r, err := rS.dataDB.GetResource(rPrf.Tenant, rPrf.ID, false, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -450,7 +472,7 @@ func (rS *ResourceService) V1AllowUsage(args utils.AttrRLsResourceUsage, allow *
|
||||
if mtcRLs, err = rS.matchingResourcesForEvent(args.Event); err != nil {
|
||||
return err
|
||||
}
|
||||
cache.Set(utils.EventResourcesPrefix+args.UsageID, mtcRLs.ids(), true, "")
|
||||
cache.Set(utils.EventResourcesPrefix+args.UsageID, mtcRLs.tenantIDs(), true, "")
|
||||
}
|
||||
if _, err = mtcRLs.AllocateResource(
|
||||
&ResourceUsage{ID: args.UsageID,
|
||||
@@ -493,7 +515,7 @@ func (rS *ResourceService) V1AllocateResource(args utils.AttrRLsResourceUsage, r
|
||||
}
|
||||
if wasShortCached || !wasCached {
|
||||
rS.lcERMux.Lock()
|
||||
rS.lcEventResources[args.UsageID] = mtcRLs.ids()
|
||||
rS.lcEventResources[args.UsageID] = mtcRLs.tenantIDs()
|
||||
rS.lcERMux.Unlock()
|
||||
}
|
||||
// index it for storing
|
||||
|
||||
@@ -99,12 +99,12 @@ type DataDB interface {
|
||||
RemoveAlias(string, string) error
|
||||
SetReverseAlias(*Alias, string) error
|
||||
GetReverseAlias(string, bool, string) ([]string, error)
|
||||
GetResourceProfile(string, bool, string) (*ResourceProfile, error)
|
||||
GetResourceProfile(string, string, bool, string) (*ResourceProfile, error)
|
||||
SetResourceProfile(*ResourceProfile, string) error
|
||||
RemoveResourceProfile(string, string) error
|
||||
GetResource(string, bool, string) (*Resource, error)
|
||||
RemoveResourceProfile(string, string, string) error
|
||||
GetResource(string, string, bool, string) (*Resource, error)
|
||||
SetResource(*Resource) error
|
||||
RemoveResource(string, string) error
|
||||
RemoveResource(string, string, string) error
|
||||
GetTiming(string, bool, string) (*utils.TPTiming, error)
|
||||
SetTiming(*utils.TPTiming, string) error
|
||||
RemoveTiming(string, string) error
|
||||
|
||||
@@ -193,6 +193,7 @@ func (ms *MapStorage) PreloadCacheForPrefix(prefix string) error {
|
||||
|
||||
// CacheDataFromDB loads data to cache,
|
||||
// prefix represents the cache prefix, IDs should be nil if all available data should be loaded
|
||||
// ToDo: convert IDs into []*utils.TenantIDs when infrastructure will be ready
|
||||
func (ms *MapStorage) CacheDataFromDB(prefix string, IDs []string, mustBeCached bool) (err error) {
|
||||
if !utils.IsSliceMember([]string{utils.DESTINATION_PREFIX,
|
||||
utils.REVERSE_DESTINATION_PREFIX,
|
||||
@@ -273,9 +274,11 @@ func (ms *MapStorage) CacheDataFromDB(prefix string, IDs []string, mustBeCached
|
||||
case utils.REVERSE_ALIASES_PREFIX:
|
||||
_, err = ms.GetReverseAlias(dataID, true, utils.NonTransactional)
|
||||
case utils.ResourceProfilesPrefix:
|
||||
_, err = ms.GetResourceProfile(dataID, true, utils.NonTransactional)
|
||||
tntID := utils.NewTenantID(dataID)
|
||||
_, err = ms.GetResourceProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
|
||||
case utils.ResourcesPrefix:
|
||||
_, err = ms.GetResource(dataID, true, utils.NonTransactional)
|
||||
tntID := utils.NewTenantID(dataID)
|
||||
_, err = ms.GetResource(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
|
||||
case utils.TimingsPrefix:
|
||||
_, err = ms.GetTiming(dataID, true, utils.NonTransactional)
|
||||
}
|
||||
@@ -1276,10 +1279,10 @@ func (ms *MapStorage) GetSMCost(cgrid, source, runid, originHost, originID strin
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) GetResourceProfile(id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) {
|
||||
func (ms *MapStorage) GetResourceProfile(tenant, id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) {
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
key := utils.ResourceProfilesPrefix + id
|
||||
key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x != nil {
|
||||
@@ -1313,23 +1316,23 @@ func (ms *MapStorage) SetResourceProfile(r *ResourceProfile, transactionID strin
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ms.dict[utils.ResourceProfilesPrefix+r.ID] = result
|
||||
ms.dict[utils.ResourceProfilesPrefix+r.TenantID()] = result
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *MapStorage) RemoveResourceProfile(id string, transactionID string) error {
|
||||
func (ms *MapStorage) RemoveResourceProfile(tenant, id string, transactionID string) error {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
key := utils.ResourceProfilesPrefix + id
|
||||
key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
delete(ms.dict, key)
|
||||
cache.RemKey(key, cacheCommit(transactionID), transactionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *MapStorage) GetResource(id string, skipCache bool, transactionID string) (r *Resource, err error) {
|
||||
func (ms *MapStorage) GetResource(tenant, id string, skipCache bool, transactionID string) (r *Resource, err error) {
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
key := utils.ResourcesPrefix + id
|
||||
key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x != nil {
|
||||
@@ -1358,14 +1361,14 @@ func (ms *MapStorage) SetResource(r *Resource) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ms.dict[utils.ResourcesPrefix+r.ID] = result
|
||||
ms.dict[utils.ResourcesPrefix+r.TenantID()] = result
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) RemoveResource(id string, transactionID string) (err error) {
|
||||
func (ms *MapStorage) RemoveResource(tenant, id string, transactionID string) (err error) {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
key := utils.ResourcesPrefix + id
|
||||
key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
delete(ms.dict, key)
|
||||
cache.RemKey(key, cacheCommit(transactionID), transactionID)
|
||||
return
|
||||
|
||||
@@ -526,9 +526,11 @@ func (ms *MongoStorage) CacheDataFromDB(prfx string, ids []string, mustBeCached
|
||||
case utils.REVERSE_ALIASES_PREFIX:
|
||||
_, err = ms.GetReverseAlias(dataID, true, utils.NonTransactional)
|
||||
case utils.ResourceProfilesPrefix:
|
||||
_, err = ms.GetResourceProfile(dataID, true, utils.NonTransactional)
|
||||
tntID := utils.NewTenantID(dataID)
|
||||
_, err = ms.GetResourceProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
|
||||
case utils.ResourcesPrefix:
|
||||
_, err = ms.GetResource(dataID, true, utils.NonTransactional)
|
||||
tntID := utils.NewTenantID(dataID)
|
||||
_, err = ms.GetResource(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
|
||||
case utils.TimingsPrefix:
|
||||
_, err = ms.GetTiming(dataID, true, utils.NonTransactional)
|
||||
}
|
||||
@@ -554,7 +556,7 @@ func (ms *MongoStorage) GetKeysForPrefix(prefix string) (result []string, err er
|
||||
defer session.Close()
|
||||
db := session.DB(ms.db)
|
||||
keyResult := struct{ Key string }{}
|
||||
idResult := struct{ Id string }{}
|
||||
idResult := struct{ Tenant, Id string }{}
|
||||
switch category {
|
||||
case utils.DESTINATION_PREFIX:
|
||||
iter := db.C(colDst).Find(bson.M{"key": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"key": 1}).Iter()
|
||||
@@ -622,14 +624,14 @@ func (ms *MongoStorage) GetKeysForPrefix(prefix string) (result []string, err er
|
||||
result = append(result, utils.REVERSE_ALIASES_PREFIX+keyResult.Key)
|
||||
}
|
||||
case utils.ResourceProfilesPrefix:
|
||||
iter := db.C(colRsP).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter()
|
||||
iter := db.C(colRsP).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"tenant": 1, "id": 1}).Iter()
|
||||
for iter.Next(&idResult) {
|
||||
result = append(result, utils.ResourceProfilesPrefix+idResult.Id)
|
||||
result = append(result, utils.ResourceProfilesPrefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id))
|
||||
}
|
||||
case utils.ResourcesPrefix:
|
||||
iter := db.C(colRes).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter()
|
||||
iter := db.C(colRes).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"tenant": 1, "id": 1}).Iter()
|
||||
for iter.Next(&idResult) {
|
||||
result = append(result, utils.ResourcesPrefix+idResult.Id)
|
||||
result = append(result, utils.ResourcesPrefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id))
|
||||
}
|
||||
case utils.StatQueuePrefix:
|
||||
iter := db.C(colStq).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter()
|
||||
@@ -1830,8 +1832,8 @@ func (ms *MongoStorage) GetAllCdrStats() (css []*CdrStats, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) GetResourceProfile(id string, skipCache bool, transactionID string) (rp *ResourceProfile, err error) {
|
||||
key := utils.ResourceProfilesPrefix + id
|
||||
func (ms *MongoStorage) GetResourceProfile(tenant, id string, skipCache bool, transactionID string) (rp *ResourceProfile, err error) {
|
||||
key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x == nil {
|
||||
@@ -1843,7 +1845,7 @@ func (ms *MongoStorage) GetResourceProfile(id string, skipCache bool, transactio
|
||||
session, col := ms.conn(colRsP)
|
||||
defer session.Close()
|
||||
rp = new(ResourceProfile)
|
||||
if err = col.Find(bson.M{"id": id}).One(rp); err != nil {
|
||||
if err = col.Find(bson.M{"tenant": tenant, "id": id}).One(rp); err != nil {
|
||||
if err == mgo.ErrNotFound {
|
||||
err = utils.ErrNotFound
|
||||
cache.Set(key, nil, cacheCommit(transactionID), transactionID)
|
||||
@@ -1862,22 +1864,23 @@ func (ms *MongoStorage) GetResourceProfile(id string, skipCache bool, transactio
|
||||
func (ms *MongoStorage) SetResourceProfile(rp *ResourceProfile, transactionID string) (err error) {
|
||||
session, col := ms.conn(colRsP)
|
||||
defer session.Close()
|
||||
_, err = col.Upsert(bson.M{"id": rp.ID}, rp)
|
||||
_, err = col.Upsert(bson.M{"tenant": rp.Tenant, "id": rp.ID}, rp)
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) RemoveResourceProfile(id string, transactionID string) (err error) {
|
||||
func (ms *MongoStorage) RemoveResourceProfile(tenant, id string, transactionID string) (err error) {
|
||||
session, col := ms.conn(colRsP)
|
||||
defer session.Close()
|
||||
if err = col.Remove(bson.M{"id": id}); err != nil {
|
||||
if err = col.Remove(bson.M{"tenant": tenant, "id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
cache.RemKey(utils.ResourceProfilesPrefix+id, cacheCommit(transactionID), transactionID)
|
||||
cache.RemKey(utils.ResourceProfilesPrefix+utils.ConcatenatedKey(tenant, id),
|
||||
cacheCommit(transactionID), transactionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) GetResource(id string, skipCache bool, transactionID string) (r *Resource, err error) {
|
||||
key := utils.ResourcesPrefix + id
|
||||
func (ms *MongoStorage) GetResource(tenant, id string, skipCache bool, transactionID string) (r *Resource, err error) {
|
||||
key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x == nil {
|
||||
@@ -1889,7 +1892,7 @@ func (ms *MongoStorage) GetResource(id string, skipCache bool, transactionID str
|
||||
session, col := ms.conn(colRes)
|
||||
defer session.Close()
|
||||
r = new(Resource)
|
||||
if err = col.Find(bson.M{"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)
|
||||
@@ -1903,17 +1906,18 @@ func (ms *MongoStorage) GetResource(id string, skipCache bool, transactionID str
|
||||
func (ms *MongoStorage) SetResource(r *Resource) (err error) {
|
||||
session, col := ms.conn(colRes)
|
||||
defer session.Close()
|
||||
_, err = col.Upsert(bson.M{"id": r.ID}, r)
|
||||
_, err = col.Upsert(bson.M{"tenant": r.Tenant, "id": r.ID}, r)
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) RemoveResource(id string, transactionID string) (err error) {
|
||||
func (ms *MongoStorage) RemoveResource(tenant, id string, transactionID string) (err error) {
|
||||
session, col := ms.conn(colRes)
|
||||
defer session.Close()
|
||||
if err = col.Remove(bson.M{"id": id}); err != nil {
|
||||
if err = col.Remove(bson.M{"tenant": tenant, "id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
cache.RemKey(utils.ResourcesPrefix+id, cacheCommit(transactionID), transactionID)
|
||||
cache.RemKey(utils.ResourcesPrefix+utils.ConcatenatedKey(tenant, id),
|
||||
cacheCommit(transactionID), transactionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -288,9 +288,11 @@ func (rs *RedisStorage) CacheDataFromDB(prfx string, ids []string, mustBeCached
|
||||
case utils.REVERSE_ALIASES_PREFIX:
|
||||
_, err = rs.GetReverseAlias(dataID, true, utils.NonTransactional)
|
||||
case utils.ResourceProfilesPrefix:
|
||||
_, err = rs.GetResourceProfile(dataID, true, utils.NonTransactional)
|
||||
tntID := utils.NewTenantID(dataID)
|
||||
_, err = rs.GetResourceProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
|
||||
case utils.ResourcesPrefix:
|
||||
_, err = rs.GetResource(dataID, true, utils.NonTransactional)
|
||||
tntID := utils.NewTenantID(dataID)
|
||||
_, err = rs.GetResource(tntID.Tenant, tntID.ID, true, utils.NonTransactional)
|
||||
case utils.TimingsPrefix:
|
||||
_, err = rs.GetTiming(dataID, true, utils.NonTransactional)
|
||||
}
|
||||
@@ -1350,8 +1352,8 @@ func (rs *RedisStorage) GetAllCdrStats() (css []*CdrStats, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (rs *RedisStorage) GetResourceProfile(id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) {
|
||||
key := utils.ResourceProfilesPrefix + id
|
||||
func (rs *RedisStorage) GetResourceProfile(tenant, id string, skipCache bool, transactionID string) (rsp *ResourceProfile, err error) {
|
||||
key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x == nil {
|
||||
@@ -1385,11 +1387,11 @@ func (rs *RedisStorage) SetResourceProfile(rsp *ResourceProfile, transactionID s
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rs.Cmd("SET", utils.ResourceProfilesPrefix+rsp.ID, result).Err
|
||||
return rs.Cmd("SET", utils.ResourceProfilesPrefix+rsp.TenantID(), result).Err
|
||||
}
|
||||
|
||||
func (rs *RedisStorage) RemoveResourceProfile(id string, transactionID string) (err error) {
|
||||
key := utils.ResourceProfilesPrefix + id
|
||||
func (rs *RedisStorage) RemoveResourceProfile(tenant, id string, transactionID string) (err error) {
|
||||
key := utils.ResourceProfilesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if err = rs.Cmd("DEL", key).Err; err != nil {
|
||||
return
|
||||
}
|
||||
@@ -1397,8 +1399,8 @@ func (rs *RedisStorage) RemoveResourceProfile(id string, transactionID string) (
|
||||
return
|
||||
}
|
||||
|
||||
func (rs *RedisStorage) GetResource(id string, skipCache bool, transactionID string) (r *Resource, err error) {
|
||||
key := utils.ResourcesPrefix + id
|
||||
func (rs *RedisStorage) GetResource(tenant, id string, skipCache bool, transactionID string) (r *Resource, err error) {
|
||||
key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x == nil {
|
||||
@@ -1427,11 +1429,11 @@ func (rs *RedisStorage) SetResource(r *Resource) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rs.Cmd("SET", utils.ResourcesPrefix+r.ID, result).Err
|
||||
return rs.Cmd("SET", utils.ResourcesPrefix+r.TenantID(), result).Err
|
||||
}
|
||||
|
||||
func (rs *RedisStorage) RemoveResource(id string, transactionID string) (err error) {
|
||||
key := utils.ResourcesPrefix + id
|
||||
func (rs *RedisStorage) RemoveResource(tenant, id string, transactionID string) (err error) {
|
||||
key := utils.ResourcesPrefix + utils.ConcatenatedKey(tenant, id)
|
||||
if err = rs.Cmd("DEL", key).Err; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -53,11 +53,11 @@ type TpReader struct {
|
||||
cdrStats map[string]*CdrStats
|
||||
users map[string]*UserProfile
|
||||
aliases map[string]*Alias
|
||||
resProfiles map[string]*utils.TPResource
|
||||
resProfiles map[string]map[string]*utils.TPResource
|
||||
sqProfiles map[string]*utils.TPStats
|
||||
thresholds map[string]*utils.TPThreshold
|
||||
resources []string // IDs of resources which need creation based on resourceProfiles
|
||||
statQueues []string // IDs of statQueues which need creation based on statQueueProfiles
|
||||
resources []*utils.TenantID // IDs of resources which need creation based on resourceProfiles
|
||||
statQueues []string // IDs of statQueues which need creation based on statQueueProfiles
|
||||
|
||||
revDests,
|
||||
revAliases,
|
||||
@@ -129,7 +129,7 @@ func (tpr *TpReader) Init() {
|
||||
tpr.users = make(map[string]*UserProfile)
|
||||
tpr.aliases = make(map[string]*Alias)
|
||||
tpr.derivedChargers = make(map[string]*utils.DerivedChargers)
|
||||
tpr.resProfiles = make(map[string]*utils.TPResource)
|
||||
tpr.resProfiles = make(map[string]map[string]*utils.TPResource)
|
||||
tpr.sqProfiles = make(map[string]*utils.TPStats)
|
||||
tpr.thresholds = make(map[string]*utils.TPThreshold)
|
||||
tpr.revDests = make(map[string][]string)
|
||||
@@ -1599,16 +1599,22 @@ func (tpr *TpReader) LoadResourceProfilesFiltered(tag string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mapRsPs := make(map[string]*utils.TPResource)
|
||||
mapRsPfls := make(map[string]map[string]*utils.TPResource)
|
||||
for _, rl := range rls {
|
||||
mapRsPs[rl.ID] = rl
|
||||
if _, has := mapRsPfls[rl.Tenant]; !has {
|
||||
mapRsPfls[rl.Tenant] = make(map[string]*utils.TPResource)
|
||||
}
|
||||
mapRsPfls[rl.Tenant][rl.ID] = rl
|
||||
}
|
||||
tpr.resProfiles = mapRsPs
|
||||
for rID := range mapRsPs {
|
||||
if has, err := tpr.dataStorage.HasData(utils.ResourcesPrefix, rID); err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
tpr.resources = append(tpr.resources, rID)
|
||||
tpr.resProfiles = mapRsPfls
|
||||
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 {
|
||||
return err
|
||||
} else if !has {
|
||||
tpr.resources = append(tpr.resources, rTid)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -1952,27 +1958,29 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
|
||||
if verbose {
|
||||
log.Print("ResourceProfiles:")
|
||||
}
|
||||
for _, tpRsp := range tpr.resProfiles {
|
||||
rsp, err := APItoResource(tpRsp, tpr.timezone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = tpr.dataStorage.SetResourceProfile(rsp, utils.NonTransactional); err != nil {
|
||||
return err
|
||||
}
|
||||
if verbose {
|
||||
log.Print("\t", rsp.ID)
|
||||
for _, mpID := range tpr.resProfiles {
|
||||
for _, tpRsp := range mpID {
|
||||
rsp, err := APItoResource(tpRsp, tpr.timezone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = tpr.dataStorage.SetResourceProfile(rsp, utils.NonTransactional); err != nil {
|
||||
return err
|
||||
}
|
||||
if verbose {
|
||||
log.Print("\t", rsp.TenantID())
|
||||
}
|
||||
}
|
||||
}
|
||||
if verbose {
|
||||
log.Print("Resources:")
|
||||
}
|
||||
for _, rID := range tpr.resources {
|
||||
if err = tpr.dataStorage.SetResource(&Resource{ID: rID, Usages: make(map[string]*ResourceUsage)}); err != nil {
|
||||
for _, rTid := range tpr.resources {
|
||||
if err = tpr.dataStorage.SetResource(&Resource{Tenant: rTid.Tenant, ID: rTid.ID, Usages: make(map[string]*ResourceUsage)}); err != nil {
|
||||
return
|
||||
}
|
||||
if verbose {
|
||||
log.Print("\t", rID)
|
||||
log.Print("\t", rTid.TenantID())
|
||||
}
|
||||
}
|
||||
if verbose {
|
||||
@@ -2057,22 +2065,24 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
|
||||
if verbose {
|
||||
log.Print("Indexing resource profiles")
|
||||
}
|
||||
rlIdxr, err := NewReqFilterIndexer(tpr.dataStorage, utils.ResourceProfilesIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, tpRL := range tpr.resProfiles {
|
||||
if rl, err := APItoResource(tpRL, tpr.timezone); err != nil {
|
||||
for tenant, mpID := range tpr.resProfiles {
|
||||
rlIdxr, err := NewReqFilterIndexer(tpr.dataStorage, utils.ResourceProfilesIndex+tenant)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, tpRL := range mpID {
|
||||
if rl, err := APItoResource(tpRL, tpr.timezone); err != nil {
|
||||
return err
|
||||
} else {
|
||||
rlIdxr.IndexFilters(rl.ID, rl.Filters)
|
||||
}
|
||||
}
|
||||
if verbose {
|
||||
log.Printf("Indexed ResourceProfile tenant: %s keys: %+v", tenant, rlIdxr.ChangedKeys().Slice())
|
||||
}
|
||||
if err := rlIdxr.StoreIndexes(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
rlIdxr.IndexFilters(rl.ID, rl.Filters)
|
||||
}
|
||||
}
|
||||
if verbose {
|
||||
log.Printf("Indexed ResourceProfile keys: %+v", rlIdxr.ChangedKeys().Slice())
|
||||
}
|
||||
if err := rlIdxr.StoreIndexes(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(tpr.sqProfiles) > 0 {
|
||||
@@ -2294,11 +2304,11 @@ func (tpr *TpReader) GetLoadedIds(categ string) ([]string, error) {
|
||||
}
|
||||
return keys, nil
|
||||
case utils.ResourceProfilesPrefix:
|
||||
keys := make([]string, len(tpr.resProfiles))
|
||||
i := 0
|
||||
for k := range tpr.resProfiles {
|
||||
keys[i] = k
|
||||
i++
|
||||
keys := make([]string, 0)
|
||||
for tenant, mpID := range tpr.resProfiles {
|
||||
for id := range mpID {
|
||||
keys = append(keys, utils.ConcatenatedKey(tenant, id))
|
||||
}
|
||||
}
|
||||
return keys, nil
|
||||
case utils.ACTION_TRIGGER_PREFIX:
|
||||
|
||||
@@ -759,3 +759,23 @@ func AppendToFile(fName, text string) error {
|
||||
f.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewTenantID(tntID string) *TenantID {
|
||||
if strings.Index(tntID, CONCATENATED_KEY_SEP) == -1 { // no :, ID without Tenant
|
||||
return &TenantID{ID: tntID}
|
||||
}
|
||||
tIDSplt := strings.Split(tntID, CONCATENATED_KEY_SEP)
|
||||
if len(tIDSplt) == 1 { // only Tenant present
|
||||
return &TenantID{Tenant: tIDSplt[0]}
|
||||
}
|
||||
return &TenantID{Tenant: tIDSplt[0], ID: tIDSplt[1]}
|
||||
}
|
||||
|
||||
type TenantID struct {
|
||||
Tenant string
|
||||
ID string
|
||||
}
|
||||
|
||||
func (tID *TenantID) TenantID() string {
|
||||
return ConcatenatedKey(tID.Tenant, tID.ID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user