2017-10-27 9 views
1

現在、httpサーバを作成しています。これは、フォルダ内のすべてのファイルに対して実行する必要があります。 1つのリクエストでファイルを書き込むことができます。別のリクエストで同時にファイルを読み取ることができるので、ファイルをロックする必要があります。これは書き込み可能です。ルーチンでは、それはファイルを読み込みます、私はちょうどロックされているファイルをスキップしたいです。 これを行うには、rubyistまたはnightlyoneのようなlocklibraryを使用したいと思います。移動中のFcntlが機能しない

問題は、私はそれらを動作させることができなかったので、私はsyscall.FcntlFlock()関数を自分自身で呼び出すようになり、期待したように動作しませんでした。
このプログラムは遊び場がUNIXベースのシステム上に存在しないで実行すると思われる原因となり、ゴー遊び場では動作しません(syscall.FcntlFlockが定義されていない)

動作しませんでしコード:

func main() { 
    time.Sleep(time.Second) 

    file, err := os.Open("lockfiletest.lock") 
    if err != nil { 
     log.Printf("error opening file2: %s", err) 
     return 
    } 
    defer file.Close() 

    flockT := syscall.Flock_t{ 
     Type: syscall.F_WRLCK, 
     Whence: io.SeekStart, 
     Start: 0, 
     Len: 0, 
    } 
    err = syscall.FcntlFlock(file.Fd(), syscall.F_SETLK, &flockT) 
    if err != nil { 
     log.Printf("error locking file2: %s", err) 
     return 
    } 

    log.Println("lock2 accessed") 

    time.Sleep(time.Second * 5) 

    log.Println("func2 finished") 

    time.Sleep(time.Second * 15) 
} 

コンソール出力:

2017/10/28 00:18:12 error locking file2: bad file descriptor 
Process finished with exit code 0 

私が間違っているのか?システムコールは壊れていますか?
私もCでそれを試して、それは正常に動作します。
このプログラムをGo1.8.3でテストし、ubuntu16.04のGo1.9.1

PS:このプログラムもWindowsで実行する必要があるため、FcntlLockを実装するだけでは不十分です。


また、sync.RWMutexを使用しているので、fileLockではなくMutexでロックされています。それはまさに私が望むものではありません。ロックされているファイルをスキップし、ミューテックスがロックされるまで待たないようにしたいからです。

答えて

0

touch lockfiletest.lockでファイルを作成すると、ファイルの内容はなくなります。プログラムはエラー:error locking file2: bad file descriptorで失敗します。

$ rm -f lockfiletest.lock 
$ touch lockfiletest.lock 
$ go run lockfiletest.go 
2017/10/27 21:17:27 error locking file2: bad file descriptor 

ファイルを開いて、TestFcntlFlockとよく似たファイルを変更しました。例えば

$ uname -s 
Linux 
~/go/src/syscall$ $ go test -v -run=TestFcntlFlock syscall_unix_test.go 
=== RUN TestFcntlFlock 
--- PASS: TestFcntlFlock (0.01s) 
PASS 
ok  syscall 0.008s 
~/go/src/syscall$ 

package main 

import (
    "io" 
    "log" 
    "os" 
    "syscall" 
    "time" 
) 

func main() { 
    time.Sleep(time.Second) 

    name := "lockfiletest.lock" 
    file, err := os.OpenFile(name, syscall.O_CREAT|syscall.O_RDWR|syscall.O_CLOEXEC, 0666) 
    if err != nil { 
     log.Printf("error opening file: %s", err) 
     return 
    } 
    defer file.Close() 

    flockT := syscall.Flock_t{ 
     Type: syscall.F_WRLCK, 
     Whence: io.SeekStart, 
     Start: 0, 
     Len: 0, 
    } 
    err = syscall.FcntlFlock(file.Fd(), syscall.F_SETLK, &flockT) 
    if err != nil { 
     log.Printf("error locking file: %s", err) 
     return 
    } 

    log.Println("lock2 accessed") 

    time.Sleep(time.Second * 5) 

    log.Println("func2 finished") 

    time.Sleep(time.Second * 15) 
} 

出力:

$ rm -f lockfiletest.lock 
$ touch lockfiletest.lock 
$ go run lockfiletest.go 
2017/10/27 21:21:56 lock2 accessed 
2017/10/27 21:22:01 func2 finished 
$ rm -f lockfiletest.lock 
$ go run lockfiletest.go 
2017/10/27 21:22:25 lock2 accessed 
2017/10/27 21:22:30 func2 finished 
$ go run lockfiletest.go 
2017/10/27 21:25:40 lock2 accessed 
2017/10/27 21:25:45 func2 finished 
$