Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions flock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package flock
import (
"encoding/json"
"errors"
"testing"
"time"

"github.com/golang/mock/gomock"
"github.com/opensvc/locker"
mockLocker "github.com/opensvc/locker/mock_locker"
"github.com/stretchr/testify/assert"
"testing"
"time"
)

func setup(t *testing.T) (prov func(string) locker.Locker, lck *mockLocker.MockLocker) {
Expand Down Expand Up @@ -36,7 +37,7 @@ func TestLock(t *testing.T) {
err := lck.Lock(100*time.Millisecond, "intent1")
assert.Equal(t, nil, err)

found := meta{}
found := Meta{}
if err := json.Unmarshal(b, &found); err != nil {
t.Fatalf("expected written data : %+v\n", b)
}
Expand Down
47 changes: 32 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@ import (
"context"
"encoding/json"
"errors"
"github.com/opensvc/locker"
"io"
"os"
"time"

"github.com/opensvc/locker"
)

type (
// T wraps flock and dumps a json data in the lock file
// T wraps flock and dumps JSON data in the lock file
// hinting about what holds the lock.
T struct {
locker.Locker
Path string
sessionId string
}

meta struct {
PID int `json:"pid"`
Intent string `json:"intent"`
SessionID string `json:"session_id"`
Meta struct {
At time.Time `json:"at"`
PID int `json:"pid"`
Intent string `json:"intent"`
SessionID string `json:"session_id"`
}
)

Expand All @@ -32,7 +33,7 @@ var (
retryInterval = 500 * time.Millisecond
)

// New allocate a file lock struct from Locker provider.
// New allocate a file lock struct from the Locker provider.
func New(p string, sessionId string, lockP func(string) locker.Locker) *T {
return &T{
Locker: lockP(p),
Expand All @@ -41,11 +42,9 @@ func New(p string, sessionId string, lockP func(string) locker.Locker) *T {
}
}

//
// Lock acquires an exclusive file lock on the file and write a json
// Lock acquires an exclusive file lock on the file and writes a JSON
// formatted structure hinting who holds the lock and with what
// intention.
//
func (t *T) Lock(timeout time.Duration, intent string) (err error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
Expand All @@ -56,20 +55,38 @@ func (t *T) Lock(timeout time.Duration, intent string) (err error) {
}
return
}
err = t.writeMeta(t, intent)
err = t.writeMeta(intent)
return
}

func (t T) writeMeta(w io.Writer, intent string) error {
m := meta{
func (t *T) writeMeta(intent string) error {
m := Meta{
At: time.Now(),
PID: os.Getpid(),
Intent: intent,
SessionID: t.sessionId,
}
enc := json.NewEncoder(w)
enc := json.NewEncoder(t)
return enc.Encode(m)
}

func (t *T) Probe(intent string) (m Meta, err error) {
err = t.Lock(time.Second*0, intent)
if err != nil {
return
}
defer func() { _ = t.UnLock() }()
m, err = t.readMeta()
return
}

func (t *T) readMeta() (Meta, error) {
var m Meta
dec := json.NewDecoder(t)
err := dec.Decode(&m)
return m, err
}

// UnLock releases the file lock acquired by Lock.
func (t *T) UnLock() error {
_ = truncate(t.Path, 0)
Expand Down