github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/writer/suffix/suffix.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 suffix
    18  
    19  import (
    20  	"bufio"
    21  	"encoding/json"
    22  	"os"
    23  	"path"
    24  	"strings"
    25  
    26  	"github.com/siglens/siglens/pkg/config"
    27  	log "github.com/sirupsen/logrus"
    28  )
    29  
    30  type SuffixEntry struct {
    31  	Suffix uint64 `json:"suffix"`
    32  }
    33  
    34  func getSuffixFromFile(fileName string) (uint64, error) {
    35  	f, err := os.OpenFile(fileName, os.O_RDWR, 0764)
    36  	if os.IsNotExist(err) {
    37  		err := os.MkdirAll(path.Dir(fileName), 0764)
    38  		if err != nil {
    39  			return 0, err
    40  		}
    41  		f, err := os.Create(fileName)
    42  		if err != nil {
    43  			return 0, err
    44  		}
    45  		defer f.Close()
    46  		if err != nil {
    47  			return 0, err
    48  		}
    49  
    50  		initialSuffix := &SuffixEntry{Suffix: 1}
    51  		raw, err := json.Marshal(initialSuffix)
    52  		if err != nil {
    53  			return 0, err
    54  		}
    55  		_, err = f.Write(raw)
    56  		if err != nil {
    57  			return 0, err
    58  		}
    59  		_, err = f.WriteString("\n")
    60  		if err != nil {
    61  			return 0, err
    62  		}
    63  
    64  		err = f.Sync()
    65  		if err != nil {
    66  			return 0, err
    67  		}
    68  		return 0, err
    69  	}
    70  	scanner := bufio.NewScanner(f)
    71  	scanner.Scan()
    72  	rawbytes := scanner.Bytes()
    73  	var suffxE SuffixEntry
    74  	err = json.Unmarshal(rawbytes, &suffxE)
    75  	if err != nil {
    76  		log.Errorf("GetSuffix: Cannot unmarshal data = %v, err= %v", string(rawbytes), err)
    77  		return 0, err
    78  	}
    79  	retVal := suffxE.Suffix
    80  	suffxE.Suffix++
    81  	raw, err := json.Marshal(suffxE)
    82  	if err != nil {
    83  		return 0, err
    84  	}
    85  	err = f.Truncate(0)
    86  	if err != nil {
    87  		return 0, err
    88  	}
    89  	_, err = f.Seek(0, 0)
    90  	if err != nil {
    91  		return 0, err
    92  	}
    93  	_, err = f.Write(raw)
    94  	if err != nil {
    95  		return 0, err
    96  	}
    97  	_, err = f.WriteString("\n")
    98  	if err != nil {
    99  		return 0, err
   100  	}
   101  
   102  	return retVal, nil
   103  }
   104  
   105  /*
   106  Get the next suffix for the given streamid and table combination
   107  
   108  Internally, creates & reads the suffix file persist suffixes
   109  */
   110  func GetSuffix(streamid, table string) (uint64, error) {
   111  
   112  	fileName := getSuffixFile(table, streamid)
   113  	nextSuffix, err := getSuffixFromFile(fileName)
   114  	if err != nil {
   115  		log.Errorf("GetSuffix: Error generating suffix for streamid %v. Err: %v", streamid, err)
   116  	}
   117  	return nextSuffix, err
   118  }
   119  
   120  func getSuffixFile(virtualTable string, streamId string) string {
   121  	var sb strings.Builder
   122  	sb.WriteString(config.GetDataPath())
   123  	sb.WriteString(config.GetHostID())
   124  	sb.WriteString("/suffix/")
   125  	sb.WriteString(virtualTable)
   126  	sb.WriteString("/")
   127  	sb.WriteString(streamId)
   128  	sb.WriteString(".suffix")
   129  	return sb.String()
   130  }