LCOV - code coverage report
Current view: top level - pebble/vfs - file_lock_unix.go (source / functions) Hit Total Coverage
Test: 2024-03-14 08:16Z e6d0a420 - tests only.lcov Lines: 28 34 82.4 %
Date: 2024-03-14 08:16:28 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2014 The LevelDB-Go and Pebble Authors. All rights reserved. Use
       2             : // of this source code is governed by a BSD-style license that can be found in
       3             : // the LICENSE file.
       4             : 
       5             : //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
       6             : // +build darwin dragonfly freebsd linux netbsd openbsd solaris
       7             : 
       8             : package vfs
       9             : 
      10             : import (
      11             :         "io"
      12             :         "os"
      13             :         "sync"
      14             : 
      15             :         "github.com/cockroachdb/errors"
      16             :         "golang.org/x/sys/unix"
      17             : )
      18             : 
      19             : var lockedFiles struct {
      20             :         mu struct {
      21             :                 sync.Mutex
      22             :                 files map[string]bool
      23             :         }
      24             : }
      25             : 
      26             : // lockCloser hides all of an os.File's methods, except for Close.
      27             : type lockCloser struct {
      28             :         name string
      29             :         f    *os.File
      30             : }
      31             : 
      32           1 : func (l lockCloser) Close() error {
      33           1 :         lockedFiles.mu.Lock()
      34           1 :         defer lockedFiles.mu.Unlock()
      35           1 :         if !lockedFiles.mu.files[l.name] {
      36           0 :                 panic(errors.Errorf("lock file %q is not locked", l.name))
      37             :         }
      38           1 :         delete(lockedFiles.mu.files, l.name)
      39           1 : 
      40           1 :         return l.f.Close()
      41             : }
      42             : 
      43           1 : func (defaultFS) Lock(name string) (io.Closer, error) {
      44           1 :         lockedFiles.mu.Lock()
      45           1 :         defer lockedFiles.mu.Unlock()
      46           1 :         if lockedFiles.mu.files == nil {
      47           1 :                 lockedFiles.mu.files = map[string]bool{}
      48           1 :         }
      49           1 :         if lockedFiles.mu.files[name] {
      50           1 :                 return nil, errors.New("lock held by current process")
      51           1 :         }
      52             : 
      53           1 :         f, err := os.Create(name)
      54           1 :         if err != nil {
      55           0 :                 return nil, err
      56           0 :         }
      57           1 :         spec := unix.Flock_t{
      58           1 :                 Type:   unix.F_WRLCK,
      59           1 :                 Whence: io.SeekStart,
      60           1 :                 Start:  0,
      61           1 :                 Len:    0, // 0 means to lock the entire file.
      62           1 :                 Pid:    int32(os.Getpid()),
      63           1 :         }
      64           1 :         if err := unix.FcntlFlock(f.Fd(), unix.F_SETLK, &spec); err != nil {
      65           0 :                 f.Close()
      66           0 :                 return nil, err
      67           0 :         }
      68           1 :         lockedFiles.mu.files[name] = true
      69           1 :         return lockCloser{name, f}, nil
      70             : }

Generated by: LCOV version 1.14