diff --git a/flock_test.go b/flock_test.go index 25fe25d..7f8869f 100644 --- a/flock_test.go +++ b/flock_test.go @@ -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) { @@ -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) } diff --git a/main.go b/main.go index c31941a..4f89e4a 100644 --- a/main.go +++ b/main.go @@ -4,14 +4,14 @@ 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 @@ -19,10 +19,11 @@ type ( 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"` } ) @@ -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), @@ -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() @@ -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)