github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/query/pqs/meta/pqsmeta.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 pqsmeta
    18  
    19  import (
    20  	"encoding/json"
    21  	"os"
    22  	"path"
    23  	"sync"
    24  
    25  	"github.com/siglens/siglens/pkg/config"
    26  	log "github.com/sirupsen/logrus"
    27  )
    28  
    29  var allEmptyPersistentQueryResultsLock sync.RWMutex
    30  
    31  func init() {
    32  	allEmptyPersistentQueryResultsLock = sync.RWMutex{}
    33  }
    34  
    35  func GetAllEmptySegmentsForPqid(pqid string) (map[string]bool, error) {
    36  	fileName := getPqmetaFilename(pqid)
    37  	return getAllEmptyPQSToMap(fileName)
    38  }
    39  
    40  func getAllEmptyPQSToMap(emptyPQSFilename string) (map[string]bool, error) {
    41  	allEmptyPQS := make(map[string]bool)
    42  	allEmptyPersistentQueryResultsLock.RLock()
    43  	defer allEmptyPersistentQueryResultsLock.RUnlock()
    44  	fd, err := os.OpenFile(emptyPQSFilename, os.O_CREATE|os.O_RDONLY, 0764)
    45  	if err != nil {
    46  		if os.IsNotExist(err) {
    47  			return map[string]bool{}, nil
    48  		}
    49  		log.Errorf("getAllEmptyPQSToMap: Cannot read persistent query meta File = %v, err= %v", emptyPQSFilename, err)
    50  		return nil, err
    51  	}
    52  	defer fd.Close()
    53  
    54  	fileInfo, err := fd.Stat()
    55  	if err != nil {
    56  		log.Errorf("getAllEmptyPQSToMap: Cannot stat filename file=%v, =%v", emptyPQSFilename, err)
    57  		return nil, err
    58  	}
    59  	if fileInfo.Size() == 0 {
    60  		return allEmptyPQS, nil
    61  	}
    62  
    63  	err = json.NewDecoder(fd).Decode(&allEmptyPQS)
    64  	if err != nil {
    65  		log.Errorf("getAllEmptyPQSToMap: Cannot unmarshal data, err =%v", err)
    66  		return nil, err
    67  	}
    68  
    69  	return allEmptyPQS, nil
    70  }
    71  
    72  func getPqmetaDirectory() string {
    73  	dirName := config.GetDataPath() + "querynodes" + "/" + config.GetHostID() + "/" + "pqmeta"
    74  	return dirName
    75  }
    76  
    77  func getPqmetaFilename(pqid string) string {
    78  	dirName := getPqmetaDirectory()
    79  	fileName := dirName + "/" + pqid + ".meta"
    80  	return fileName
    81  }
    82  
    83  func AddEmptyResults(pqid string, segKey string, virtualTableName string) {
    84  	dirName := getPqmetaDirectory()
    85  	if _, err := os.Stat(dirName); os.IsNotExist(err) {
    86  		err := os.MkdirAll(dirName, os.FileMode(0764))
    87  		if err != nil {
    88  			log.Errorf("Failed to create directory at %s: %v", dirName, err)
    89  		}
    90  	}
    91  	fileName := getPqmetaFilename(pqid)
    92  	emptyPQS, err := getAllEmptyPQSToMap(fileName)
    93  	if err != nil {
    94  		log.Errorf("Failed to get empty PQS data from file at %s: %v", fileName, err)
    95  	}
    96  	if emptyPQS != nil {
    97  		emptyPQS[segKey] = true
    98  		writeEmptyPqsMapToFile(fileName, emptyPQS)
    99  	}
   100  }
   101  
   102  func writeEmptyPqsMapToFile(fileName string, emptyPqs map[string]bool) {
   103  	allEmptyPersistentQueryResultsLock.Lock()
   104  	defer allEmptyPersistentQueryResultsLock.Unlock()
   105  	fd, err := os.OpenFile(fileName, os.O_RDWR|os.O_TRUNC, 0764)
   106  	if err != nil {
   107  		log.Errorf("WriteEmptyPQS: Error opening file at fname=%v, err=%v", fileName, err)
   108  	}
   109  	jsonData, err := json.Marshal(emptyPqs)
   110  	if err != nil {
   111  		log.Errorf("WriteEmptyPQS: could not marshal data, err=%v", err)
   112  	}
   113  	_, err = fd.Write(jsonData)
   114  	if err != nil {
   115  		log.Errorf("WriteEmptyPQS: buf write failed fname=%v, err=%v", fileName, err)
   116  	}
   117  
   118  	err = fd.Sync()
   119  	if err != nil {
   120  		log.Errorf("WriteEmptyPQS: sync failed filename=%v,err=%v", fileName, err)
   121  	}
   122  	fd.Close()
   123  }
   124  
   125  func removePqmrFilesAndDirectory(pqid string) error {
   126  	workingDirectory, err := os.Getwd()
   127  	if err != nil {
   128  		log.Errorf("Error fetching current workingDirectory")
   129  		return err
   130  	}
   131  	pqFname := workingDirectory + "/" + getPqmetaFilename(pqid)
   132  	err = os.Remove(pqFname)
   133  	if err != nil {
   134  		log.Errorf("Cannot delete file at %v", err)
   135  		return err
   136  	}
   137  	pqMetaDirectory := path.Dir(pqFname)
   138  	files, err := os.ReadDir(pqMetaDirectory)
   139  	if err != nil {
   140  		log.Errorf("Cannot PQMR directory at %v", pqMetaDirectory)
   141  		return err
   142  	}
   143  	if len(files) == 0 {
   144  		err := os.Remove(pqMetaDirectory)
   145  		if err != nil {
   146  			log.Errorf("Error deleting Pqmr directory at %v", pqMetaDirectory)
   147  			return err
   148  		}
   149  	}
   150  	return nil
   151  }
   152  
   153  func DeleteSegmentFromPqid(pqid string, segKey string) {
   154  	pqFname := getPqmetaFilename(pqid)
   155  	emptyPQS, err := getAllEmptyPQSToMap(pqFname)
   156  	if err != nil {
   157  		log.Errorf("DeleteSegmentFromPqid: Failed to get empty PQS data from file at %s: %v", pqFname, err)
   158  	}
   159  	delete(emptyPQS, segKey)
   160  	if len(emptyPQS) == 0 {
   161  		err := removePqmrFilesAndDirectory(pqid)
   162  		if err != nil {
   163  			log.Errorf("DeleteSegmentFromPqid: Error removing segKey %v from %v pqid", segKey, pqid)
   164  		}
   165  		return
   166  	}
   167  	writeEmptyPqsMapToFile(pqFname, emptyPQS)
   168  }