github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/tools/blocksconvert/plan_file.go (about) 1 package blocksconvert 2 3 import ( 4 "compress/gzip" 5 "fmt" 6 "io" 7 "regexp" 8 "strconv" 9 "strings" 10 "time" 11 12 "github.com/golang/snappy" 13 ) 14 15 // Plan file describes which series must be included in a block for given user and day. 16 // It consists of JSON objects, each written on its own line. 17 // Plan file starts with single header, many plan entries and single footer. 18 19 type PlanEntry struct { 20 // Header 21 User string `json:"user,omitempty"` 22 DayIndex int `json:"day_index,omitempty"` 23 24 // Entries 25 SeriesID string `json:"sid,omitempty"` 26 Chunks []string `json:"cs,omitempty"` 27 28 // Footer 29 Complete bool `json:"complete,omitempty"` 30 } 31 32 func (pe *PlanEntry) Reset() { 33 *pe = PlanEntry{} 34 } 35 36 // Returns true and "base name" or false and empty string. 37 func IsPlanFilename(name string) (bool, string) { 38 switch { 39 case strings.HasSuffix(name, ".plan.gz"): 40 return true, name[:len(name)-len(".plan.gz")] 41 42 case strings.HasSuffix(name, ".plan.snappy"): 43 return true, name[:len(name)-len(".plan.snappy")] 44 45 case strings.HasSuffix(name, ".plan"): 46 return true, name[:len(name)-len(".plan")] 47 } 48 49 return false, "" 50 } 51 52 func PreparePlanFileReader(planFile string, in io.Reader) (io.Reader, error) { 53 switch { 54 case strings.HasSuffix(planFile, ".snappy"): 55 return snappy.NewReader(in), nil 56 57 case strings.HasSuffix(planFile, ".gz"): 58 return gzip.NewReader(in) 59 } 60 61 return in, nil 62 } 63 64 func StartingFilename(planBaseName string, t time.Time) string { 65 return fmt.Sprintf("%s.starting.%d", planBaseName, t.Unix()) 66 } 67 68 func ProgressFilename(planBaseName string, t time.Time) string { 69 return fmt.Sprintf("%s.inprogress.%d", planBaseName, t.Unix()) 70 } 71 72 var progress = regexp.MustCompile(`^(.+)\.(starting|progress|inprogress)\.(\d+)$`) 73 74 func IsProgressFilename(name string) (bool, string, time.Time) { 75 m := progress.FindStringSubmatch(name) 76 if len(m) == 0 { 77 return false, "", time.Time{} 78 } 79 80 ts, err := strconv.ParseInt(m[3], 10, 64) 81 if err != nil { 82 return false, "", time.Time{} 83 } 84 85 return true, m[1], time.Unix(ts, 0) 86 } 87 88 func FinishedFilename(planBaseName string, id string) string { 89 return fmt.Sprintf("%s.finished.%s", planBaseName, id) 90 } 91 92 var finished = regexp.MustCompile(`^(.+)\.finished\.([a-zA-Z0-9]+)$`) 93 94 func IsFinishedFilename(name string) (bool, string, string) { 95 m := finished.FindStringSubmatch(name) 96 if len(m) == 0 { 97 return false, "", "" 98 } 99 100 return true, m[1], m[2] 101 } 102 103 func ErrorFilename(planBaseName string) string { 104 return planBaseName + ".error" 105 } 106 107 func IsErrorFilename(name string) (bool, string) { 108 if strings.HasSuffix(name, ".error") { 109 return true, name[:len(name)-len(".error")] 110 } 111 return false, "" 112 }