/*
 * Copyright (C) the libgit2 contributors. All rights reserved.
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#include "common.h"
#include "repository.h"
#include "commit.h"
#include "thread-utils.h"
#include "util.h"
#include "cache.h"
#include "odb.h"
#include "object.h"
#include "git2/oid.h"

GIT__USE_OIDMAP

bool git_cache__enabled = true;
ssize_t git_cache__max_storage = (256 * 1024 * 1024);
git_atomic_ssize git_cache__current_storage = {0};

static size_t git_cache__max_object_size[8] = {
	0,     /* GIT_OBJ__EXT1 */
	4096,  /* GIT_OBJ_COMMIT */
	4096,  /* GIT_OBJ_TREE */
	0,     /* GIT_OBJ_BLOB */
	4096,  /* GIT_OBJ_TAG */
	0,     /* GIT_OBJ__EXT2 */
	0,     /* GIT_OBJ_OFS_DELTA */
	0      /* GIT_OBJ_REF_DELTA */
};

int git_cache_set_max_object_size(git_otype type, size_t size)
{
	if (type < 0 || (size_t)type >= ARRAY_SIZE(git_cache__max_object_size)) {
		giterr_set(GITERR_INVALID, "type out of range");
		return -1;
	}

	git_cache__max_object_size[type] = size;
	return 0;
}

void git_cache_dump_stats(git_cache *cache)
{
	git_cached_obj *object;

	if (kh_size(cache->map) == 0)
		return;

	printf("Cache %p: %d items cached, %d bytes\n",
		cache, kh_size(cache->map), (int)cache->used_memory);

	kh_foreach_value(cache->map, object, {
		char oid_str[9];
		printf(" %s%c %s (%d)\n",
			git_object_type2string(object->type),
			object->flags == GIT_CACHE_STORE_PARSED ? '*' : ' ',
			git_oid_tostr(oid_str, sizeof(oid_str), &object->oid),
			(int)object->size
		);
	});
}

int git_cache_init(git_cache *cache)
{
	memset(cache, 0, sizeof(*cache));
	cache->map = git_oidmap_alloc();
	if (git_rwlock_init(&cache->lock)) {
		giterr_set(GITERR_OS, "Failed to initialize cache rwlock");
		return -1;
	}
	return 0;
}

/* called with lock */
static void clear_cache(git_cache *cache)
{
	git_cached_obj *evict = NULL;

	if (kh_size(cache->map) == 0)
		return;

	kh_foreach_value(cache->map, evict, {
		git_cached_obj_decref(evict);
	});

	kh_clear(oid, cache->map);
	git_atomic_ssize_add(&git_cache__current_storage, -cache->used_memory);
	cache->used_memory = 0;
}

void git_cache_clear(git_cache *cache)
{
	if (git_rwlock_wrlock(&cache->lock) < 0)
		return;

	clear_cache(cache);

	git_rwlock_wrunlock(&cache->lock);
}

void git_cache_free(git_cache *cache)
{
	git_cache_clear(cache);
	git_oidmap_free(cache->map);
	git_rwlock_free(&cache->lock);
	git__memzero(cache, sizeof(*cache));
}

/* Called with lock */
static void cache_evict_entries(git_cache *cache)
{
	uint32_t seed = rand();
	size_t evict_count = 8;
	ssize_t evicted_memory = 0;

	/* do not infinite loop if there's not enough entries to evict  */
	if (evict_count > kh_size(cache->map)) {
		clear_cache(cache);
		return;
	}

	while (evict_count > 0) {
		khiter_t pos = seed++ % kh_end(cache->map);

		if (kh_exist(cache->map, pos)) {
			git_cached_obj *evict = kh_val(cache->map, pos);

			evict_count--;
			evicted_memory += evict->size;
			git_cached_obj_decref(evict);

			kh_del(oid, cache->map, pos);
		}
	}

	cache->used_memory -= evicted_memory;
	git_atomic_ssize_add(&git_cache__current_storage, -evicted_memory);
}

static bool cache_should_store(git_otype object_type, size_t object_size)
{
	size_t max_size = git_cache__max_object_size[object_type];
	return git_cache__enabled && object_size < max_size;
}

static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
{
	khiter_t pos;
	git_cached_obj *entry = NULL;

	if (!git_cache__enabled || git_rwlock_rdlock(&cache->lock) < 0)
		return NULL;

	pos = kh_get(oid, cache->map, oid);
	if (pos != kh_end(cache->map)) {
		entry = kh_val(cache->map, pos);

		if (flags && entry->flags != flags) {
			entry = NULL;
		} else {
			git_cached_obj_incref(entry);
		}
	}

	git_rwlock_rdunlock(&cache->lock);

	return entry;
}

static void *cache_store(git_cache *cache, git_cached_obj *entry)
{
	khiter_t pos;

	git_cached_obj_incref(entry);

	if (!git_cache__enabled && cache->used_memory > 0) {
		git_cache_clear(cache);
		return entry;
	}

	if (!cache_should_store(entry->type, entry->size))
		return entry;

	if (git_rwlock_wrlock(&cache->lock) < 0)
		return entry;

	/* soften the load on the cache */
	if (git_cache__current_storage.val > git_cache__max_storage)
		cache_evict_entries(cache);

	pos = kh_get(oid, cache->map, &entry->oid);

	/* not found */
	if (pos == kh_end(cache->map)) {
		int rval;

		pos = kh_put(oid, cache->map, &entry->oid, &rval);
		if (rval >= 0) {
			kh_key(cache->map, pos) = &entry->oid;
			kh_val(cache->map, pos) = entry;
			git_cached_obj_incref(entry);
			cache->used_memory += entry->size;
			git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size);
		}
	}
	/* found */
	else {
		git_cached_obj *stored_entry = kh_val(cache->map, pos);

		if (stored_entry->flags == entry->flags) {
			git_cached_obj_decref(entry);
			git_cached_obj_incref(stored_entry);
			entry = stored_entry;
		} else if (stored_entry->flags == GIT_CACHE_STORE_RAW &&
			entry->flags == GIT_CACHE_STORE_PARSED) {
			git_cached_obj_decref(stored_entry);
			git_cached_obj_incref(entry);

			kh_key(cache->map, pos) = &entry->oid;
			kh_val(cache->map, pos) = entry;
		} else {
			/* NO OP */
		}
	}

	git_rwlock_wrunlock(&cache->lock);
	return entry;
}

void *git_cache_store_raw(git_cache *cache, git_odb_object *entry)
{
	entry->cached.flags = GIT_CACHE_STORE_RAW;
	return cache_store(cache, (git_cached_obj *)entry);
}

void *git_cache_store_parsed(git_cache *cache, git_object *entry)
{
	entry->cached.flags = GIT_CACHE_STORE_PARSED;
	return cache_store(cache, (git_cached_obj *)entry);
}

git_odb_object *git_cache_get_raw(git_cache *cache, const git_oid *oid)
{
	return cache_get(cache, oid, GIT_CACHE_STORE_RAW);
}

git_object *git_cache_get_parsed(git_cache *cache, const git_oid *oid)
{
	return cache_get(cache, oid, GIT_CACHE_STORE_PARSED);
}

void *git_cache_get_any(git_cache *cache, const git_oid *oid)
{
	return cache_get(cache, oid, GIT_CACHE_STORE_ANY);
}

void git_cached_obj_decref(void *_obj)
{
	git_cached_obj *obj = _obj;

	if (git_atomic_dec(&obj->refcount) == 0) {
		switch (obj->flags) {
		case GIT_CACHE_STORE_RAW:
			git_odb_object__free(_obj);
			break;

		case GIT_CACHE_STORE_PARSED:
			git_object__free(_obj);
			break;

		default:
			git__free(_obj);
			break;
		}
	}
}
