/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Copyright (c) 2016, Intel Corporation.
 */

#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/list.h>
#include <sys/time.h>

#include "fmd_api.h"
#include "fmd_serd.h"
#include "../zed_log.h"


#define	FMD_STR_BUCKETS		211


#ifdef SERD_ENG_DEBUG
#define	serd_log_msg(fmt, ...) \
	zed_log_msg(LOG_INFO, fmt, __VA_ARGS__)
#else
#define	serd_log_msg(fmt, ...)
#endif


/*
 * SERD Engine Backend
 */

/*
 * Compute the delta between events in nanoseconds.  To account for very old
 * events which are replayed, we must handle the case where time is negative.
 * We convert the hrtime_t's to unsigned 64-bit integers and then handle the
 * case where 'old' is greater than 'new' (i.e. high-res time has wrapped).
 */
static hrtime_t
fmd_event_delta(hrtime_t t1, hrtime_t t2)
{
	uint64_t old = t1;
	uint64_t new = t2;

	return (new >= old ? new - old : (UINT64_MAX - old) + new + 1);
}

static fmd_serd_eng_t *
fmd_serd_eng_alloc(const char *name, uint64_t n, hrtime_t t)
{
	fmd_serd_eng_t *sgp;

	sgp = malloc(sizeof (fmd_serd_eng_t));
	bzero(sgp, sizeof (fmd_serd_eng_t));

	sgp->sg_name = strdup(name);
	sgp->sg_flags = FMD_SERD_DIRTY;
	sgp->sg_n = n;
	sgp->sg_t = t;

	list_create(&sgp->sg_list, sizeof (fmd_serd_elem_t),
	    offsetof(fmd_serd_elem_t, se_list));

	return (sgp);
}

static void
fmd_serd_eng_free(fmd_serd_eng_t *sgp)
{
	fmd_serd_eng_reset(sgp);
	free(sgp->sg_name);
	list_destroy(&sgp->sg_list);
	free(sgp);
}

/*
 * sourced from fmd_string.c
 */
static ulong_t
fmd_strhash(const char *key)
{
	ulong_t g, h = 0;
	const char *p;

	for (p = key; *p != '\0'; p++) {
		h = (h << 4) + *p;

		if ((g = (h & 0xf0000000)) != 0) {
			h ^= (g >> 24);
			h ^= g;
		}
	}

	return (h);
}

void
fmd_serd_hash_create(fmd_serd_hash_t *shp)
{
	shp->sh_hashlen = FMD_STR_BUCKETS;
	shp->sh_hash = calloc(shp->sh_hashlen, sizeof (void *));
	shp->sh_count = 0;
}

void
fmd_serd_hash_destroy(fmd_serd_hash_t *shp)
{
	fmd_serd_eng_t *sgp, *ngp;
	uint_t i;

	for (i = 0; i < shp->sh_hashlen; i++) {
		for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = ngp) {
			ngp = sgp->sg_next;
			fmd_serd_eng_free(sgp);
		}
	}

	free(shp->sh_hash);
	bzero(shp, sizeof (fmd_serd_hash_t));
}

void
fmd_serd_hash_apply(fmd_serd_hash_t *shp, fmd_serd_eng_f *func, void *arg)
{
	fmd_serd_eng_t *sgp;
	uint_t i;

	for (i = 0; i < shp->sh_hashlen; i++) {
		for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = sgp->sg_next)
			func(sgp, arg);
	}
}

fmd_serd_eng_t *
fmd_serd_eng_insert(fmd_serd_hash_t *shp, const char *name,
    uint_t n, hrtime_t t)
{
	uint_t h = fmd_strhash(name) % shp->sh_hashlen;
	fmd_serd_eng_t *sgp = fmd_serd_eng_alloc(name, n, t);

	serd_log_msg("  SERD Engine: inserting  %s N %d T %llu",
	    name, (int)n, (long long unsigned)t);

	sgp->sg_next = shp->sh_hash[h];
	shp->sh_hash[h] = sgp;
	shp->sh_count++;

	return (sgp);
}

fmd_serd_eng_t *
fmd_serd_eng_lookup(fmd_serd_hash_t *shp, const char *name)
{
	uint_t h = fmd_strhash(name) % shp->sh_hashlen;
	fmd_serd_eng_t *sgp;

	for (sgp = shp->sh_hash[h]; sgp != NULL; sgp = sgp->sg_next) {
		if (strcmp(name, sgp->sg_name) == 0)
			return (sgp);
	}

	return (NULL);
}

void
fmd_serd_eng_delete(fmd_serd_hash_t *shp, const char *name)
{
	uint_t h = fmd_strhash(name) % shp->sh_hashlen;
	fmd_serd_eng_t *sgp, **pp = &shp->sh_hash[h];

	serd_log_msg("  SERD Engine: deleting %s", name);

	for (sgp = *pp; sgp != NULL; sgp = sgp->sg_next) {
		if (strcmp(sgp->sg_name, name) != 0)
			pp = &sgp->sg_next;
		else
			break;
	}

	if (sgp != NULL) {
		*pp = sgp->sg_next;
		fmd_serd_eng_free(sgp);
		assert(shp->sh_count != 0);
		shp->sh_count--;
	}
}

static void
fmd_serd_eng_discard(fmd_serd_eng_t *sgp, fmd_serd_elem_t *sep)
{
	list_remove(&sgp->sg_list, sep);
	sgp->sg_count--;

	serd_log_msg("  SERD Engine: discarding %s, %d remaining",
	    sgp->sg_name, (int)sgp->sg_count);

	free(sep);
}

int
fmd_serd_eng_record(fmd_serd_eng_t *sgp, hrtime_t hrt)
{
	fmd_serd_elem_t *sep, *oep;

	/*
	 * If the fired flag is already set, return false and discard the
	 * event.  This means that the caller will only see the engine "fire"
	 * once until fmd_serd_eng_reset() is called.  The fmd_serd_eng_fired()
	 * function can also be used in combination with fmd_serd_eng_record().
	 */
	if (sgp->sg_flags & FMD_SERD_FIRED) {
		serd_log_msg("  SERD Engine: record %s already fired!",
		    sgp->sg_name);
		return (FMD_B_FALSE);
	}

	while (sgp->sg_count >= sgp->sg_n)
		fmd_serd_eng_discard(sgp, list_tail(&sgp->sg_list));

	sep = malloc(sizeof (fmd_serd_elem_t));
	sep->se_hrt = hrt;

	list_insert_head(&sgp->sg_list, sep);
	sgp->sg_count++;

	serd_log_msg("  SERD Engine: recording %s of %d (%llu)",
	    sgp->sg_name, (int)sgp->sg_count, (long long unsigned)hrt);

	/*
	 * Pick up the oldest element pointer for comparison to 'sep'.  We must
	 * do this after adding 'sep' because 'oep' and 'sep' can be the same.
	 */
	oep = list_tail(&sgp->sg_list);

	if (sgp->sg_count >= sgp->sg_n &&
	    fmd_event_delta(oep->se_hrt, sep->se_hrt) <= sgp->sg_t) {
		sgp->sg_flags |= FMD_SERD_FIRED | FMD_SERD_DIRTY;
		serd_log_msg("  SERD Engine: fired %s", sgp->sg_name);
		return (FMD_B_TRUE);
	}

	sgp->sg_flags |= FMD_SERD_DIRTY;
	return (FMD_B_FALSE);
}

int
fmd_serd_eng_fired(fmd_serd_eng_t *sgp)
{
	return (sgp->sg_flags & FMD_SERD_FIRED);
}

int
fmd_serd_eng_empty(fmd_serd_eng_t *sgp)
{
	return (sgp->sg_count == 0);
}

void
fmd_serd_eng_reset(fmd_serd_eng_t *sgp)
{
	serd_log_msg("  SERD Engine: resetting %s", sgp->sg_name);

	while (sgp->sg_count != 0)
		fmd_serd_eng_discard(sgp, list_head(&sgp->sg_list));

	sgp->sg_flags &= ~FMD_SERD_FIRED;
	sgp->sg_flags |= FMD_SERD_DIRTY;
}

void
fmd_serd_eng_gc(fmd_serd_eng_t *sgp)
{
	fmd_serd_elem_t *sep, *nep;
	hrtime_t hrt;

	if (sgp->sg_count == 0 || (sgp->sg_flags & FMD_SERD_FIRED))
		return; /* no garbage collection needed if empty or fired */

	sep = list_head(&sgp->sg_list);
	if (sep == NULL)
		return;

	hrt = sep->se_hrt - sgp->sg_t;

	for (sep = list_head(&sgp->sg_list); sep != NULL; sep = nep) {
		if (sep->se_hrt >= hrt)
			break; /* sep and subsequent events are all within T */

		nep = list_next(&sgp->sg_list, sep);
		fmd_serd_eng_discard(sgp, sep);
		sgp->sg_flags |= FMD_SERD_DIRTY;
	}
}
