go.ligato.io/vpp-agent/v3@v3.5.0/plugins/kvscheduler/internal/graph/graph_impl.go (about)

     1  // Copyright (c) 2018 Cisco and/or its affiliates.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at:
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package graph
    16  
    17  import (
    18  	"sync"
    19  	"time"
    20  )
    21  
    22  const (
    23  	// how often (at most) the log of previous revisions gets trimmed to remove
    24  	// records too old to keep
    25  	oldRevsTrimmingPeriod = 1 * time.Minute
    26  )
    27  
    28  // kvgraph implements Graph interface.
    29  type kvgraph struct {
    30  	rwLock sync.RWMutex
    31  	graph  *graphR
    32  
    33  	startTime           time.Time
    34  	lastRevTrimming     time.Time // last time the history of revisions was trimmed
    35  	recordOldRevs       bool
    36  	recordAgeLimit      time.Duration
    37  	permanentInitPeriod time.Duration
    38  
    39  	methodTracker MethodTracker
    40  }
    41  
    42  // MethodTracker can be optionally supplied to track beginning and end of calls
    43  // for (non-trivial) graph methods.
    44  type MethodTracker func(method string) (onReturn func())
    45  
    46  // Opts groups input options for the graph constructor.
    47  type Opts struct {
    48  	RecordOldRevs       bool
    49  	RecordAgeLimit      uint32
    50  	PermanentInitPeriod uint32
    51  
    52  	MethodTracker MethodTracker
    53  }
    54  
    55  // NewGraph creates and new instance of key-value graph.
    56  // <recordOldRevs> if enabled, will cause the graph to record the previous
    57  // revisions of every node that have ever existed. <recordAgeLimit> is in minutes
    58  // and allows to limit the maximum age of a record to keep, avoiding infinite
    59  // memory usage growth. The initial phase of the execution is, however, of greater
    60  // significance and <permanentInitPeriod> allows to keep records from that period
    61  // permanently in memory.
    62  func NewGraph(opts Opts) Graph {
    63  	kvgraph := &kvgraph{
    64  		startTime:           time.Now(),
    65  		lastRevTrimming:     time.Now(),
    66  		recordOldRevs:       opts.RecordOldRevs,
    67  		recordAgeLimit:      time.Duration(opts.RecordAgeLimit) * time.Minute,
    68  		permanentInitPeriod: time.Duration(opts.PermanentInitPeriod) * time.Minute,
    69  		methodTracker:       opts.MethodTracker,
    70  	}
    71  	kvgraph.graph = newGraphR(opts.MethodTracker)
    72  	kvgraph.graph.parent = kvgraph
    73  	return kvgraph
    74  }
    75  
    76  // Read returns a graph handle for read-only access.
    77  // The graph supports multiple concurrent readers.
    78  // Release eventually using Release() method.
    79  func (kvgraph *kvgraph) Read() ReadAccess {
    80  	kvgraph.rwLock.RLock()
    81  	return kvgraph.graph
    82  }
    83  
    84  // Write returns a graph handle for read-write access.
    85  // The graph supports at most one writer at a time - i.e. it is assumed
    86  // there is no write-concurrency.
    87  // If <inPlace> is enabled, the changes are applied with immediate effect,
    88  // otherwise they are propagated to the graph using Save().
    89  // In-place Write handle holds write lock, therefore reading is blocked until
    90  // the handle is released.
    91  // If <record> is true, the changes will be recorded once the handle is
    92  // released.
    93  // Release eventually using Release() method.
    94  func (kvgraph *kvgraph) Write(inPlace, record bool) RWAccess {
    95  	if kvgraph.methodTracker != nil {
    96  		defer kvgraph.methodTracker("Write")()
    97  	}
    98  	if inPlace {
    99  		kvgraph.rwLock.Lock()
   100  	}
   101  	return newGraphRW(kvgraph.graph, inPlace, record)
   102  }