// Copyright 2025 Cloudbase Solutions SRL // // Licensed 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 locking import ( "fmt" "log/slog" "runtime" "sync" ) var locker Locker var lockerMux = sync.Mutex{} func TryLock(key, identifier string) (ok bool) { if locker == nil { panic("no locker is registered") } _, filename, line, _ := runtime.Caller(1) slog.Debug("attempting to try lock", "key", key, "identifier", identifier, "caller", fmt.Sprintf("%s:%d", filename, line)) defer slog.Debug("try lock returned", "key", key, "identifier", identifier, "locked", ok, "caller", fmt.Sprintf("%s:%d", filename, line)) ok = locker.TryLock(key, identifier) return ok } func Lock(key, identifier string) { if locker == nil { panic("no locker is registered") } _, filename, line, _ := runtime.Caller(1) slog.Debug("attempting to lock", "key", key, "identifier", identifier, "caller", fmt.Sprintf("%s:%d", filename, line)) defer slog.Debug("lock acquired", "key", key, "identifier", identifier, "caller", fmt.Sprintf("%s:%d", filename, line)) locker.Lock(key, identifier) } func Unlock(key string, remove bool) { if locker == nil { panic("no locker is registered") } _, filename, line, _ := runtime.Caller(1) slog.Debug("attempting to unlock", "key", key, "remove", remove, "caller", fmt.Sprintf("%s:%d", filename, line)) defer slog.Debug("unlock completed", "key", key, "remove", remove, "caller", fmt.Sprintf("%s:%d", filename, line)) locker.Unlock(key, remove) } func LockedBy(key string) (string, bool) { if locker == nil { panic("no locker is registered") } return locker.LockedBy(key) } func Delete(key string) { if locker == nil { panic("no locker is registered") } locker.Delete(key) } func RegisterLocker(lock Locker) error { lockerMux.Lock() defer lockerMux.Unlock() if locker != nil { return fmt.Errorf("locker already registered") } locker = lock return nil }