github.com/cs3org/reva/v2@v2.27.7/pkg/storage/fs/posix/tree/gpfsfilauditloggingwatcher.go (about)

     1  // Copyright 2018-2024 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package tree
    20  
    21  import (
    22  	"bufio"
    23  	"encoding/json"
    24  	"io"
    25  	"os"
    26  	"strconv"
    27  	"time"
    28  
    29  	"github.com/rs/zerolog"
    30  )
    31  
    32  type GpfsFileAuditLoggingWatcher struct {
    33  	tree *Tree
    34  	log  *zerolog.Logger
    35  }
    36  
    37  type lwe struct {
    38  	Event        string
    39  	Path         string
    40  	BytesWritten string
    41  }
    42  
    43  func NewGpfsFileAuditLoggingWatcher(tree *Tree, auditLogFile string, log *zerolog.Logger) (*GpfsFileAuditLoggingWatcher, error) {
    44  	w := &GpfsFileAuditLoggingWatcher{
    45  		tree: tree,
    46  		log:  log,
    47  	}
    48  
    49  	_, err := os.Stat(auditLogFile)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	return w, nil
    55  }
    56  
    57  func (w *GpfsFileAuditLoggingWatcher) Watch(path string) {
    58  start:
    59  	file, err := os.Open(path)
    60  	if err != nil {
    61  		// try again later
    62  		time.Sleep(5 * time.Second)
    63  		goto start
    64  	}
    65  	defer file.Close()
    66  
    67  	// Seek to the end of the file
    68  	_, err = file.Seek(0, io.SeekEnd)
    69  	if err != nil {
    70  		time.Sleep(5 * time.Second)
    71  		goto start
    72  	}
    73  
    74  	reader := bufio.NewReader(file)
    75  	ev := &lwe{}
    76  	for {
    77  		line, err := reader.ReadString('\n')
    78  		switch err {
    79  		case nil:
    80  			err := json.Unmarshal([]byte(line), ev)
    81  			if err != nil {
    82  				w.log.Error().Err(err).Str("line", line).Msg("error unmarshalling line")
    83  				continue
    84  			}
    85  			if isLockFile(ev.Path) || isTrash(ev.Path) || w.tree.isUpload(ev.Path) {
    86  				continue
    87  			}
    88  			go func() {
    89  				switch ev.Event {
    90  				case "CREATE":
    91  					err = w.tree.Scan(ev.Path, ActionCreate, false)
    92  				case "CLOSE":
    93  					var bytesWritten int
    94  					bytesWritten, err = strconv.Atoi(ev.BytesWritten)
    95  					if err == nil && bytesWritten > 0 {
    96  						err = w.tree.Scan(ev.Path, ActionUpdate, false)
    97  					}
    98  				case "RENAME":
    99  					err = w.tree.Scan(ev.Path, ActionMove, false)
   100  					if warmupErr := w.tree.WarmupIDCache(ev.Path, false, false); warmupErr != nil {
   101  						w.log.Error().Err(warmupErr).Str("path", ev.Path).Msg("error warming up id cache")
   102  					}
   103  				}
   104  				if err != nil {
   105  					w.log.Error().Err(err).Str("line", line).Msg("error unmarshalling line")
   106  				}
   107  			}()
   108  
   109  		case io.EOF:
   110  			time.Sleep(1 * time.Second)
   111  		default:
   112  			time.Sleep(5 * time.Second)
   113  			goto start
   114  		}
   115  	}
   116  }