mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-20 06:38:45 +05:00
Merge branch 'Edwardro22-master'
This commit is contained in:
@@ -45,6 +45,10 @@ func init() {
|
||||
var err error
|
||||
switch DB {
|
||||
case "map":
|
||||
if cgrCfg := config.CgrConfig(); cgrCfg == nil {
|
||||
cgrCfg, _ = config.NewDefaultCGRConfig()
|
||||
config.SetCgrConfig(cgrCfg)
|
||||
}
|
||||
ratingStorage, _ = NewMapStorage()
|
||||
accountingStorage, _ = NewMapStorage()
|
||||
case utils.MONGO:
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -70,11 +71,13 @@ func (s storage) smembers(key string, ms Marshaler) (idMap utils.StringMap, ok b
|
||||
}
|
||||
|
||||
func NewMapStorage() (*MapStorage, error) {
|
||||
return &MapStorage{dict: make(map[string][]byte), ms: NewCodecMsgpackMarshaler(), cacheCfg: &config.CacheConfig{RatingPlans: &config.CacheParamConfig{Precache: true}}}, nil
|
||||
return &MapStorage{dict: make(map[string][]byte), ms: NewCodecMsgpackMarshaler(), cacheCfg: config.CgrConfig().CacheConfig}, nil
|
||||
}
|
||||
|
||||
func NewMapStorageJson() (*MapStorage, error) {
|
||||
return &MapStorage{dict: make(map[string][]byte), ms: new(JSONBufMarshaler), cacheCfg: &config.CacheConfig{RatingPlans: &config.CacheParamConfig{Precache: true}}}, nil
|
||||
func NewMapStorageJson() (mpStorage *MapStorage, err error) {
|
||||
mpStorage, err = NewMapStorage()
|
||||
mpStorage.ms = new(JSONBufMarshaler)
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) Close() {}
|
||||
@@ -95,7 +98,7 @@ func (ms *MapStorage) SelectDatabase(dbName string) (err error) {
|
||||
}
|
||||
|
||||
func (ms *MapStorage) RebuildReverseForPrefix(prefix string) error {
|
||||
// FIXME: should do transaction
|
||||
// ToDo: should do transaction
|
||||
keys, err := ms.GetKeysForPrefix(prefix)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -142,7 +145,6 @@ func (ms *MapStorage) RebuildReverseForPrefix(prefix string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FixMe
|
||||
func (ms *MapStorage) LoadRatingCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs []string) error {
|
||||
if ms.cacheCfg == nil {
|
||||
return nil
|
||||
@@ -250,6 +252,119 @@ 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
|
||||
func (ms *MapStorage) CacheDataFromDB(prefix string, IDs []string, mustBeCached bool) (err error) {
|
||||
if !utils.IsSliceMember([]string{utils.DESTINATION_PREFIX,
|
||||
utils.REVERSE_DESTINATION_PREFIX,
|
||||
utils.RATING_PLAN_PREFIX,
|
||||
utils.RATING_PROFILE_PREFIX,
|
||||
utils.ACTION_PREFIX,
|
||||
utils.ACTION_PLAN_PREFIX,
|
||||
utils.AccountActionPlansPrefix,
|
||||
utils.ACTION_TRIGGER_PREFIX,
|
||||
utils.SHARED_GROUP_PREFIX,
|
||||
utils.DERIVEDCHARGERS_PREFIX,
|
||||
utils.LCR_PREFIX,
|
||||
utils.ALIASES_PREFIX,
|
||||
utils.REVERSE_ALIASES_PREFIX,
|
||||
utils.ResourceLimitsPrefix}, prefix) {
|
||||
return utils.NewCGRError(utils.REDIS,
|
||||
utils.MandatoryIEMissingCaps,
|
||||
utils.UnsupportedCachePrefix,
|
||||
fmt.Sprintf("prefix <%s> is not a supported cache prefix", prefix))
|
||||
}
|
||||
if IDs == nil {
|
||||
keyIDs, err := ms.GetKeysForPrefix(prefix)
|
||||
if err != nil {
|
||||
return utils.NewCGRError(utils.REDIS,
|
||||
utils.ServerErrorCaps,
|
||||
err.Error(),
|
||||
fmt.Sprintf("MapStorage error <%s> querying keys for prefix: <%s>", prefix))
|
||||
}
|
||||
for _, keyID := range keyIDs {
|
||||
if mustBeCached { // Only consider loading ids which are already in cache
|
||||
if _, hasIt := cache.Get(keyID); !hasIt {
|
||||
continue
|
||||
}
|
||||
}
|
||||
IDs = append(IDs, keyID[len(prefix):])
|
||||
}
|
||||
var nrItems int
|
||||
switch prefix {
|
||||
case utils.DESTINATION_PREFIX:
|
||||
nrItems = ms.cacheCfg.Destinations.Limit
|
||||
case utils.REVERSE_DESTINATION_PREFIX:
|
||||
nrItems = ms.cacheCfg.ReverseDestinations.Limit
|
||||
case utils.RATING_PLAN_PREFIX:
|
||||
nrItems = ms.cacheCfg.RatingPlans.Limit
|
||||
case utils.RATING_PROFILE_PREFIX:
|
||||
nrItems = ms.cacheCfg.RatingProfiles.Limit
|
||||
case utils.ACTION_PREFIX:
|
||||
nrItems = ms.cacheCfg.Actions.Limit
|
||||
case utils.ACTION_PLAN_PREFIX:
|
||||
nrItems = ms.cacheCfg.ActionPlans.Limit
|
||||
case utils.AccountActionPlansPrefix:
|
||||
nrItems = ms.cacheCfg.AccountActionPlans.Limit
|
||||
case utils.ACTION_TRIGGER_PREFIX:
|
||||
nrItems = ms.cacheCfg.ActionTriggers.Limit
|
||||
case utils.SHARED_GROUP_PREFIX:
|
||||
nrItems = ms.cacheCfg.SharedGroups.Limit
|
||||
case utils.DERIVEDCHARGERS_PREFIX:
|
||||
nrItems = ms.cacheCfg.DerivedChargers.Limit
|
||||
case utils.LCR_PREFIX:
|
||||
nrItems = ms.cacheCfg.Lcr.Limit
|
||||
case utils.ALIASES_PREFIX:
|
||||
nrItems = ms.cacheCfg.Aliases.Limit
|
||||
case utils.REVERSE_ALIASES_PREFIX:
|
||||
nrItems = ms.cacheCfg.ReverseAliases.Limit
|
||||
case utils.ResourceLimitsPrefix:
|
||||
nrItems = ms.cacheCfg.ResourceLimits.Limit
|
||||
}
|
||||
if nrItems != 0 && nrItems < len(IDs) {
|
||||
IDs = IDs[:nrItems]
|
||||
}
|
||||
}
|
||||
for _, dataID := range IDs {
|
||||
if mustBeCached {
|
||||
if _, hasIt := cache.Get(prefix + dataID); !hasIt { // only cache if previously there
|
||||
continue
|
||||
}
|
||||
}
|
||||
switch prefix {
|
||||
case utils.DESTINATION_PREFIX:
|
||||
_, err = ms.GetDestination(dataID, true, utils.NonTransactional)
|
||||
case utils.REVERSE_DESTINATION_PREFIX:
|
||||
_, err = ms.GetReverseDestination(dataID, true, utils.NonTransactional)
|
||||
case utils.RATING_PLAN_PREFIX:
|
||||
_, err = ms.GetRatingPlan(dataID, true, utils.NonTransactional)
|
||||
case utils.RATING_PROFILE_PREFIX:
|
||||
_, err = ms.GetRatingProfile(dataID, true, utils.NonTransactional)
|
||||
case utils.ACTION_PREFIX:
|
||||
_, err = ms.GetActions(dataID, true, utils.NonTransactional)
|
||||
case utils.ACTION_PLAN_PREFIX:
|
||||
_, err = ms.GetActionPlan(dataID, true, utils.NonTransactional)
|
||||
case utils.AccountActionPlansPrefix:
|
||||
_, err = ms.GetAccountActionPlans(dataID, true, utils.NonTransactional)
|
||||
case utils.ACTION_TRIGGER_PREFIX:
|
||||
_, err = ms.GetActionTriggers(dataID, true, utils.NonTransactional)
|
||||
case utils.SHARED_GROUP_PREFIX:
|
||||
_, err = ms.GetSharedGroup(dataID, true, utils.NonTransactional)
|
||||
case utils.DERIVEDCHARGERS_PREFIX:
|
||||
_, err = ms.GetDerivedChargers(dataID, true, utils.NonTransactional)
|
||||
case utils.LCR_PREFIX:
|
||||
_, err = ms.GetLCR(dataID, true, utils.NonTransactional)
|
||||
case utils.ALIASES_PREFIX:
|
||||
_, err = ms.GetAlias(dataID, true, utils.NonTransactional)
|
||||
case utils.REVERSE_ALIASES_PREFIX:
|
||||
_, err = ms.GetReverseAlias(dataID, true, utils.NonTransactional)
|
||||
case utils.ResourceLimitsPrefix:
|
||||
_, err = ms.GetResourceLimit(dataID, true, utils.NonTransactional)
|
||||
}
|
||||
if err != nil {
|
||||
return utils.NewCGRError(utils.REDIS,
|
||||
utils.ServerErrorCaps,
|
||||
err.Error(),
|
||||
fmt.Sprintf("error <%s> querying MapStorage for category: <%s>, dataID: <%s>", prefix, dataID))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -343,7 +458,9 @@ func (ms *MapStorage) GetRatingProfile(key string, skipCache bool, transactionID
|
||||
cCommit := cacheCommit(transactionID)
|
||||
if values, ok := ms.dict[key]; ok {
|
||||
rpf = new(RatingProfile)
|
||||
err = ms.ms.Unmarshal(values, rpf)
|
||||
if err = ms.ms.Unmarshal(values, &rpf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
cache.Set(key, nil, cCommit, transactionID)
|
||||
return nil, utils.ErrNotFound
|
||||
@@ -439,14 +556,18 @@ func (ms *MapStorage) GetDestination(key string, skipCache bool, transactionID s
|
||||
}
|
||||
r.Close()
|
||||
dest = new(Destination)
|
||||
err = ms.ms.Unmarshal(out, dest)
|
||||
err = ms.ms.Unmarshal(out, &dest)
|
||||
if err != nil {
|
||||
cache.Set(key, dest, cCommit, transactionID)
|
||||
cache.Set(key, nil, cCommit, transactionID)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if dest == nil {
|
||||
cache.Set(key, nil, cCommit, transactionID)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
cache.Set(key, dest, cCommit, transactionID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -508,16 +629,19 @@ func (ms *MapStorage) RemoveDestination(destID string, transactionID string) (er
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ms.mu.Lock()
|
||||
delete(ms.dict, key)
|
||||
ms.mu.Unlock()
|
||||
cache.RemKey(key, cacheCommit(transactionID), transactionID)
|
||||
|
||||
for _, prefix := range d.Prefixes {
|
||||
ms.mu.Lock()
|
||||
ms.dict.srem(utils.REVERSE_DESTINATION_PREFIX+prefix, destID, ms.ms)
|
||||
ms.mu.Unlock()
|
||||
ms.GetReverseDestination(prefix, true, transactionID) // it will recache the destination
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -577,9 +701,9 @@ func (ms *MapStorage) GetActions(key string, skipCache bool, transactionID strin
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
cCommit := cacheCommit(transactionID)
|
||||
key = utils.ACTION_PREFIX + key
|
||||
cachekey := utils.ACTION_PREFIX + key
|
||||
if !skipCache {
|
||||
if x, err := cache.GetCloned(key); err != nil {
|
||||
if x, err := cache.GetCloned(cachekey); err != nil {
|
||||
if err.Error() != utils.ItemNotFound {
|
||||
return nil, err
|
||||
}
|
||||
@@ -589,13 +713,13 @@ func (ms *MapStorage) GetActions(key string, skipCache bool, transactionID strin
|
||||
return x.(Actions), nil
|
||||
}
|
||||
}
|
||||
if values, ok := ms.dict[key]; ok {
|
||||
if values, ok := ms.dict[cachekey]; ok {
|
||||
err = ms.ms.Unmarshal(values, &as)
|
||||
} else {
|
||||
cache.Set(key, nil, cCommit, transactionID)
|
||||
cache.Set(cachekey, nil, cCommit, transactionID)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
cache.Set(key, as, cCommit, transactionID)
|
||||
cache.Set(cachekey, as, cCommit, transactionID)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -603,26 +727,28 @@ func (ms *MapStorage) SetActions(key string, as Actions, transactionID string) (
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
cCommit := cacheCommit(transactionID)
|
||||
cachekey := utils.ACTION_PREFIX + key
|
||||
result, err := ms.ms.Marshal(&as)
|
||||
ms.dict[utils.ACTION_PREFIX+key] = result
|
||||
cache.RemKey(utils.ACTION_PREFIX+key, cCommit, transactionID)
|
||||
ms.dict[cachekey] = result
|
||||
cache.RemKey(cachekey, cCommit, transactionID)
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) RemoveActions(key string, transactionID string) (err error) {
|
||||
cachekey := utils.ACTION_PREFIX + key
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
delete(ms.dict, utils.ACTION_PREFIX+key)
|
||||
cache.RemKey(utils.ACTION_PREFIX+key, cacheCommit(transactionID), transactionID)
|
||||
delete(ms.dict, cachekey)
|
||||
ms.mu.Unlock()
|
||||
cache.RemKey(cachekey, cacheCommit(transactionID), transactionID)
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) GetSharedGroup(key string, skipCache bool, transactionID string) (sg *SharedGroup, err error) {
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
key = utils.SHARED_GROUP_PREFIX + key
|
||||
cachekey := utils.SHARED_GROUP_PREFIX + key
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x, ok := cache.Get(cachekey); ok {
|
||||
if x != nil {
|
||||
return x.(*SharedGroup), nil
|
||||
}
|
||||
@@ -630,13 +756,13 @@ func (ms *MapStorage) GetSharedGroup(key string, skipCache bool, transactionID s
|
||||
}
|
||||
}
|
||||
cCommit := cacheCommit(transactionID)
|
||||
if values, ok := ms.dict[key]; ok {
|
||||
if values, ok := ms.dict[cachekey]; ok {
|
||||
err = ms.ms.Unmarshal(values, &sg)
|
||||
if err == nil {
|
||||
cache.Set(key, sg, cCommit, transactionID)
|
||||
cache.Set(cachekey, sg, cCommit, transactionID)
|
||||
}
|
||||
} else {
|
||||
cache.Set(key, nil, cCommit, transactionID)
|
||||
cache.Set(cachekey, nil, cCommit, transactionID)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return
|
||||
@@ -654,12 +780,19 @@ func (ms *MapStorage) SetSharedGroup(sg *SharedGroup, transactionID string) (err
|
||||
func (ms *MapStorage) GetAccount(key string) (ub *Account, err error) {
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
if values, ok := ms.dict[utils.ACCOUNT_PREFIX+key]; ok {
|
||||
ub = &Account{ID: key}
|
||||
err = ms.ms.Unmarshal(values, ub)
|
||||
} else {
|
||||
values, ok := ms.dict[utils.ACCOUNT_PREFIX+key]
|
||||
if !ok {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
ub = &Account{ID: key}
|
||||
err = ms.ms.Unmarshal(values, &ub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(values) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -785,41 +918,40 @@ func (ms *MapStorage) RemoveUser(key string) error {
|
||||
func (ms *MapStorage) GetAlias(key string, skipCache bool, transactionID string) (al *Alias, err error) {
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
origKey := key
|
||||
key = utils.ALIASES_PREFIX + key
|
||||
cacheKey := utils.ALIASES_PREFIX + key
|
||||
cCommit := cacheCommit(transactionID)
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
if x != nil {
|
||||
al = &Alias{Values: x.(AliasValues)}
|
||||
al.SetId(origKey)
|
||||
return al, nil
|
||||
if x, ok := cache.Get(cacheKey); ok {
|
||||
if x == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return nil, utils.ErrNotFound
|
||||
return x.(*Alias), nil
|
||||
}
|
||||
}
|
||||
cCommit := cacheCommit(transactionID)
|
||||
if values, ok := ms.dict[key]; ok {
|
||||
if values, ok := ms.dict[cacheKey]; ok {
|
||||
al = &Alias{Values: make(AliasValues, 0)}
|
||||
al.SetId(key[len(utils.ALIASES_PREFIX):])
|
||||
err = ms.ms.Unmarshal(values, &al.Values)
|
||||
if err == nil {
|
||||
cache.Set(key, al.Values, cCommit, transactionID)
|
||||
al.SetId(key)
|
||||
if err = ms.ms.Unmarshal(values, &al.Values); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
cache.Set(key, nil, cCommit, transactionID)
|
||||
cache.Set(cacheKey, nil, cCommit, transactionID)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return al, nil
|
||||
cache.Set(cacheKey, al, cCommit, transactionID)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func (ms *MapStorage) SetAlias(al *Alias, transactionID string) error {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
|
||||
result, err := ms.ms.Marshal(al.Values)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key := utils.ALIASES_PREFIX + al.GetId()
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
ms.dict[key] = result
|
||||
cache.RemKey(key, cacheCommit(transactionID), transactionID)
|
||||
return nil
|
||||
@@ -837,15 +969,15 @@ func (ms *MapStorage) GetReverseAlias(reverseID string, skipCache bool, transact
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
}
|
||||
var values []string
|
||||
|
||||
cCommit := cacheCommit(transactionID)
|
||||
if idMap, ok := ms.dict.smembers(key, ms.ms); len(idMap) > 0 && ok {
|
||||
values = idMap.Slice()
|
||||
ids = idMap.Slice()
|
||||
} else {
|
||||
cache.Set(key, nil, cCommit, transactionID)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
cache.Set(key, values, cCommit, transactionID)
|
||||
cache.Set(key, ids, cCommit, transactionID)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1027,6 +1159,8 @@ func (ms *MapStorage) GetAllActionPlans() (ats map[string]*ActionPlan, err error
|
||||
}
|
||||
|
||||
func (ms *MapStorage) GetAccountActionPlans(acntID string, skipCache bool, transactionID string) (apIDs []string, err error) {
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
key := utils.AccountActionPlansPrefix + acntID
|
||||
if !skipCache {
|
||||
if x, ok := cache.Get(key); ok {
|
||||
@@ -1036,9 +1170,7 @@ func (ms *MapStorage) GetAccountActionPlans(acntID string, skipCache bool, trans
|
||||
return x.([]string), nil
|
||||
}
|
||||
}
|
||||
ms.mu.RLock()
|
||||
values, ok := ms.dict[key]
|
||||
ms.mu.RUnlock()
|
||||
if !ok {
|
||||
cache.Set(key, nil, cacheCommit(transactionID), transactionID)
|
||||
err = utils.ErrNotFound
|
||||
@@ -1053,8 +1185,7 @@ func (ms *MapStorage) GetAccountActionPlans(acntID string, skipCache bool, trans
|
||||
|
||||
func (ms *MapStorage) SetAccountActionPlans(acntID string, apIDs []string, overwrite bool) (err error) {
|
||||
if !overwrite {
|
||||
oldaPlIDs, err := ms.GetAccountActionPlans(acntID, true, utils.NonTransactional)
|
||||
if err != nil && err != utils.ErrNotFound {
|
||||
if oldaPlIDs, err := ms.GetAccountActionPlans(acntID, true, utils.NonTransactional); err != nil && err != utils.ErrNotFound {
|
||||
return err
|
||||
} else {
|
||||
for _, oldAPid := range oldaPlIDs {
|
||||
@@ -1064,7 +1195,6 @@ func (ms *MapStorage) SetAccountActionPlans(acntID string, apIDs []string, overw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
result, err := ms.ms.Marshal(apIDs)
|
||||
@@ -1072,12 +1202,11 @@ func (ms *MapStorage) SetAccountActionPlans(acntID string, apIDs []string, overw
|
||||
return err
|
||||
}
|
||||
ms.dict[utils.AccountActionPlansPrefix+acntID] = result
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) RemAccountActionPlans(acntID string, apIDs []string) (err error) {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
key := utils.AccountActionPlansPrefix + acntID
|
||||
if len(apIDs) == 0 {
|
||||
delete(ms.dict, key)
|
||||
@@ -1094,10 +1223,17 @@ func (ms *MapStorage) RemAccountActionPlans(acntID string, apIDs []string) (err
|
||||
}
|
||||
i++
|
||||
}
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
if len(oldaPlIDs) == 0 {
|
||||
delete(ms.dict, key)
|
||||
return
|
||||
}
|
||||
var result []byte
|
||||
if result, err = ms.ms.Marshal(oldaPlIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
ms.dict[key] = result
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1277,7 +1413,8 @@ func (ms *MapStorage) SetResourceLimit(rl *ResourceLimit, transactionID string)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ms.dict[utils.ResourceLimitsPrefix+rl.ID] = result
|
||||
key := utils.ResourceLimitsPrefix + rl.ID
|
||||
ms.dict[key] = result
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1314,9 +1451,10 @@ func (ms *MapStorage) SetReqFilterIndexes(dbKey string, indexes map[string]map[s
|
||||
return
|
||||
}
|
||||
func (ms *MapStorage) MatchReqFilterIndex(dbKey, fieldValKey string) (itemIDs utils.StringMap, err error) {
|
||||
cacheKey := dbKey + fieldValKey
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
if x, ok := cache.Get(dbKey + fieldValKey); ok { // Attempt to find in cache first
|
||||
if x, ok := cache.Get(cacheKey); ok { // Attempt to find in cache first
|
||||
if x != nil {
|
||||
return x.(utils.StringMap), nil
|
||||
}
|
||||
@@ -1325,7 +1463,7 @@ func (ms *MapStorage) MatchReqFilterIndex(dbKey, fieldValKey string) (itemIDs ut
|
||||
// Not found in cache, check in DB
|
||||
values, ok := ms.dict[dbKey]
|
||||
if !ok {
|
||||
cache.Set(dbKey+fieldValKey, nil, true, utils.NonTransactional)
|
||||
cache.Set(cacheKey, nil, true, utils.NonTransactional)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
var indexes map[string]map[string]utils.StringMap
|
||||
@@ -1336,7 +1474,12 @@ func (ms *MapStorage) MatchReqFilterIndex(dbKey, fieldValKey string) (itemIDs ut
|
||||
if _, hasIt := indexes[keySplt[0]]; hasIt {
|
||||
itemIDs = indexes[keySplt[0]][keySplt[1]]
|
||||
}
|
||||
cache.Set(dbKey+fieldValKey, itemIDs, true, utils.NonTransactional)
|
||||
//Verify items
|
||||
if len(itemIDs) == 0 {
|
||||
cache.Set(cacheKey, nil, true, utils.NonTransactional)
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
cache.Set(cacheKey, itemIDs, true, utils.NonTransactional)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
@@ -53,6 +56,12 @@ type v1Balance struct {
|
||||
TimingIDs string
|
||||
Disabled bool
|
||||
}
|
||||
type v1UnitsCounter struct {
|
||||
Direction string
|
||||
BalanceType string
|
||||
// Units float64
|
||||
Balances v1BalanceChain // first balance is the general one (no destination)
|
||||
}
|
||||
|
||||
func (b *v1Balance) IsDefault() bool {
|
||||
return (b.DestinationIds == "" || b.DestinationIds == utils.ANY) &&
|
||||
@@ -64,34 +73,149 @@ func (b *v1Balance) IsDefault() bool {
|
||||
b.Disabled == false
|
||||
}
|
||||
|
||||
type v1UnitsCounter struct {
|
||||
Direction string
|
||||
BalanceType string
|
||||
// Units float64
|
||||
Balances v1BalanceChain // first balance is the general one (no destination)
|
||||
}
|
||||
|
||||
type v1ActionTriggers []*v1ActionTrigger
|
||||
|
||||
type v1ActionTrigger struct {
|
||||
Id string
|
||||
ThresholdType string
|
||||
ThresholdValue float64
|
||||
Recurrent bool
|
||||
MinSleep time.Duration
|
||||
BalanceId string
|
||||
BalanceType string
|
||||
BalanceDirection string
|
||||
BalanceDestinationIds string
|
||||
BalanceWeight float64
|
||||
BalanceExpirationDate time.Time
|
||||
BalanceTimingTags string
|
||||
BalanceRatingSubject string
|
||||
BalanceCategory string
|
||||
BalanceSharedGroup string
|
||||
BalanceDisabled bool
|
||||
Weight float64
|
||||
ActionsId string
|
||||
MinQueuedItems int
|
||||
Executed bool
|
||||
func (v1Acc v1Account) AsAccount() (ac engine.Account) {
|
||||
// transfer data into new structure
|
||||
ac = engine.Account{
|
||||
ID: v1Acc.Id,
|
||||
BalanceMap: make(map[string]engine.Balances, len(v1Acc.BalanceMap)),
|
||||
UnitCounters: make(engine.UnitCounters, len(v1Acc.UnitCounters)),
|
||||
ActionTriggers: make(engine.ActionTriggers, len(v1Acc.ActionTriggers)),
|
||||
AllowNegative: v1Acc.AllowNegative,
|
||||
Disabled: v1Acc.Disabled,
|
||||
}
|
||||
idElements := strings.Split(ac.ID, utils.CONCATENATED_KEY_SEP)
|
||||
if len(idElements) != 3 {
|
||||
log.Printf("Malformed account ID %s", v1Acc.Id)
|
||||
}
|
||||
ac.ID = fmt.Sprintf("%s:%s", idElements[1], idElements[2])
|
||||
// balances
|
||||
for oldBalKey, oldBalChain := range v1Acc.BalanceMap {
|
||||
keyElements := strings.Split(oldBalKey, "*")
|
||||
newBalKey := "*" + keyElements[1]
|
||||
newBalDirection := "*" + idElements[0]
|
||||
ac.BalanceMap[newBalKey] = make(engine.Balances, len(oldBalChain))
|
||||
for index, oldBal := range oldBalChain {
|
||||
// check default to set new id
|
||||
ac.BalanceMap[newBalKey][index] = &engine.Balance{
|
||||
Uuid: oldBal.Uuid,
|
||||
ID: oldBal.Id,
|
||||
Value: oldBal.Value,
|
||||
Directions: utils.ParseStringMap(newBalDirection),
|
||||
ExpirationDate: oldBal.ExpirationDate,
|
||||
Weight: oldBal.Weight,
|
||||
DestinationIDs: utils.ParseStringMap(oldBal.DestinationIds),
|
||||
RatingSubject: oldBal.RatingSubject,
|
||||
Categories: utils.ParseStringMap(oldBal.Category),
|
||||
SharedGroups: utils.ParseStringMap(oldBal.SharedGroup),
|
||||
Timings: oldBal.Timings,
|
||||
TimingIDs: utils.ParseStringMap(oldBal.TimingIDs),
|
||||
Disabled: oldBal.Disabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
// unit counters
|
||||
for _, oldUc := range v1Acc.UnitCounters {
|
||||
newUc := &engine.UnitCounter{Counters: make(engine.CounterFilters, len(oldUc.Balances))}
|
||||
for index, oldUcBal := range oldUc.Balances {
|
||||
bf := &engine.BalanceFilter{}
|
||||
if oldUcBal.Uuid != "" {
|
||||
bf.Uuid = utils.StringPointer(oldUcBal.Uuid)
|
||||
}
|
||||
if oldUcBal.Id != "" {
|
||||
bf.ID = utils.StringPointer(oldUcBal.Id)
|
||||
}
|
||||
if oldUc.BalanceType != "" {
|
||||
bf.Type = utils.StringPointer(oldUc.BalanceType)
|
||||
}
|
||||
if oldUc.Direction != "" {
|
||||
bf.Directions = utils.StringMapPointer(utils.ParseStringMap(oldUc.Direction))
|
||||
}
|
||||
if !oldUcBal.ExpirationDate.IsZero() {
|
||||
bf.ExpirationDate = utils.TimePointer(oldUcBal.ExpirationDate)
|
||||
}
|
||||
if oldUcBal.Weight != 0 {
|
||||
bf.Weight = utils.Float64Pointer(oldUcBal.Weight)
|
||||
}
|
||||
if oldUcBal.DestinationIds != "" {
|
||||
bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.DestinationIds))
|
||||
}
|
||||
if oldUcBal.RatingSubject != "" {
|
||||
bf.RatingSubject = utils.StringPointer(oldUcBal.RatingSubject)
|
||||
}
|
||||
if oldUcBal.Category != "" {
|
||||
bf.Categories = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.Category))
|
||||
}
|
||||
if oldUcBal.SharedGroup != "" {
|
||||
bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.SharedGroup))
|
||||
}
|
||||
if oldUcBal.TimingIDs != "" {
|
||||
bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.TimingIDs))
|
||||
}
|
||||
if oldUcBal.Disabled != false {
|
||||
bf.Disabled = utils.BoolPointer(oldUcBal.Disabled)
|
||||
}
|
||||
bf.Timings = oldUcBal.Timings
|
||||
cf := &engine.CounterFilter{
|
||||
Value: oldUcBal.Value,
|
||||
Filter: bf,
|
||||
}
|
||||
newUc.Counters[index] = cf
|
||||
}
|
||||
ac.UnitCounters[oldUc.BalanceType] = append(ac.UnitCounters[oldUc.BalanceType], newUc)
|
||||
}
|
||||
//action triggers
|
||||
for index, oldAtr := range v1Acc.ActionTriggers {
|
||||
at := &engine.ActionTrigger{
|
||||
UniqueID: oldAtr.Id,
|
||||
ThresholdType: oldAtr.ThresholdType,
|
||||
ThresholdValue: oldAtr.ThresholdValue,
|
||||
Recurrent: oldAtr.Recurrent,
|
||||
MinSleep: oldAtr.MinSleep,
|
||||
Weight: oldAtr.Weight,
|
||||
ActionsID: oldAtr.ActionsId,
|
||||
MinQueuedItems: oldAtr.MinQueuedItems,
|
||||
Executed: oldAtr.Executed,
|
||||
}
|
||||
bf := &engine.BalanceFilter{}
|
||||
if oldAtr.BalanceId != "" {
|
||||
bf.ID = utils.StringPointer(oldAtr.BalanceId)
|
||||
}
|
||||
if oldAtr.BalanceType != "" {
|
||||
bf.Type = utils.StringPointer(oldAtr.BalanceType)
|
||||
}
|
||||
if oldAtr.BalanceRatingSubject != "" {
|
||||
bf.RatingSubject = utils.StringPointer(oldAtr.BalanceRatingSubject)
|
||||
}
|
||||
if oldAtr.BalanceDirection != "" {
|
||||
bf.Directions = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceDirection))
|
||||
}
|
||||
if oldAtr.BalanceDestinationIds != "" {
|
||||
bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceDestinationIds))
|
||||
}
|
||||
if oldAtr.BalanceTimingTags != "" {
|
||||
bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceTimingTags))
|
||||
}
|
||||
if oldAtr.BalanceCategory != "" {
|
||||
bf.Categories = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceCategory))
|
||||
}
|
||||
if oldAtr.BalanceSharedGroup != "" {
|
||||
bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceSharedGroup))
|
||||
}
|
||||
if oldAtr.BalanceWeight != 0 {
|
||||
bf.Weight = utils.Float64Pointer(oldAtr.BalanceWeight)
|
||||
}
|
||||
if oldAtr.BalanceDisabled != false {
|
||||
bf.Disabled = utils.BoolPointer(oldAtr.BalanceDisabled)
|
||||
}
|
||||
if !oldAtr.BalanceExpirationDate.IsZero() {
|
||||
bf.ExpirationDate = utils.TimePointer(oldAtr.BalanceExpirationDate)
|
||||
}
|
||||
at.Balance = bf
|
||||
ac.ActionTriggers[index] = at
|
||||
if ac.ActionTriggers[index].ThresholdType == "*min_counter" ||
|
||||
ac.ActionTriggers[index].ThresholdType == "*max_counter" {
|
||||
ac.ActionTriggers[index].ThresholdType = strings.Replace(ac.ActionTriggers[index].ThresholdType, "_", "_event_", 1)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
41
migrator/accounts_test.go
Normal file
41
migrator/accounts_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func TestV1AccountAsAccount(t *testing.T) {
|
||||
v1b := &v1Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
|
||||
v1Acc := &v1Account{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]v1BalanceChain{utils.VOICE: v1BalanceChain{v1b}, utils.MONETARY: v1BalanceChain{&v1Balance{Value: 21}}}}
|
||||
v2 := &engine.Balance{Uuid: "", ID: "", Value: 10, Directions: utils.StringMap{"*OUT": true}, Weight: 10, DestinationIDs: utils.StringMap{"NAT": true}, RatingSubject: "", Categories: utils.NewStringMap(""), SharedGroups: utils.NewStringMap(""), TimingIDs: utils.NewStringMap("")}
|
||||
m2 := &engine.Balance{Uuid: "", ID: "", Value: 21, Directions: utils.StringMap{"*OUT": true}, DestinationIDs: utils.NewStringMap(""), RatingSubject: "", Categories: utils.NewStringMap(""), SharedGroups: utils.NewStringMap(""), TimingIDs: utils.NewStringMap("")}
|
||||
testAccount := &engine.Account{ID: "CUSTOMER_1:rif", BalanceMap: map[string]engine.Balances{utils.VOICE: engine.Balances{v2}, utils.MONETARY: engine.Balances{m2}}, UnitCounters: engine.UnitCounters{}, ActionTriggers: engine.ActionTriggers{}}
|
||||
if def := v1b.IsDefault(); def != false {
|
||||
t.Errorf("Expecting: false, received: true")
|
||||
}
|
||||
newAcc := v1Acc.AsAccount()
|
||||
if !reflect.DeepEqual(*testAccount, newAcc) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", *testAccount, newAcc)
|
||||
}
|
||||
}
|
||||
86
migrator/action.go
Normal file
86
migrator/action.go
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type v1Action struct {
|
||||
Id string
|
||||
ActionType string
|
||||
BalanceType string
|
||||
Direction string
|
||||
ExtraParameters string
|
||||
ExpirationString string
|
||||
Weight float64
|
||||
Balance *v1Balance
|
||||
}
|
||||
|
||||
type v1Actions []*v1Action
|
||||
|
||||
func (v1Act v1Action) AsAction() (act engine.Action) {
|
||||
act = engine.Action{
|
||||
Id: v1Act.Id,
|
||||
ActionType: v1Act.ActionType,
|
||||
ExtraParameters: v1Act.ExtraParameters,
|
||||
ExpirationString: v1Act.ExpirationString,
|
||||
Weight: v1Act.Weight,
|
||||
Balance: &engine.BalanceFilter{},
|
||||
}
|
||||
bf := act.Balance
|
||||
if v1Act.Balance.Uuid != "" {
|
||||
bf.Uuid = utils.StringPointer(v1Act.Balance.Uuid)
|
||||
}
|
||||
if v1Act.Balance.Id != "" {
|
||||
bf.ID = utils.StringPointer(v1Act.Balance.Id)
|
||||
}
|
||||
if v1Act.BalanceType != "" {
|
||||
bf.Type = utils.StringPointer(v1Act.BalanceType)
|
||||
}
|
||||
if v1Act.Balance.Value != 0 {
|
||||
bf.Value = &utils.ValueFormula{Static: v1Act.Balance.Value}
|
||||
}
|
||||
if v1Act.Balance.RatingSubject != "" {
|
||||
bf.RatingSubject = utils.StringPointer(v1Act.Balance.RatingSubject)
|
||||
}
|
||||
if v1Act.Balance.DestinationIds != "" {
|
||||
bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.DestinationIds))
|
||||
}
|
||||
if v1Act.Balance.TimingIDs != "" {
|
||||
bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.TimingIDs))
|
||||
}
|
||||
if v1Act.Balance.Category != "" {
|
||||
bf.Categories = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.Category))
|
||||
}
|
||||
if v1Act.Balance.SharedGroup != "" {
|
||||
bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.SharedGroup))
|
||||
}
|
||||
if v1Act.Balance.Weight != 0 {
|
||||
bf.Weight = utils.Float64Pointer(v1Act.Balance.Weight)
|
||||
}
|
||||
if v1Act.Balance.Disabled != false {
|
||||
bf.Disabled = utils.BoolPointer(v1Act.Balance.Disabled)
|
||||
}
|
||||
if !v1Act.Balance.ExpirationDate.IsZero() {
|
||||
bf.ExpirationDate = utils.TimePointer(v1Act.Balance.ExpirationDate)
|
||||
}
|
||||
bf.Timings = v1Act.Balance.Timings
|
||||
return
|
||||
}
|
||||
75
migrator/action_plan.go
Normal file
75
migrator/action_plan.go
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type v1ActionPlan struct {
|
||||
Uuid string // uniquely identify the timing
|
||||
Id string // informative purpose only
|
||||
AccountIds []string
|
||||
Timing *engine.RateInterval
|
||||
Weight float64
|
||||
ActionsId string
|
||||
actions v1Actions
|
||||
stCache time.Time // cached time of the next start
|
||||
}
|
||||
|
||||
type v1ActionPlans []*v1ActionPlan
|
||||
|
||||
func (at *v1ActionPlan) IsASAP() bool {
|
||||
if at.Timing == nil {
|
||||
return false
|
||||
}
|
||||
return at.Timing.Timing.StartTime == utils.ASAP
|
||||
}
|
||||
|
||||
func (v1AP v1ActionPlan) AsActionPlan() (ap engine.ActionPlan) {
|
||||
for idx, actionId := range v1AP.AccountIds {
|
||||
idElements := strings.Split(actionId, utils.CONCATENATED_KEY_SEP)
|
||||
if len(idElements) != 3 {
|
||||
continue
|
||||
}
|
||||
v1AP.AccountIds[idx] = fmt.Sprintf("%s:%s", idElements[1], idElements[2])
|
||||
}
|
||||
ap = engine.ActionPlan{
|
||||
Id: v1AP.Id,
|
||||
AccountIDs: make(utils.StringMap),
|
||||
}
|
||||
if x := v1AP.IsASAP(); !x {
|
||||
for _, accID := range v1AP.AccountIds {
|
||||
if _, exists := ap.AccountIDs[accID]; !exists {
|
||||
ap.AccountIDs[accID] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
ap.ActionTimings = append(ap.ActionTimings, &engine.ActionTiming{
|
||||
Uuid: utils.GenUUID(),
|
||||
Timing: v1AP.Timing,
|
||||
ActionsID: v1AP.ActionsId,
|
||||
Weight: v1AP.Weight,
|
||||
})
|
||||
return
|
||||
}
|
||||
39
migrator/action_plan_test.go
Normal file
39
migrator/action_plan_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func TestV1ActionPlanAsActionPlan(t *testing.T) {
|
||||
v1ap := &v1ActionPlan{Id: "test", AccountIds: []string{"one"}, Timing: &engine.RateInterval{Timing: new(engine.RITiming)}}
|
||||
ap := &engine.ActionPlan{Id: "test", AccountIDs: utils.StringMap{"one": true}, ActionTimings: []*engine.ActionTiming{&engine.ActionTiming{Timing: &engine.RateInterval{Timing: new(engine.RITiming)}}}}
|
||||
newap := v1ap.AsActionPlan()
|
||||
if ap.Id != newap.Id || !reflect.DeepEqual(ap.AccountIDs, newap.AccountIDs) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", *ap, newap)
|
||||
} else if !reflect.DeepEqual(ap.ActionTimings[0].Timing, newap.ActionTimings[0].Timing) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", ap.ActionTimings[0].Timing, newap.ActionTimings[0].Timing)
|
||||
} else if ap.ActionTimings[0].Weight != newap.ActionTimings[0].Weight || ap.ActionTimings[0].ActionsID != newap.ActionTimings[0].ActionsID {
|
||||
t.Errorf("Expecting: %+v, received: %+v", ap.ActionTimings[0].Weight, newap.ActionTimings[0].Weight)
|
||||
}
|
||||
}
|
||||
34
migrator/action_test.go
Normal file
34
migrator/action_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
)
|
||||
|
||||
func TestV1ActionsAsActions(t *testing.T) {
|
||||
v1act := &v1Action{Id: "", ActionType: "", BalanceType: "", Direction: "INBOUND", ExtraParameters: "", ExpirationString: "", Balance: &v1Balance{}}
|
||||
act := &engine.Action{Id: "", ActionType: "", ExtraParameters: "", ExpirationString: "", Weight: 0.00, Balance: &engine.BalanceFilter{}}
|
||||
newact := v1act.AsAction()
|
||||
if !reflect.DeepEqual(*act, newact) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", *act, newact)
|
||||
}
|
||||
}
|
||||
89
migrator/action_trigger.go
Normal file
89
migrator/action_trigger.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type v1ActionTrigger struct {
|
||||
Id string
|
||||
ThresholdType string
|
||||
ThresholdValue float64
|
||||
Recurrent bool
|
||||
MinSleep time.Duration
|
||||
BalanceId string
|
||||
BalanceType string
|
||||
BalanceDirection string
|
||||
BalanceDestinationIds string
|
||||
BalanceWeight float64
|
||||
BalanceExpirationDate time.Time
|
||||
BalanceTimingTags string
|
||||
BalanceRatingSubject string
|
||||
BalanceCategory string
|
||||
BalanceSharedGroup string
|
||||
BalanceDisabled bool
|
||||
Weight float64
|
||||
ActionsId string
|
||||
MinQueuedItems int
|
||||
Executed bool
|
||||
}
|
||||
|
||||
type v1ActionTriggers []*v1ActionTrigger
|
||||
|
||||
func (v1Act v1ActionTrigger) AsActionTrigger() (at engine.ActionTrigger) {
|
||||
|
||||
at = engine.ActionTrigger{
|
||||
UniqueID: v1Act.Id,
|
||||
ThresholdType: v1Act.ThresholdType,
|
||||
ThresholdValue: v1Act.ThresholdValue,
|
||||
Recurrent: v1Act.Recurrent,
|
||||
MinSleep: v1Act.MinSleep,
|
||||
Weight: v1Act.Weight,
|
||||
ActionsID: v1Act.ActionsId,
|
||||
MinQueuedItems: v1Act.MinQueuedItems,
|
||||
Executed: v1Act.Executed,
|
||||
}
|
||||
bf := &engine.BalanceFilter{}
|
||||
if v1Act.BalanceId != "" {
|
||||
bf.ID = utils.StringPointer(v1Act.BalanceId)
|
||||
}
|
||||
if v1Act.BalanceType != "" {
|
||||
bf.Type = utils.StringPointer(v1Act.BalanceType)
|
||||
}
|
||||
if v1Act.BalanceRatingSubject != "" {
|
||||
bf.RatingSubject = utils.StringPointer(v1Act.BalanceRatingSubject)
|
||||
}
|
||||
if v1Act.BalanceDirection != "" {
|
||||
bf.Directions = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceDirection))
|
||||
}
|
||||
if v1Act.BalanceDestinationIds != "" {
|
||||
bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceDestinationIds))
|
||||
}
|
||||
if v1Act.BalanceTimingTags != "" {
|
||||
bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceTimingTags))
|
||||
}
|
||||
if v1Act.BalanceCategory != "" {
|
||||
bf.Categories = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceCategory))
|
||||
}
|
||||
if v1Act.BalanceSharedGroup != "" {
|
||||
bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceSharedGroup))
|
||||
}
|
||||
if v1Act.BalanceWeight != 0 {
|
||||
bf.Weight = utils.Float64Pointer(v1Act.BalanceWeight)
|
||||
}
|
||||
if v1Act.BalanceDisabled != false {
|
||||
bf.Disabled = utils.BoolPointer(v1Act.BalanceDisabled)
|
||||
}
|
||||
if !v1Act.BalanceExpirationDate.IsZero() {
|
||||
bf.ExpirationDate = utils.TimePointer(v1Act.BalanceExpirationDate)
|
||||
}
|
||||
at.Balance = bf
|
||||
if at.ThresholdType == "*min_counter" ||
|
||||
at.ThresholdType == "*max_counter" {
|
||||
at.ThresholdType = strings.Replace(at.ThresholdType, "_", "_event_", 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
50
migrator/action_trigger_test.go
Normal file
50
migrator/action_trigger_test.go
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
var v1ActionTriggers1 = `{"BalanceType": "*monetary","BalanceDirection": "*out","ThresholdType":"*max_balance", "ThresholdValue" :2, "ActionsId": "TEST_ACTIONS", "Executed": true}`
|
||||
|
||||
func TestV1ActionTriggersAsActionTriggers(t *testing.T) {
|
||||
atrs := &engine.ActionTrigger{
|
||||
Balance: &engine.BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
},
|
||||
ThresholdType: utils.TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
ActionsID: "TEST_ACTIONS",
|
||||
Executed: true,
|
||||
}
|
||||
var v1actstrgrs v1ActionTrigger
|
||||
if err := json.Unmarshal([]byte(v1ActionTriggers1), &v1actstrgrs); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
newatrs := v1actstrgrs.AsActionTrigger()
|
||||
if !reflect.DeepEqual(*atrs, newatrs) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", *atrs, newatrs)
|
||||
}
|
||||
}
|
||||
@@ -89,8 +89,8 @@ func (m *Migrator) migrateCostDetails() (err error) {
|
||||
v1CC := &v1CallCost{Direction: ccDirection.String, Category: ccCategory.String, Tenant: ccTenant.String,
|
||||
Subject: ccSubject.String, Account: ccAccount.String, Destination: ccDestination.String, TOR: ccTor.String,
|
||||
Cost: ccCost.Float64, Timespans: v1tmsps}
|
||||
cc, err := v1CC.AsCallCost()
|
||||
if err != nil {
|
||||
cc := v1CC.AsCallCost()
|
||||
if cc == nil {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<Migrator> Error: <%s> when converting into CallCost CDR with id: <%d>", err.Error(), id))
|
||||
continue
|
||||
@@ -152,7 +152,7 @@ type v1UnitInfo struct {
|
||||
TOR string
|
||||
}
|
||||
|
||||
func (v1cc *v1CallCost) AsCallCost() (cc *engine.CallCost, err error) {
|
||||
func (v1cc *v1CallCost) AsCallCost() (cc *engine.CallCost) {
|
||||
cc = new(engine.CallCost)
|
||||
cc.Direction = v1cc.Direction
|
||||
cc.Category = v1cc.Category
|
||||
|
||||
@@ -31,9 +31,7 @@ func TestV1CostDetailsAsCostDetails1(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
v1CC := &v1CallCost{Timespans: v1tmsps}
|
||||
if _, err := v1CC.AsCallCost(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_ = v1CC.AsCallCost()
|
||||
// ToDo: Test here the content
|
||||
|
||||
}
|
||||
@@ -44,7 +42,6 @@ func TestV1CostDetailsAsCostDetails2(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
v1CC := &v1CallCost{Timespans: v1tmsps}
|
||||
if _, err := v1CC.AsCallCost(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_ = v1CC.AsCallCost()
|
||||
|
||||
}
|
||||
|
||||
41
migrator/sharedgroup.go
Normal file
41
migrator/sharedgroup.go
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type v1SharedGroup struct {
|
||||
Id string
|
||||
AccountParameters map[string]*engine.SharingParameters
|
||||
MemberIds []string
|
||||
}
|
||||
|
||||
func (v1SG v1SharedGroup) AsSharedGroup() (sg engine.SharedGroup) {
|
||||
sg = engine.SharedGroup{
|
||||
Id: v1SG.Id,
|
||||
AccountParameters: v1SG.AccountParameters,
|
||||
MemberIds: make(utils.StringMap),
|
||||
}
|
||||
for _, accID := range v1SG.MemberIds {
|
||||
sg.MemberIds[accID] = true
|
||||
}
|
||||
return
|
||||
}
|
||||
48
migrator/sharedgroup_test.go
Normal file
48
migrator/sharedgroup_test.go
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package migrator
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func TestV1SharedGroupAsSharedGroup(t *testing.T) {
|
||||
v1sg := &v1SharedGroup{
|
||||
Id: "Test",
|
||||
AccountParameters: map[string]*engine.SharingParameters{
|
||||
"test": &engine.SharingParameters{Strategy: "*highest"},
|
||||
},
|
||||
MemberIds: []string{"1", "2", "3"},
|
||||
}
|
||||
sg := &engine.SharedGroup{
|
||||
Id: "Test",
|
||||
AccountParameters: map[string]*engine.SharingParameters{
|
||||
"test": &engine.SharingParameters{Strategy: "*highest"},
|
||||
},
|
||||
MemberIds: utils.NewStringMap("1", "2", "3"),
|
||||
}
|
||||
newsg := v1sg.AsSharedGroup()
|
||||
if !reflect.DeepEqual(*sg, newsg) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", *sg, newsg)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user