diff --git a/engine/action_plan.go b/engine/action_plan.go index d08dd62ad..5165b5c58 100644 --- a/engine/action_plan.go +++ b/engine/action_plan.go @@ -86,6 +86,9 @@ func (apl *ActionPlan) RemoveAccountID(accID string) (found bool) { // Clone clones *ActionPlan func (apl *ActionPlan) Clone() *ActionPlan { + if apl == nil { + return nil + } cln := &ActionPlan{ Id: apl.Id, AccountIDs: apl.AccountIDs.Clone(), diff --git a/engine/dispatcherprfl.go b/engine/dispatcherprfl.go index b12ac6cb9..66f3999f0 100644 --- a/engine/dispatcherprfl.go +++ b/engine/dispatcherprfl.go @@ -114,6 +114,9 @@ type DispatcherProfile struct { // Clone method for DispatcherProfile func (dp *DispatcherProfile) Clone() *DispatcherProfile { + if dp == nil { + return nil + } clone := &DispatcherProfile{ Tenant: dp.Tenant, ID: dp.ID, @@ -230,6 +233,9 @@ func (dHPrflIDs DispatcherHostIDs) Shuffle() { } func (dHPrflIDs DispatcherHostIDs) Clone() (cln DispatcherHostIDs) { + if dHPrflIDs == nil { + return + } cln = make(DispatcherHostIDs, len(dHPrflIDs)) copy(cln, dHPrflIDs) return diff --git a/engine/filters.go b/engine/filters.go index cbd5a1e82..317427186 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -205,6 +205,9 @@ type Filter struct { // Clone method for Filter func (fltr *Filter) Clone() *Filter { + if fltr == nil { + return nil + } clone := &Filter{ Tenant: fltr.Tenant, ID: fltr.ID, diff --git a/engine/libattributes.go b/engine/libattributes.go index 8e014970d..ba63493d7 100644 --- a/engine/libattributes.go +++ b/engine/libattributes.go @@ -67,6 +67,9 @@ type AttributeProfile struct { // Clone method for AttributeProfile struct func (ap *AttributeProfile) Clone() *AttributeProfile { + if ap == nil { + return nil + } clone := &AttributeProfile{ Tenant: ap.Tenant, ID: ap.ID, diff --git a/engine/libchargers.go b/engine/libchargers.go index 7f78ff111..cb1cd96bf 100644 --- a/engine/libchargers.go +++ b/engine/libchargers.go @@ -37,6 +37,9 @@ type ChargerProfile struct { // Clone method for ChargerProfile func (cp *ChargerProfile) Clone() *ChargerProfile { + if cp == nil { + return nil + } clone := &ChargerProfile{ Tenant: cp.Tenant, ID: cp.ID, diff --git a/engine/librankings.go b/engine/librankings.go index 49139f61a..0c8f328f7 100644 --- a/engine/librankings.go +++ b/engine/librankings.go @@ -53,11 +53,15 @@ func (rkp *RankingProfile) TenantID() string { // Clone will clone a RankingProfile func (rkP *RankingProfile) Clone() (cln *RankingProfile) { + if rkP == nil { + return nil + } cln = &RankingProfile{ Tenant: rkP.Tenant, ID: rkP.ID, Schedule: rkP.Schedule, Sorting: rkP.Sorting, + Stored: rkP.Stored, } if rkP.StatIDs != nil { cln.StatIDs = make([]string, len(rkP.StatIDs)) @@ -68,7 +72,6 @@ func (rkP *RankingProfile) Clone() (cln *RankingProfile) { copy(cln.MetricIDs, rkP.MetricIDs) } if rkP.SortingParameters != nil { - cln.SortingParameters = make([]string, len(rkP.SortingParameters)) copy(cln.SortingParameters, rkP.SortingParameters) } @@ -127,27 +130,38 @@ type Ranking struct { // Clone clones *Ranking func (r *Ranking) Clone() *Ranking { + if r == nil { + return nil + } r.rMux.RLock() defer r.rMux.RUnlock() cln := &Ranking{ - Tenant: r.Tenant, - ID: r.ID, - LastUpdate: r.LastUpdate, - Sorting: r.Sorting, - SortingParameters: make([]string, len(r.SortingParameters)), - SortedStatIDs: make([]string, len(r.SortedStatIDs)), + Tenant: r.Tenant, + ID: r.ID, + LastUpdate: r.LastUpdate, + Sorting: r.Sorting, } - copy(cln.SortingParameters, r.SortingParameters) - copy(cln.SortedStatIDs, r.SortedStatIDs) - cln.Metrics = make(map[string]map[string]float64) - for statID, metricMap := range r.Metrics { - cln.Metrics[statID] = make(map[string]float64) - maps.Copy(cln.Metrics[statID], metricMap) + if r.SortingParameters != nil { + cln.SortingParameters = make([]string, len(r.SortingParameters)) + copy(cln.SortingParameters, r.SortingParameters) + } + if r.SortedStatIDs != nil { + cln.SortedStatIDs = make([]string, len(r.SortedStatIDs)) + copy(cln.SortedStatIDs, r.SortedStatIDs) + } + if r.Metrics != nil { + cln.Metrics = make(map[string]map[string]float64) + for statID, metricMap := range r.Metrics { + cln.Metrics[statID] = make(map[string]float64) + maps.Copy(cln.Metrics[statID], metricMap) + } } if r.rkPrfl != nil { cln.rkPrfl = r.rkPrfl.Clone() } - cln.metricIDs = r.metricIDs.Clone() + if r.metricIDs != nil { + cln.metricIDs = r.metricIDs.Clone() + } return cln } diff --git a/engine/libstats.go b/engine/libstats.go index f127daf70..1297245f8 100644 --- a/engine/libstats.go +++ b/engine/libstats.go @@ -25,6 +25,8 @@ import ( "strings" "time" + "maps" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/guardian" "github.com/cgrates/cgrates/utils" @@ -48,7 +50,7 @@ type StatQueueProfile struct { lkID string // holds the reference towards guardian lock key } -// Clone clones *StatQueueProfile +// Clone clones *StatQueueProfile (lkID excluded) func (sqp *StatQueueProfile) Clone() *StatQueueProfile { if sqp == nil { return nil @@ -62,7 +64,6 @@ func (sqp *StatQueueProfile) Clone() *StatQueueProfile { Stored: sqp.Stored, Blocker: sqp.Blocker, Weight: sqp.Weight, - lkID: sqp.lkID, } if sqp.FilterIDs != nil { result.FilterIDs = make([]string, len(sqp.FilterIDs)) @@ -253,16 +254,23 @@ type StatQueue struct { ttl *time.Duration // timeToLeave, picked on each init } -// Clone clones *StatQueue +// Clone clones *StatQueue (lkID excluded) func (sq *StatQueue) Clone() *StatQueue { - result := &StatQueue{ - Tenant: sq.Tenant, - ID: sq.ID, - SQItems: make([]SQItem, len(sq.SQItems)), - SQMetrics: sq.SQMetrics, - lkID: sq.lkID, + if sq == nil { + return nil + } + result := &StatQueue{ + Tenant: sq.Tenant, + ID: sq.ID, + } + if sq.SQItems != nil { + result.SQItems = make([]SQItem, len(sq.SQItems)) + copy(result.SQItems, sq.SQItems) + } + if sq.SQMetrics != nil { + result.SQMetrics = make(map[string]StatMetric) + maps.Copy(result.SQMetrics, sq.SQMetrics) } - copy(result.SQItems, sq.SQItems) if sq.sqPrfl != nil { result.sqPrfl = sq.sqPrfl.Clone() } diff --git a/engine/libtrends.go b/engine/libtrends.go index 22ce6d519..f87bac44e 100644 --- a/engine/libtrends.go +++ b/engine/libtrends.go @@ -46,6 +46,9 @@ type TrendProfile struct { // Clone will clone the TrendProfile so it can be used by scheduler safely func (tP *TrendProfile) Clone() (clnTp *TrendProfile) { + if tP == nil { + return nil + } clnTp = &TrendProfile{ Tenant: tP.Tenant, ID: tP.ID, @@ -124,6 +127,9 @@ type Trend struct { } func (t *Trend) Clone() (tC *Trend) { + if t == nil { + return nil + } tC = &Trend{ Tenant: t.Tenant, ID: t.ID, diff --git a/engine/resources.go b/engine/resources.go index cc3f30a44..9f736e7a5 100644 --- a/engine/resources.go +++ b/engine/resources.go @@ -48,7 +48,7 @@ type ResourceProfile struct { lkID string // holds the reference towards guardian lock key } -// Clone clones *ResourceProfile +// Clone clones *ResourceProfile (lkID excluded) func (rp *ResourceProfile) Clone() *ResourceProfile { if rp == nil { return nil @@ -62,7 +62,6 @@ func (rp *ResourceProfile) Clone() *ResourceProfile { Blocker: rp.Blocker, Stored: rp.Stored, Weight: rp.Weight, - lkID: rp.lkID, } if rp.FilterIDs != nil { clone.FilterIDs = make([]string, len(rp.FilterIDs)) @@ -73,10 +72,7 @@ func (rp *ResourceProfile) Clone() *ResourceProfile { copy(clone.ThresholdIDs, rp.ThresholdIDs) } if rp.ActivationInterval != nil { - clone.ActivationInterval = &utils.ActivationInterval{ - ActivationTime: rp.ActivationInterval.ActivationTime, - ExpiryTime: rp.ActivationInterval.ExpiryTime, - } + clone.ActivationInterval = rp.ActivationInterval.Clone() } return clone } @@ -169,7 +165,7 @@ type Resource struct { rPrf *ResourceProfile // for ordering purposes } -// Clone clones *Resource +// Clone clones *Resource (lkID excluded) func (r *Resource) Clone() *Resource { if r == nil { return nil @@ -177,7 +173,6 @@ func (r *Resource) Clone() *Resource { clone := &Resource{ Tenant: r.Tenant, ID: r.ID, - lkID: r.lkID, } if r.Usages != nil { clone.Usages = make(map[string]*ResourceUsage, len(r.Usages)) @@ -207,6 +202,11 @@ func (r *Resource) Clone() *Resource { return clone } +// CacheClone returns a clone of ActionPlan used by ltcache CacheCloner +func (apl *Resource) CacheClone() any { + return apl.Clone() +} + // resourceLockKey returns the ID used to lock a resource with guardian func resourceLockKey(tnt, id string) string { return utils.ConcatenatedKey(utils.CacheResources, tnt, id) diff --git a/engine/routes.go b/engine/routes.go index 7c70d7d1d..6b236e8f8 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -104,6 +104,9 @@ type RouteProfile struct { // Clone method for RouteProfile func (rp *RouteProfile) Clone() *RouteProfile { + if rp == nil { + return nil + } clone := &RouteProfile{ Tenant: rp.Tenant, ID: rp.ID, diff --git a/engine/storage_utils.go b/engine/storage_utils.go index 9dfab7413..959d052d6 100644 --- a/engine/storage_utils.go +++ b/engine/storage_utils.go @@ -120,16 +120,17 @@ type SMCost struct { // Clone clones SMCost func (s *SMCost) Clone() *SMCost { - clone := &SMCost{ - CGRID: s.CGRID, - RunID: s.RunID, - OriginHost: s.OriginHost, - OriginID: s.OriginID, - CostSource: s.CostSource, - Usage: s.Usage, + if s == nil { + return nil } - if s.CostDetails != nil { - clone.CostDetails = s.CostDetails.Clone() + clone := &SMCost{ + CGRID: s.CGRID, + RunID: s.RunID, + OriginHost: s.OriginHost, + OriginID: s.OriginID, + CostSource: s.CostSource, + Usage: s.Usage, + CostDetails: s.CostDetails.Clone(), } return clone } diff --git a/engine/thresholds.go b/engine/thresholds.go index 3a538a831..61ce5b969 100644 --- a/engine/thresholds.go +++ b/engine/thresholds.go @@ -54,8 +54,11 @@ type ThresholdProfile struct { lkID string // holds the reference towards guardian lock key } -// Clone clones *ThresholdProfile +// Clone clones *ThresholdProfile (lkID excluded) func (tp *ThresholdProfile) Clone() *ThresholdProfile { + if tp == nil { + return nil + } clone := &ThresholdProfile{ Tenant: tp.Tenant, ID: tp.ID, @@ -65,7 +68,6 @@ func (tp *ThresholdProfile) Clone() *ThresholdProfile { Blocker: tp.Blocker, Weight: tp.Weight, Async: tp.Async, - lkID: tp.lkID, } if tp.FilterIDs != nil { clone.FilterIDs = make([]string, len(tp.FilterIDs)) @@ -139,14 +141,16 @@ type Threshold struct { dirty *bool // needs save } -// Clone clones *Threshold +// Clone clones *Threshold (lkID excluded) func (t *Threshold) Clone() *Threshold { + if t == nil { + return nil + } clone := &Threshold{ Tenant: t.Tenant, ID: t.ID, Hits: t.Hits, Snooze: t.Snooze, - lkID: t.lkID, } if t.tPrfl != nil { clone.tPrfl = t.tPrfl.Clone() diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 5a0d5f757..f46bf1e91 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -99,12 +99,17 @@ type TPDestination struct { // Clone method for TPDestination func (tpd *TPDestination) Clone() *TPDestination { + if tpd == nil { + return nil + } clone := &TPDestination{ TPid: tpd.TPid, ID: tpd.ID, } - clone.Prefixes = make([]string, len(tpd.Prefixes)) - copy(clone.Prefixes, tpd.Prefixes) + if tpd.Prefixes != nil { + clone.Prefixes = make([]string, len(tpd.Prefixes)) + copy(clone.Prefixes, tpd.Prefixes) + } return clone } @@ -123,13 +128,18 @@ type TPRateRALs struct { // Clone method for TPRateRALs func (tpr *TPRateRALs) Clone() *TPRateRALs { + if tpr == nil { + return nil + } clone := &TPRateRALs{ TPid: tpr.TPid, ID: tpr.ID, } - clone.RateSlots = make([]*RateSlot, len(tpr.RateSlots)) - for i, slot := range tpr.RateSlots { - clone.RateSlots[i] = slot.Clone() + if tpr.RateSlots != nil { + clone.RateSlots = make([]*RateSlot, len(tpr.RateSlots)) + for i, slot := range tpr.RateSlots { + clone.RateSlots[i] = slot.Clone() + } } return clone } @@ -168,6 +178,9 @@ type RateSlot struct { // Clone method for RateSlot func (rs *RateSlot) Clone() *RateSlot { + if rs == nil { + return nil + } return &RateSlot{ ConnectFee: rs.ConnectFee, Rate: rs.Rate, @@ -213,13 +226,18 @@ type TPDestinationRate struct { // Clone method for TPDestinationRate func (tpdr *TPDestinationRate) Clone() *TPDestinationRate { + if tpdr == nil { + return nil + } clone := &TPDestinationRate{ TPid: tpdr.TPid, ID: tpdr.ID, } - clone.DestinationRates = make([]*DestinationRate, len(tpdr.DestinationRates)) - for i, destRate := range tpdr.DestinationRates { - clone.DestinationRates[i] = destRate.Clone() + if tpdr.DestinationRates != nil { + clone.DestinationRates = make([]*DestinationRate, len(tpdr.DestinationRates)) + for i, destRate := range tpdr.DestinationRates { + clone.DestinationRates[i] = destRate.Clone() + } } return clone } @@ -241,6 +259,9 @@ type DestinationRate struct { // Clone method for DestinationRate func (dr *DestinationRate) Clone() *DestinationRate { + if dr == nil { + return nil + } clone := &DestinationRate{ DestinationId: dr.DestinationId, RateId: dr.RateId, @@ -267,6 +288,9 @@ type ApierTPTiming struct { // Clone method for ApierTPTiming func (apt *ApierTPTiming) Clone() *ApierTPTiming { + if apt == nil { + return nil + } return &ApierTPTiming{ TPid: apt.TPid, ID: apt.ID, @@ -412,13 +436,18 @@ type TPRatingPlan struct { // Clone method for TPRatingPlan func (tprp *TPRatingPlan) Clone() *TPRatingPlan { + if tprp == nil { + return nil + } clone := &TPRatingPlan{ TPid: tprp.TPid, ID: tprp.ID, } - clone.RatingPlanBindings = make([]*TPRatingPlanBinding, len(tprp.RatingPlanBindings)) - for i, binding := range tprp.RatingPlanBindings { - clone.RatingPlanBindings[i] = binding.Clone() + if tprp.RatingPlanBindings != nil { + clone.RatingPlanBindings = make([]*TPRatingPlanBinding, len(tprp.RatingPlanBindings)) + for i, binding := range tprp.RatingPlanBindings { + clone.RatingPlanBindings[i] = binding.Clone() + } } return clone } @@ -437,6 +466,9 @@ type TPRatingPlanBinding struct { // Clone method for TPRatingPlanBinding func (tpb *TPRatingPlanBinding) Clone() *TPRatingPlanBinding { + if tpb == nil { + return nil + } clone := &TPRatingPlanBinding{ DestinationRatesId: tpb.DestinationRatesId, TimingId: tpb.TimingId, @@ -467,6 +499,9 @@ type TPRatingProfile struct { // Clone method for TPRatingProfile func (rpf *TPRatingProfile) Clone() *TPRatingProfile { + if rpf == nil { + return nil + } clone := &TPRatingProfile{ TPid: rpf.TPid, LoadId: rpf.LoadId, @@ -474,9 +509,11 @@ func (rpf *TPRatingProfile) Clone() *TPRatingProfile { Category: rpf.Category, Subject: rpf.Subject, } - clone.RatingPlanActivations = make([]*TPRatingActivation, len(rpf.RatingPlanActivations)) - for i, activation := range rpf.RatingPlanActivations { - clone.RatingPlanActivations[i] = activation.Clone() + if rpf.RatingPlanActivations != nil { + clone.RatingPlanActivations = make([]*TPRatingActivation, len(rpf.RatingPlanActivations)) + for i, activation := range rpf.RatingPlanActivations { + clone.RatingPlanActivations[i] = activation.Clone() + } } return clone } @@ -536,6 +573,9 @@ type TPRatingActivation struct { // Clone method for TPRatingActivation func (tpa *TPRatingActivation) Clone() *TPRatingActivation { + if tpa == nil { + return nil + } return &TPRatingActivation{ ActivationTime: tpa.ActivationTime, RatingPlanId: tpa.RatingPlanId, @@ -578,13 +618,18 @@ type TPActions struct { // Clone method for TPActions func (tpa *TPActions) Clone() *TPActions { + if tpa == nil { + return nil + } clone := &TPActions{ TPid: tpa.TPid, ID: tpa.ID, } - clone.Actions = make([]*TPAction, len(tpa.Actions)) - for i, action := range tpa.Actions { - clone.Actions[i] = action.Clone() + if tpa.Actions != nil { + clone.Actions = make([]*TPAction, len(tpa.Actions)) + for i, action := range tpa.Actions { + clone.Actions[i] = action.Clone() + } } return clone } @@ -616,6 +661,9 @@ type TPAction struct { // Clone method for TPAction func (tpa *TPAction) Clone() *TPAction { + if tpa == nil { + return nil + } return &TPAction{ Identifier: tpa.Identifier, BalanceId: tpa.BalanceId, @@ -645,13 +693,18 @@ type TPSharedGroups struct { // Clone method for TPSharedGroups func (tpsg *TPSharedGroups) Clone() *TPSharedGroups { + if tpsg == nil { + return nil + } clone := &TPSharedGroups{ TPid: tpsg.TPid, ID: tpsg.ID, } - clone.SharedGroups = make([]*TPSharedGroup, len(tpsg.SharedGroups)) - for i, sharedGroup := range tpsg.SharedGroups { - clone.SharedGroups[i] = sharedGroup.Clone() + if tpsg.SharedGroups != nil { + clone.SharedGroups = make([]*TPSharedGroup, len(tpsg.SharedGroups)) + for i, sharedGroup := range tpsg.SharedGroups { + clone.SharedGroups[i] = sharedGroup.Clone() + } } return clone } @@ -669,6 +722,9 @@ type TPSharedGroup struct { // Clone method for TPSharedGroup func (tpsg *TPSharedGroup) Clone() *TPSharedGroup { + if tpsg == nil { + return nil + } return &TPSharedGroup{ Account: tpsg.Account, Strategy: tpsg.Strategy, @@ -684,13 +740,18 @@ type TPActionPlan struct { // Clone method for TPActionPlan func (tap *TPActionPlan) Clone() *TPActionPlan { + if tap == nil { + return nil + } clone := &TPActionPlan{ TPid: tap.TPid, ID: tap.ID, } - clone.ActionPlan = make([]*TPActionTiming, len(tap.ActionPlan)) - for i, actionTiming := range tap.ActionPlan { - clone.ActionPlan[i] = actionTiming.Clone() + if tap.ActionPlan != nil { + clone.ActionPlan = make([]*TPActionTiming, len(tap.ActionPlan)) + for i, actionTiming := range tap.ActionPlan { + clone.ActionPlan[i] = actionTiming.Clone() + } } return clone } @@ -708,6 +769,9 @@ type TPActionTiming struct { // Clone method for TPActionTiming func (tat *TPActionTiming) Clone() *TPActionTiming { + if tat == nil { + return nil + } return &TPActionTiming{ ActionsId: tat.ActionsId, TimingId: tat.TimingId, @@ -723,13 +787,18 @@ type TPActionTriggers struct { // Clone method for TPActionTriggers func (tpat *TPActionTriggers) Clone() *TPActionTriggers { + if tpat == nil { + return nil + } clone := &TPActionTriggers{ TPid: tpat.TPid, ID: tpat.ID, } - clone.ActionTriggers = make([]*TPActionTrigger, len(tpat.ActionTriggers)) - for i, actionTrigger := range tpat.ActionTriggers { - clone.ActionTriggers[i] = actionTrigger.Clone() + if tpat.ActionTriggers != nil { + clone.ActionTriggers = make([]*TPActionTrigger, len(tpat.ActionTriggers)) + for i, actionTrigger := range tpat.ActionTriggers { + clone.ActionTriggers[i] = actionTrigger.Clone() + } } return clone } @@ -765,6 +834,9 @@ type TPActionTrigger struct { // Clone method for TPActionTrigger func (tpat *TPActionTrigger) Clone() *TPActionTrigger { + if tpat == nil { + return nil + } return &TPActionTrigger{ Id: tpat.Id, UniqueID: tpat.UniqueID, @@ -803,6 +875,9 @@ type TPAccountActions struct { // Clone method for TPAccountActions func (aa *TPAccountActions) Clone() *TPAccountActions { + if aa == nil { + return nil + } return &TPAccountActions{ TPid: aa.TPid, LoadId: aa.LoadId, @@ -1308,6 +1383,9 @@ type TPResourceProfile struct { // Clone method for TPResourceProfile func (trp *TPResourceProfile) Clone() *TPResourceProfile { + if trp == nil { + return nil + } clone := &TPResourceProfile{ TPid: trp.TPid, Tenant: trp.Tenant, @@ -1319,10 +1397,14 @@ func (trp *TPResourceProfile) Clone() *TPResourceProfile { Stored: trp.Stored, Weight: trp.Weight, } - clone.FilterIDs = make([]string, len(trp.FilterIDs)) - copy(clone.FilterIDs, trp.FilterIDs) - clone.ThresholdIDs = make([]string, len(trp.ThresholdIDs)) - copy(clone.ThresholdIDs, trp.ThresholdIDs) + if trp.FilterIDs != nil { + clone.FilterIDs = make([]string, len(trp.FilterIDs)) + copy(clone.FilterIDs, trp.FilterIDs) + } + if trp.ThresholdIDs != nil { + clone.ThresholdIDs = make([]string, len(trp.ThresholdIDs)) + copy(clone.ThresholdIDs, trp.ThresholdIDs) + } if trp.ActivationInterval != nil { clone.ActivationInterval = trp.ActivationInterval.Clone() } @@ -1342,6 +1424,9 @@ type TPActivationInterval struct { // Clone method for TPActivationInterval func (tai *TPActivationInterval) Clone() *TPActivationInterval { + if tai == nil { + return nil + } return &TPActivationInterval{ ActivationTime: tai.ActivationTime, ExpiryTime: tai.ExpiryTime, @@ -1418,6 +1503,9 @@ type MetricWithFilters struct { // Clone method for MetricWithFilters func (mwf *MetricWithFilters) Clone() *MetricWithFilters { + if mwf == nil { + return nil + } return &MetricWithFilters{ FilterIDs: slices.Clone(mwf.FilterIDs), MetricID: mwf.MetricID, @@ -1443,6 +1531,9 @@ type TPStatProfile struct { // Clone method for TPStatProfile func (tsp *TPStatProfile) Clone() *TPStatProfile { + if tsp == nil { + return nil + } clone := &TPStatProfile{ TPid: tsp.TPid, Tenant: tsp.Tenant, @@ -1454,13 +1545,19 @@ func (tsp *TPStatProfile) Clone() *TPStatProfile { Weight: tsp.Weight, MinItems: tsp.MinItems, } - clone.FilterIDs = make([]string, len(tsp.FilterIDs)) - copy(clone.FilterIDs, tsp.FilterIDs) - clone.ThresholdIDs = make([]string, len(tsp.ThresholdIDs)) - copy(clone.ThresholdIDs, tsp.ThresholdIDs) - clone.Metrics = make([]*MetricWithFilters, len(tsp.Metrics)) - for i, metric := range tsp.Metrics { - clone.Metrics[i] = metric.Clone() + if tsp.FilterIDs != nil { + clone.FilterIDs = make([]string, len(tsp.FilterIDs)) + copy(clone.FilterIDs, tsp.FilterIDs) + } + if tsp.ThresholdIDs != nil { + clone.ThresholdIDs = make([]string, len(tsp.ThresholdIDs)) + copy(clone.ThresholdIDs, tsp.ThresholdIDs) + } + if tsp.Metrics != nil { + clone.Metrics = make([]*MetricWithFilters, len(tsp.Metrics)) + for i, metric := range tsp.Metrics { + clone.Metrics[i] = metric.Clone() + } } if tsp.ActivationInterval != nil { clone.ActivationInterval = tsp.ActivationInterval.Clone() @@ -1489,6 +1586,9 @@ type TPRankingProfile struct { // Clone method for TPRankingProfile func (trp *TPRankingProfile) Clone() *TPRankingProfile { + if trp == nil { + return nil + } clone := &TPRankingProfile{ TPid: trp.TPid, Tenant: trp.Tenant, @@ -1546,6 +1646,9 @@ type TPTrendsProfile struct { // Clone method for TPTrendsProfile func (ttp *TPTrendsProfile) Clone() *TPTrendsProfile { + if ttp == nil { + return nil + } clone := &TPTrendsProfile{ TPid: ttp.TPid, Tenant: ttp.Tenant, @@ -1593,6 +1696,9 @@ type TPThresholdProfile struct { // Clone method for TPThresholdProfile func (ttp *TPThresholdProfile) Clone() *TPThresholdProfile { + if ttp == nil { + return nil + } clone := &TPThresholdProfile{ TPid: ttp.TPid, Tenant: ttp.Tenant, @@ -1604,10 +1710,14 @@ func (ttp *TPThresholdProfile) Clone() *TPThresholdProfile { Weight: ttp.Weight, Async: ttp.Async, } - clone.FilterIDs = make([]string, len(ttp.FilterIDs)) - copy(clone.FilterIDs, ttp.FilterIDs) - clone.ActionIDs = make([]string, len(ttp.ActionIDs)) - copy(clone.ActionIDs, ttp.ActionIDs) + if ttp.FilterIDs != nil { + clone.FilterIDs = make([]string, len(ttp.FilterIDs)) + copy(clone.FilterIDs, ttp.FilterIDs) + } + if ttp.ActionIDs != nil { + clone.ActionIDs = make([]string, len(ttp.ActionIDs)) + copy(clone.ActionIDs, ttp.ActionIDs) + } if ttp.ActivationInterval != nil { clone.ActivationInterval = ttp.ActivationInterval.Clone() } @@ -1630,20 +1740,18 @@ type TPFilterProfile struct { // Clone method for TPFilterProfile func (tfp *TPFilterProfile) Clone() *TPFilterProfile { + if tfp == nil { + return nil + } clone := &TPFilterProfile{ TPid: tfp.TPid, Tenant: tfp.Tenant, ID: tfp.ID, } - if len(tfp.Filters) > 0 { + if tfp.Filters != nil { clone.Filters = make([]*TPFilter, len(tfp.Filters)) for i, filter := range tfp.Filters { - clone.Filters[i] = &TPFilter{ - Type: filter.Type, - Element: filter.Element, - Values: make([]string, len(filter.Values)), - } - copy(clone.Filters[i].Values, filter.Values) + clone.Filters[i] = filter.Clone() } } if tfp.ActivationInterval != nil { @@ -1664,6 +1772,22 @@ type TPFilter struct { Values []string // Filter definition } +// Clone method for TPFilter +func (f *TPFilter) Clone() *TPFilter { + if f == nil { + return nil + } + clone := &TPFilter{ + Type: f.Type, + Element: f.Element, + } + if f.Values != nil { + clone.Values = make([]string, len(f.Values)) + copy(clone.Values, f.Values) + } + return clone +} + // TPRoute is used in TPRouteProfile type TPRoute struct { ID string // RouteID @@ -1679,6 +1803,9 @@ type TPRoute struct { // Clone method for TPRoute func (r *TPRoute) Clone() *TPRoute { + if r == nil { + return nil + } return &TPRoute{ ID: r.ID, Weight: r.Weight, @@ -1707,6 +1834,9 @@ type TPRouteProfile struct { // Clone method for TPRouteProfile func (tprp *TPRouteProfile) Clone() *TPRouteProfile { + if tprp == nil { + return nil + } clone := &TPRouteProfile{ TPid: tprp.TPid, Tenant: tprp.Tenant, @@ -1749,6 +1879,9 @@ type TPAttribute struct { // Clone clones TPAttribute func (tpa *TPAttribute) Clone() *TPAttribute { + if tpa == nil { + return nil + } clone := &TPAttribute{ Path: tpa.Path, Type: tpa.Type, @@ -1776,6 +1909,9 @@ type TPAttributeProfile struct { // Clone clones TPAttributeProfile func (tpap *TPAttributeProfile) Clone() *TPAttributeProfile { + if tpap == nil { + return nil + } clone := &TPAttributeProfile{ TPid: tpap.TPid, Tenant: tpap.Tenant, @@ -1822,6 +1958,9 @@ type TPChargerProfile struct { // Clone clones TPChargerProfile func (tpcp *TPChargerProfile) Clone() *TPChargerProfile { + if tpcp == nil { + return nil + } clone := &TPChargerProfile{ TPid: tpcp.TPid, Tenant: tpcp.Tenant, @@ -1870,6 +2009,9 @@ type TPDispatcherProfile struct { // Clone clones TPDispatcherProfile func (tpdp *TPDispatcherProfile) Clone() *TPDispatcherProfile { + if tpdp == nil { + return nil + } clone := &TPDispatcherProfile{ TPid: tpdp.TPid, Tenant: tpdp.Tenant, @@ -1917,6 +2059,9 @@ type TPDispatcherHostProfile struct { // Clone clones TPDispatcherHostProfile func (tpdhp *TPDispatcherHostProfile) Clone() *TPDispatcherHostProfile { + if tpdhp == nil { + return nil + } clone := &TPDispatcherHostProfile{ ID: tpdhp.ID, Weight: tpdhp.Weight, @@ -1943,6 +2088,9 @@ type TPDispatcherHost struct { // Clone clones TPDispatcherHost func (tpdh *TPDispatcherHost) Clone() *TPDispatcherHost { + if tpdh == nil { + return nil + } clone := &TPDispatcherHost{ TPid: tpdh.TPid, Tenant: tpdh.Tenant, @@ -1976,6 +2124,9 @@ type TPDispatcherHostConn struct { // Clone clones TPDispatcherHostConn func (tpdhc *TPDispatcherHostConn) Clone() *TPDispatcherHostConn { + if tpdhc == nil { + return nil + } return &TPDispatcherHostConn{ Address: tpdhc.Address, Transport: tpdhc.Transport, diff --git a/utils/map.go b/utils/map.go index f21ca9c5c..9677e3922 100644 --- a/utils/map.go +++ b/utils/map.go @@ -111,6 +111,9 @@ func (sm StringMap) Copy(o StringMap) { } func (sm StringMap) Clone() StringMap { + if sm == nil { + return nil + } result := make(StringMap, len(sm)) result.Copy(sm) return result