diff --git a/pkg/blobstore/Makefile b/pkg/blobstore/Makefile index db07d2f..3eba753 100644 --- a/pkg/blobstore/Makefile +++ b/pkg/blobstore/Makefile @@ -6,9 +6,9 @@ GOFILES = \ blobreader.go ifeq ($(GOOS),windows) -GOFILES += pid_windows.go +GOFILES += lock_windows.go else -GOFILES += pid_unix.go +GOFILES += lock_unix.go endif include $(GOROOT)/src/Make.pkg diff --git a/pkg/blobstore/lock_unix.go b/pkg/blobstore/lock_unix.go new file mode 100644 index 0000000..32ce0d2 --- /dev/null +++ b/pkg/blobstore/lock_unix.go @@ -0,0 +1,73 @@ +// Copyright (c) 2011 The Grumble Authors +// The use of this source code is goverened by a BSD-style +// license that can be found in the LICENSE-file. + +package blobstore + +import ( + "os" + "path/filepath" + "io/ioutil" + "strconv" + "syscall" +) + +// Acquire lockfile at path. +func AcquireLockFile(path string) os.Error { + dir, fn := filepath.Split(path) + lockfn := filepath.Join(dir, fn) + + lockfile, err := os.OpenFile(lockfn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) + if e, ok := err.(*os.PathError); ok && e.Error == os.EEXIST { + content, err := ioutil.ReadFile(lockfn) + if err != nil { + return err + } + + pid, err := strconv.Atoi(string(content)) + if err == nil { + if syscall.Kill(pid, 0) == 0 { + return ErrLocked + } + } + + lockfile, err = ioutil.TempFile(dir, "lock") + if err != nil { + return err + } + + _, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid())) + if err != nil { + lockfile.Close() + return ErrLockAcquirement + } + + curfn := lockfile.Name() + + err = lockfile.Close() + if err != nil { + return err + } + + err = os.Rename(curfn, lockfn) + if err != nil { + os.Remove(curfn) + return ErrLockAcquirement + } + } else if err != nil { + return err + } else { + _, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid())) + if err != nil { + return err + } + lockfile.Close() + } + + return nil +} + +// Release lockfile at path. +func ReleaseLockFile(path string) os.Error { + return os.Remove(path) +} diff --git a/pkg/blobstore/lock_windows.go b/pkg/blobstore/lock_windows.go new file mode 100644 index 0000000..028d790 --- /dev/null +++ b/pkg/blobstore/lock_windows.go @@ -0,0 +1,29 @@ +// Copyright (c) 2011 The Grumble Authors +// The use of this source code is goverened by a BSD-style +// license that can be found in the LICENSE-file. + +package blobstore + +import ( + "os" + "syscall" +) + +const ( + FILE_FLAG_DELETE_ON_CLOSE = 0x04000000 +) + +// Acquire a lockfile at path. +func AcquireLockFile(path string) os.Error { + handle, _ := syscall.CreateFile(syscall.StringToUTF16Ptr(path), syscall.GENERIC_WRITE, 0, nil, syscall.CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0) + if handle < 0 { + return ErrLocked + } + return nil +} + +// Release the lockfile at path. +func ReleaseLockFile(path string) os.Error { + // No-op because we use FLAG_DELETE_ON_CLOSE. + return nil +} diff --git a/pkg/blobstore/pid_unix.go b/pkg/blobstore/pid_unix.go deleted file mode 100644 index a4fcc53..0000000 --- a/pkg/blobstore/pid_unix.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2011 The Grumble Authors -// The use of this source code is goverened by a BSD-style -// license that can be found in the LICENSE-file. - -package blobstore - -import ( - "syscall" -) - -func getPid() uint64 { - return uint64(syscall.Getpid()) -} - -func pidRunning(pid uint64) bool { - return syscall.Kill(int(pid), 0) == 0 -} diff --git a/pkg/blobstore/pid_windows.go b/pkg/blobstore/pid_windows.go deleted file mode 100644 index 043010f..0000000 --- a/pkg/blobstore/pid_windows.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2011 The Grumble Authors -// The use of this source code is goverened by a BSD-style -// license that can be found in the LICENSE-file. - -package blobstore - -import ( - "syscall" -) - -func getPid() uint64 { - handle, _ := syscall.GetCurrentProcess() - return uint64(handle) -} - -func pidRunning(pid uint64) bool { - var status uint32 - syscall.GetExitCodeProcess(uint32(pid), &status) - return status == 259 // STILL_ACTIVE -}