100 lines
2.9 KiB
Go
100 lines
2.9 KiB
Go
|
// Licensed to Elasticsearch B.V. under one or more contributor
|
||
|
// license agreements. See the NOTICE file distributed with
|
||
|
// this work for additional information regarding copyright
|
||
|
// ownership. Elasticsearch B.V. licenses this file to you under
|
||
|
// the Apache License, Version 2.0 (the "License"); you may
|
||
|
// not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing,
|
||
|
// software distributed under the License is distributed on an
|
||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
// KIND, either express or implied. See the License for the
|
||
|
// specific language governing permissions and limitations
|
||
|
// under the License.
|
||
|
|
||
|
package file
|
||
|
|
||
|
import (
|
||
|
"os"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"github.com/mitchellh/hashstructure"
|
||
|
|
||
|
"github.com/elastic/beats/libbeat/common/file"
|
||
|
)
|
||
|
|
||
|
// State is used to communicate the reading state of a file
|
||
|
type State struct {
|
||
|
Id string `json:"-"` // local unique id to make comparison more efficient
|
||
|
Finished bool `json:"-"` // harvester state
|
||
|
Fileinfo os.FileInfo `json:"-"` // the file info
|
||
|
Source string `json:"source"`
|
||
|
Offset int64 `json:"offset"`
|
||
|
Timestamp time.Time `json:"timestamp"`
|
||
|
TTL time.Duration `json:"ttl"`
|
||
|
Type string `json:"type"`
|
||
|
Meta map[string]string `json:"meta"`
|
||
|
FileStateOS file.StateOS
|
||
|
}
|
||
|
|
||
|
// NewState creates a new file state
|
||
|
func NewState(fileInfo os.FileInfo, path string, t string, meta map[string]string) State {
|
||
|
if len(meta) == 0 {
|
||
|
meta = nil
|
||
|
}
|
||
|
return State{
|
||
|
Fileinfo: fileInfo,
|
||
|
Source: path,
|
||
|
Finished: false,
|
||
|
FileStateOS: file.GetOSState(fileInfo),
|
||
|
Timestamp: time.Now(),
|
||
|
TTL: -1, // By default, state does have an infinite ttl
|
||
|
Type: t,
|
||
|
Meta: meta,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ID returns a unique id for the state as a string
|
||
|
func (s *State) ID() string {
|
||
|
// Generate id on first request. This is needed as id is not set when converting back from json
|
||
|
if s.Id == "" {
|
||
|
if len(s.Meta) == 0 {
|
||
|
s.Id = s.FileStateOS.String()
|
||
|
} else {
|
||
|
hashValue, _ := hashstructure.Hash(s.Meta, nil)
|
||
|
var hashBuf [17]byte
|
||
|
hash := strconv.AppendUint(hashBuf[:0], hashValue, 16)
|
||
|
hash = append(hash, '-')
|
||
|
|
||
|
fileID := s.FileStateOS.String()
|
||
|
|
||
|
var b strings.Builder
|
||
|
b.Grow(len(hash) + len(fileID))
|
||
|
b.Write(hash)
|
||
|
b.WriteString(fileID)
|
||
|
|
||
|
s.Id = b.String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return s.Id
|
||
|
}
|
||
|
|
||
|
// IsEqual compares the state to an other state supporting stringer based on the unique string
|
||
|
func (s *State) IsEqual(c *State) bool {
|
||
|
return s.ID() == c.ID()
|
||
|
}
|
||
|
|
||
|
// IsEmpty returns true if the state is empty
|
||
|
func (s *State) IsEmpty() bool {
|
||
|
return s.FileStateOS == file.StateOS{} &&
|
||
|
s.Source == "" &&
|
||
|
len(s.Meta) == 0 &&
|
||
|
s.Timestamp.IsZero()
|
||
|
}
|