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  }