github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/stores/indexshipper/uploads/table.go (about) 1 package uploads 2 3 import ( 4 "context" 5 "sync" 6 "time" 7 8 "github.com/go-kit/log" 9 10 "github.com/grafana/loki/pkg/storage/stores/indexshipper/index" 11 "github.com/grafana/loki/pkg/storage/stores/indexshipper/storage" 12 util_log "github.com/grafana/loki/pkg/util/log" 13 ) 14 15 const ( 16 // a temp file is created during uploads with name of the db + tempFileSuffix 17 tempFileSuffix = ".temp" 18 ) 19 20 type Table interface { 21 Name() string 22 AddIndex(userID string, idx index.Index) error 23 ForEach(userID string, callback index.ForEachIndexCallback) error 24 Upload(ctx context.Context) error 25 Cleanup(indexRetainPeriod time.Duration) error 26 Stop() 27 } 28 29 // table is a collection of one or more index files created by the ingester or compacted by the compactor. 30 // A table would provide a logical grouping for index by a period. This period is controlled by `schema_config.configs.index.period` config. 31 // It contains index for all the users sending logs to Loki. 32 // All the public methods are concurrency safe and take care of mutexes to avoid any data race. 33 type table struct { 34 name string 35 baseUserIndexSet, baseCommonIndexSet storage.IndexSet 36 logger log.Logger 37 38 indexSet map[string]IndexSet 39 indexSetMtx sync.RWMutex 40 } 41 42 // NewTable create a new table instance. 43 func NewTable(name string, storageClient storage.Client) Table { 44 return &table{ 45 name: name, 46 baseUserIndexSet: storage.NewIndexSet(storageClient, true), 47 baseCommonIndexSet: storage.NewIndexSet(storageClient, false), 48 logger: log.With(util_log.Logger, "table-name", name), 49 indexSet: make(map[string]IndexSet), 50 } 51 } 52 53 // Name returns the name of the table. 54 func (lt *table) Name() string { 55 return lt.name 56 } 57 58 // AddIndex adds a new index to the table. 59 func (lt *table) AddIndex(userID string, idx index.Index) error { 60 lt.indexSetMtx.Lock() 61 defer lt.indexSetMtx.Unlock() 62 63 if _, ok := lt.indexSet[userID]; !ok { 64 baseIndexSet := lt.baseUserIndexSet 65 if userID == "" { 66 baseIndexSet = lt.baseCommonIndexSet 67 } 68 idxSet, err := NewIndexSet(lt.name, userID, baseIndexSet, loggerWithUserID(lt.logger, userID)) 69 if err != nil { 70 return err 71 } 72 73 lt.indexSet[userID] = idxSet 74 } 75 76 lt.indexSet[userID].Add(idx) 77 return nil 78 } 79 80 // ForEach iterates over all the indexes belonging to the user. 81 func (lt *table) ForEach(userID string, callback index.ForEachIndexCallback) error { 82 lt.indexSetMtx.RLock() 83 defer lt.indexSetMtx.RUnlock() 84 85 // TODO(owen-d): refactor? Uploads mgr never has user indices, 86 // only common (multitenant) ones. 87 // iterate through both user and common index 88 for _, uid := range []string{userID, ""} { 89 idxSet, ok := lt.indexSet[uid] 90 if !ok { 91 continue 92 } 93 94 if err := idxSet.ForEach(callback); err != nil { 95 return err 96 } 97 } 98 return nil 99 } 100 101 // Upload uploads the index to object storage. 102 func (lt *table) Upload(ctx context.Context) error { 103 lt.indexSetMtx.RLock() 104 defer lt.indexSetMtx.RUnlock() 105 106 for _, indexSet := range lt.indexSet { 107 if err := indexSet.Upload(ctx); err != nil { 108 return err 109 } 110 } 111 112 return nil 113 } 114 115 // Cleanup removes indexes which are already uploaded and have been retained for period longer than indexRetainPeriod since they were uploaded. 116 func (lt *table) Cleanup(indexRetainPeriod time.Duration) error { 117 lt.indexSetMtx.RLock() 118 defer lt.indexSetMtx.RUnlock() 119 120 for _, indexSet := range lt.indexSet { 121 if err := indexSet.Cleanup(indexRetainPeriod); err != nil { 122 return err 123 } 124 } 125 126 return nil 127 } 128 129 // Stop closes all the open dbs. 130 func (lt *table) Stop() { 131 lt.indexSetMtx.Lock() 132 defer lt.indexSetMtx.Unlock() 133 134 for _, indexSet := range lt.indexSet { 135 indexSet.Close() 136 } 137 } 138 139 func loggerWithUserID(logger log.Logger, userID string) log.Logger { 140 if userID == "" { 141 return logger 142 } 143 144 return log.With(logger, "user-id", userID) 145 }