// Copyright 2020 The gVisor Authors.
//
// 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 refsvfs2

import (
	"fmt"

	"gvisor.dev/gvisor/pkg/log"
	refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
	"gvisor.dev/gvisor/pkg/sync"
)

var (
	// liveObjects is a global map of reference-counted objects. Objects are
	// inserted when leak check is enabled, and they are removed when they are
	// destroyed. It is protected by liveObjectsMu.
	liveObjects   map[CheckedObject]struct{}
	liveObjectsMu sync.Mutex
)

// CheckedObject represents a reference-counted object with an informative
// leak detection message.
type CheckedObject interface {
	// RefType is the type of the reference-counted object.
	RefType() string

	// LeakMessage supplies a warning to be printed upon leak detection.
	LeakMessage() string

	// LogRefs indicates whether reference-related events should be logged.
	LogRefs() bool
}

func init() {
	liveObjects = make(map[CheckedObject]struct{})
}

// LeakCheckEnabled returns whether leak checking is enabled. The following
// functions should only be called if it returns true.
func LeakCheckEnabled() bool {
	return refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking
}

// leakCheckPanicEnabled returns whether DoLeakCheck() should panic when leaks
// are detected.
func leakCheckPanicEnabled() bool {
	return refs_vfs1.GetLeakMode() == refs_vfs1.LeaksPanic
}

// Register adds obj to the live object map.
func Register(obj CheckedObject) {
	if LeakCheckEnabled() {
		liveObjectsMu.Lock()
		if _, ok := liveObjects[obj]; ok {
			panic(fmt.Sprintf("Unexpected entry in leak checking map: reference %p already added", obj))
		}
		liveObjects[obj] = struct{}{}
		liveObjectsMu.Unlock()
		if LeakCheckEnabled() && obj.LogRefs() {
			logEvent(obj, "registered")
		}
	}
}

// Unregister removes obj from the live object map.
func Unregister(obj CheckedObject) {
	if LeakCheckEnabled() {
		liveObjectsMu.Lock()
		defer liveObjectsMu.Unlock()
		if _, ok := liveObjects[obj]; !ok {
			panic(fmt.Sprintf("Expected to find entry in leak checking map for reference %p", obj))
		}
		delete(liveObjects, obj)
		if LeakCheckEnabled() && obj.LogRefs() {
			logEvent(obj, "unregistered")
		}
	}
}

// LogIncRef logs a reference increment.
func LogIncRef(obj CheckedObject, refs int64) {
	if LeakCheckEnabled() && obj.LogRefs() {
		logEvent(obj, fmt.Sprintf("IncRef to %d", refs))
	}
}

// LogTryIncRef logs a successful TryIncRef call.
func LogTryIncRef(obj CheckedObject, refs int64) {
	if LeakCheckEnabled() && obj.LogRefs() {
		logEvent(obj, fmt.Sprintf("TryIncRef to %d", refs))
	}
}

// LogDecRef logs a reference decrement.
func LogDecRef(obj CheckedObject, refs int64) {
	if LeakCheckEnabled() && obj.LogRefs() {
		logEvent(obj, fmt.Sprintf("DecRef to %d", refs))
	}
}

// logEvent logs a message for the given reference-counted object.
//
// obj.LogRefs() should be checked before calling logEvent, in order to avoid
// calling any text processing needed to evaluate msg.
func logEvent(obj CheckedObject, msg string) {
	log.Infof("[%s %p] %s:\n%s", obj.RefType(), obj, msg, refs_vfs1.FormatStack(refs_vfs1.RecordStack()))
}

// checkOnce makes sure that leak checking is only done once. DoLeakCheck is
// called from multiple places (which may overlap) to cover different sandbox
// exit scenarios.
var checkOnce sync.Once

// DoLeakCheck iterates through the live object map and logs a message for each
// object. It should be called when no reference-counted objects are reachable
// anymore, at which point anything left in the map is considered a leak. On
// multiple calls, only the first call will perform the leak check.
func DoLeakCheck() {
	if LeakCheckEnabled() {
		checkOnce.Do(doLeakCheck)
	}
}

// DoRepeatedLeakCheck is the same as DoLeakCheck except that it can be called
// multiple times by the caller to incrementally perform leak checking.
func DoRepeatedLeakCheck() {
	if LeakCheckEnabled() {
		doLeakCheck()
	}
}

func doLeakCheck() {
	liveObjectsMu.Lock()
	defer liveObjectsMu.Unlock()
	leaked := len(liveObjects)
	if leaked > 0 {
		msg := fmt.Sprintf("Leak checking detected %d leaked objects:\n", leaked)
		for obj := range liveObjects {
			msg += obj.LeakMessage() + "\n"
		}
		if leakCheckPanicEnabled() {
			panic(msg)
		}
		log.Warningf(msg)
	}
}
