code.vegaprotocol.io/vega@v0.79.0/core/snapshot/worker.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package snapshot 17 18 import ( 19 "encoding/hex" 20 "sync/atomic" 21 "time" 22 23 "code.vegaprotocol.io/vega/core/types" 24 "code.vegaprotocol.io/vega/libs/crypto" 25 "code.vegaprotocol.io/vega/logging" 26 ) 27 28 type treeKeyToSnapshot struct { 29 treeKey []byte 30 namespace types.SnapshotNamespace 31 } 32 33 type snapshotResult struct { 34 input treeKeyToSnapshot 35 toRemove bool 36 err error 37 state []byte 38 updated bool 39 } 40 41 func gatherState(e *Engine, treeKeysToSnapshotChan chan treeKeyToSnapshot, snapshotResultsChan chan<- snapshotResult, treeKeysCounter *atomic.Int64, recordMetrics *snapMetricsState) { 42 for toSnapshot := range treeKeysToSnapshotChan { 43 // this is for metrics 44 startTime := time.Now() 45 currentNamespace := toSnapshot.namespace 46 47 treeKeyStr := string(toSnapshot.treeKey) 48 49 t0 := time.Now() 50 51 e.snapshotLock.RLock() 52 provider := e.treeKeysToProviders[treeKeyStr] 53 providerKey := e.treeKeysToProviderKeys[treeKeyStr] 54 e.snapshotLock.RUnlock() 55 56 if provider.Stopped() { 57 snapshotResultsChan <- snapshotResult{input: toSnapshot, updated: true, toRemove: true} 58 if treeKeysCounter.Add(-1) <= 0 { 59 close(treeKeysToSnapshotChan) 60 close(snapshotResultsChan) 61 } 62 continue 63 } 64 65 state, additionalProviders, err := provider.GetState(providerKey) 66 if err != nil { 67 snapshotResultsChan <- snapshotResult{input: toSnapshot, err: err, updated: true} 68 close(treeKeysToSnapshotChan) 69 close(snapshotResultsChan) 70 return 71 } 72 73 var treeKeys [][]byte 74 var ok bool 75 additionalTreeKeysToSnapshot := []treeKeyToSnapshot{} 76 77 // The provider has generated new providers, register them with the engine 78 // add them to the AVL tree 79 for _, additionalProvider := range additionalProviders { 80 knownTreeKeys := map[string]struct{}{} 81 // need to atomically check what's in there for the tree key and then add the provider 82 e.snapshotLock.Lock() 83 treeKeys, ok = e.namespacesToTreeKeys[additionalProvider.Namespace()] 84 if ok { 85 for _, treeKey := range treeKeys { 86 knownTreeKeys[string(treeKey)] = struct{}{} 87 } 88 } 89 e.addProviders(additionalProvider) 90 e.snapshotLock.Unlock() 91 e.log.Debug("Additional provider added by the worker", 92 logging.String("namespace", additionalProvider.Namespace().String()), 93 ) 94 95 e.snapshotLock.RLock() 96 treeKeys, ok = e.namespacesToTreeKeys[additionalProvider.Namespace()] 97 e.snapshotLock.RUnlock() 98 if !ok || len(treeKeys) == 0 { 99 continue 100 } 101 102 for _, tk := range treeKeys { 103 // ignore tree keys we've already done 104 if _, ok := knownTreeKeys[string(tk)]; ok { 105 continue 106 } 107 additionalTreeKeysToSnapshot = append(additionalTreeKeysToSnapshot, treeKeyToSnapshot{treeKey: tk, namespace: additionalProvider.Namespace()}) 108 } 109 } 110 111 e.log.Debug("State updated", 112 logging.String("tree-key", treeKeyStr), 113 logging.String("hash", hex.EncodeToString(crypto.Hash(state))), 114 logging.Float64("took", time.Since(t0).Seconds()), 115 ) 116 117 treeKeysCounter.Add(int64(len(additionalTreeKeysToSnapshot))) 118 119 for _, treeKeyToSnapshot := range additionalTreeKeysToSnapshot { 120 treeKeysToSnapshotChan <- treeKeyToSnapshot 121 } 122 123 snapshotResultsChan <- snapshotResult{input: toSnapshot, state: state, updated: true} 124 125 if treeKeysCounter.Add(-1) <= 0 { 126 close(treeKeysToSnapshotChan) 127 close(snapshotResultsChan) 128 } 129 130 timeTaken := time.Since(startTime) 131 recordMetrics.Register(currentNamespace.String(), timeTaken, len(state)) 132 } 133 }