| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package filelock |
| |
| import ( |
| "context" |
| "time" |
| ) |
| |
| const ( |
| // DefaultLockTimeout is the default lock timeout. |
| DefaultLockTimeout = 3 * time.Second |
| // DefaultLockRetryDelay is the default lock retry delay. |
| DefaultLockRetryDelay = 200 * time.Millisecond |
| ) |
| |
| // Unlocker unlocks a file lock. |
| type Unlocker interface { |
| Unlock() error |
| } |
| |
| // Lock locks a file lock. |
| // |
| // Use in cases where you need a lock for a specific system file, such as in testing, |
| // otherwise use a Locker to manage your file locks. |
| func Lock(ctx context.Context, filePath string, options ...LockOption) (Unlocker, error) { |
| return lock(ctx, filePath, options...) |
| } |
| |
| // RLock read-locks a file lock. |
| // |
| // Use in cases where you need a lock for a specific system file, such as in testing, |
| // otherwise use a Locker to manage your file locks. |
| func RLock(ctx context.Context, filePath string, options ...LockOption) (Unlocker, error) { |
| return rlock(ctx, filePath, options...) |
| } |
| |
| // Locker provides file locks. |
| type Locker interface { |
| // Lock locks a file lock within the root directory of the Locker. |
| // |
| // The given path must be normalized and relative. |
| Lock(ctx context.Context, path string, options ...LockOption) (Unlocker, error) |
| // RLock read-locks a file lock within the root directory of the Locker. |
| // |
| // The given path must be normalized and relative. |
| RLock(ctx context.Context, path string, options ...LockOption) (Unlocker, error) |
| } |
| |
| // NewLocker returns a new Locker for the given root directory path. |
| // |
| // The root directory path should generally be a data directory path. |
| // The root directory must exist. |
| func NewLocker(rootDirPath string) (Locker, error) { |
| return newLocker(rootDirPath) |
| } |
| |
| // LockOption is an option for lock. |
| type LockOption func(*lockOptions) |
| |
| // LockWithTimeout returns a new LockOption that sets the lock timeout. |
| // |
| // Lock returns error if the lock cannot be acquired after this amount of time. |
| // If this is set to 0, the lock will never timeout. |
| func LockWithTimeout(timeout time.Duration) LockOption { |
| return func(lockOptions *lockOptions) { |
| lockOptions.timeout = timeout |
| } |
| } |
| |
| // LockWithRetryDelay returns a new LockOption that sets the lock retry delay. |
| // |
| // Lock will try to lock on this delay up until the lock timeout. |
| func LockWithRetryDelay(retryDelay time.Duration) LockOption { |
| return func(lockOptions *lockOptions) { |
| lockOptions.retryDelay = retryDelay |
| } |
| } |
| |
| // NewNopLocker returns a new no-op Locker. |
| func NewNopLocker() Locker { |
| return newNopLocker() |
| } |