blob: 87cb3dd5dc9f159561991ca803b8b85799168103 [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"sync"
"github.com/golang/groupcache/lru"
"v.io/v23/context"
"v.io/v23/verror"
"v.io/x/ref/services/allocator"
)
var (
// instanceCache maps email to list of instances.
instanceCache *lru.Cache
instanceCacheMutex sync.Mutex
)
func checkOwnerOfInstance(ctx *context.T, email, handle string) error {
return checkOwner(ctx, email, func(instance allocator.Instance) bool {
return instance.Handle == handle
})
}
func checkOwnerOfMountName(ctx *context.T, email, mName string) error {
return checkOwner(ctx, email, func(instance allocator.Instance) bool {
return instance.MountName == mName
})
}
// checkOwner returns the mount name of the instance if the given email has
// access to it, or an error otherwise.
func checkOwner(ctx *context.T, email string, predicate func(allocator.Instance) bool) error {
instanceCacheMutex.Lock()
if instanceCache == nil {
instanceCache = lru.New(maxInstancesFlag)
}
v, ok := instanceCache.Get(email)
instanceCacheMutex.Unlock()
if ok {
if instances, ok := v.([]allocator.Instance); !ok {
// Our cache code is broken. Proceed to refresh entry.
ctx.Errorf("invalid cache entry type %T for email %v", v, email)
} else {
for _, instance := range instances {
if predicate(instance) {
return nil
}
}
}
}
instances, err := serverInstances(ctx, email)
if err != nil {
return err
}
// Regardless of whether an instance matches or not, update the email's
// cache entry since the user is using the system.
instanceCacheMutex.Lock()
instanceCache.Add(email, instances)
instanceCacheMutex.Unlock()
for _, instance := range instances {
if predicate(instance) {
return nil
}
}
return verror.New(verror.ErrNoExistOrNoAccess, nil)
}