/*
 * 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, %"PRIdZ" bytes\n",
		cache, kh_size(cache->map), cache->used_memory);

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

int git_cache_init(git_cache *cache)
{
	memset(cache, 0, sizeof(*cache));
	cache->map = git_oidmap_alloc();
	GITERR_CHECK_ALLOC(cache->map);
	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;
		}
	}
}
