github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/blob/blobStorage.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package blob 18 19 import ( 20 "fmt" 21 "sync" 22 "time" 23 24 "github.com/siglens/siglens/pkg/blob/local" 25 "github.com/siglens/siglens/pkg/blob/ssutils" 26 "github.com/siglens/siglens/pkg/hooks" 27 log "github.com/sirupsen/logrus" 28 ) 29 30 func InitBlobStore() error { 31 if hook := hooks.GlobalHooks.InitBlobStoreExtrasHook; hook != nil { 32 alreadyHandled, err := hook() 33 if alreadyHandled { 34 return err 35 } 36 } 37 38 return local.InitLocalStorage() 39 } 40 41 func UploadSegmentFiles(allFiles []string) error { 42 if hook := hooks.GlobalHooks.UploadSegmentFilesExtrasHook; hook != nil { 43 alreadyHandled, err := hook(allFiles) 44 if alreadyHandled { 45 return err 46 } 47 } 48 49 local.BulkAddSegSetFilesToLocal(allFiles) 50 return nil 51 } 52 53 func UploadIngestNodeDir() error { 54 if hook := hooks.GlobalHooks.UploadIngestNodeExtrasHook; hook != nil { 55 alreadyHandled, err := hook() 56 if alreadyHandled { 57 return err 58 } 59 } 60 61 return nil 62 } 63 64 func UploadQueryNodeDir() error { 65 if hook := hooks.GlobalHooks.UploadQueryNodeExtrasHook; hook != nil { 66 alreadyHandled, err := hook() 67 if alreadyHandled { 68 return err 69 } 70 } 71 72 return nil 73 } 74 75 func DeleteBlob(filepath string) error { 76 if hook := hooks.GlobalHooks.DeleteBlobExtrasHook; hook != nil { 77 alreadyHandled, err := hook(filepath) 78 if alreadyHandled { 79 return err 80 } 81 } 82 83 return local.DeleteLocal(filepath) 84 } 85 86 func DownloadAllIngestNodesDir() error { 87 if hook := hooks.GlobalHooks.DownloadAllIngestNodesDirExtrasHook; hook != nil { 88 alreadyHandled, err := hook() 89 if alreadyHandled { 90 return err 91 } 92 } 93 94 return nil 95 } 96 97 func DownloadAllQueryNodesDir() error { 98 if hook := hooks.GlobalHooks.DownloadAllQueryNodesDirExtrasHook; hook != nil { 99 alreadyHandled, err := hook() 100 if alreadyHandled { 101 return err 102 } 103 } 104 105 return nil 106 } 107 108 /* 109 To set all passed seg set files as in use to prevent being removed by localcleaner, set the inUseFlag to true otherwise false 110 Up to caller to call SetSegSetFilesAsNotInUse with same data after resouces are no longer needed 111 Returns an error if failed to download segment blob from S3 or mark any segSetFile as in use 112 */ 113 func DownloadSegmentBlob(fName string, inUseFlag bool) error { 114 if local.IsFilePresentOnLocal(fName) { 115 return nil 116 } 117 118 if hook := hooks.GlobalHooks.DownloadSegmentBlobExtrasHook; hook != nil { 119 alreadyHandled, err := hook(fName) 120 if alreadyHandled { 121 return err 122 } 123 } 124 125 size, _ := ssutils.GetFileSizeFromDisk(fName) 126 ssData := ssutils.NewSegSetData(fName, size) 127 local.AddSegSetFileToLocal(fName, ssData) 128 129 if inUseFlag { 130 err := local.SetBlobAsInUse(fName) 131 if err != nil { 132 log.Errorf("DownloadSegmentBlob: failed to set segSetFile %v as in use: %v", fName, err) 133 return err 134 } 135 } 136 return nil 137 } 138 139 // segFiles is a map with fileName as the key and colName as the corresponding value 140 func BulkDownloadSegmentBlob(segFiles map[string]string, inUseFlag bool) error { 141 var bulkDownloadWG sync.WaitGroup 142 var err error 143 sTime := time.Now() 144 for fileName := range segFiles { 145 bulkDownloadWG.Add(1) 146 go func(fName string) { 147 defer bulkDownloadWG.Done() 148 err = DownloadSegmentBlob(fName, inUseFlag) 149 if err != nil { 150 err = fmt.Errorf("BulkDownloadSegmentBlob: failed to download segsetfile %+v", fName) 151 return 152 } 153 }(fileName) 154 } 155 bulkDownloadWG.Wait() 156 log.Debugf("BulkDownloadSegmentBlob: downloaded %v segsetfiles in %v", len(segFiles), time.Since(sTime)) 157 return err 158 } 159 160 /* 161 Sets all passed seg set files as no longer in use so it can be removed by localcleaner 162 Returns an error if failed to mark any segSetFile as not in use 163 */ 164 func SetSegSetFilesAsNotInUse(files []string) error { 165 var retErr error 166 retErr = nil 167 for _, segSetFile := range files { 168 err := local.SetBlobAsNotInUse(segSetFile) 169 if err != nil { 170 log.Errorf("SetSegSetFilesAsNotInUse: failed to set segSetFile as not in use: %v", err) 171 retErr = err 172 continue 173 } 174 } 175 return retErr 176 } 177 178 /* 179 Sets all passed seg set files as no longer in use so it can be removed by localcleaner 180 Returns an error if failed to mark any segSetFile as not in use 181 */ 182 func SetBlobAsNotInUse(fName string) error { 183 err := local.SetBlobAsNotInUse(fName) 184 if err != nil { 185 log.Errorf("SetBlobAsNotInUse: failed to set segSetFile as not in use: %v", err) 186 return err 187 } 188 189 return nil 190 } 191 192 // Returns size of file. If file does not exit, returns 0 with no error. 193 func GetFileSize(filename string) uint64 { 194 size, exists := local.GetLocalFileSize(filename) 195 if exists { 196 return size 197 } 198 199 size, onLocal := ssutils.GetFileSizeFromDisk(filename) 200 if onLocal { 201 return size 202 } 203 204 if hook := hooks.GlobalHooks.GetFileSizeExtrasHook; hook != nil { 205 alreadyHandled, size := hook(filename) 206 if alreadyHandled { 207 return size 208 } 209 } 210 211 return 0 212 } 213 214 // For a given meta file, returns if it exists in blob store. 215 // The input should always be a file in the ingestnodes directory. Either segmetas or metrics metas 216 func DoesMetaFileExistInBlob(fName string) (bool, error) { 217 if hook := hooks.GlobalHooks.DoesMetaFileExistExtrasHook; hook != nil { 218 alreadyHandled, exists, err := hook(fName) 219 if alreadyHandled { 220 return exists, err 221 } 222 } 223 224 return false, nil 225 }