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  }