/*
 *------------------------------------------------------------------
 * cj.c
 *
 * Copyright (c) 2013 Cisco and/or its affiliates.
 * 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.
 *------------------------------------------------------------------
 */

/**
 * @file
 * Circular joournal diagnostic mechanism.
 *
 * The @c cj thread-safe circular log buffer scheme is occasionally useful
 * when chasing bugs. Calls to it should not be checked in.
 */
/*? %%clicmd:group_label Circular Journal %% ?*/
/*? %%syscfg:group_label Circular Journal %% ?*/

#include <stdio.h>
#include <vlib/vlib.h>

#include <vlib/unix/cj.h>

cj_main_t cj_main;

void
cj_log (u32 type, void *data0, void *data1)
{
  u64 new_tail;
  cj_main_t *cjm = &cj_main;
  cj_record_t *r;

  if (cjm->enable == 0)
    return;

  new_tail = clib_atomic_add_fetch (&cjm->tail, 1);

  r = (cj_record_t *) & (cjm->records[new_tail & (cjm->num_records - 1)]);
  r->time = vlib_time_now (cjm->vlib_main);
  r->thread_index = vlib_get_thread_index ();
  r->type = type;
  r->data[0] = pointer_to_uword (data0);
  r->data[1] = pointer_to_uword (data1);
}

void
cj_stop (void)
{
  cj_main_t *cjm = &cj_main;

  cjm->enable = 0;
}


clib_error_t *
cj_init (vlib_main_t * vm)
{
  cj_main_t *cjm = &cj_main;

  cjm->vlib_main = vm;
  return 0;
}

VLIB_INIT_FUNCTION (cj_init);

static clib_error_t *
cj_config (vlib_main_t * vm, unformat_input_t * input)
{
  cj_main_t *cjm = &cj_main;
  int matched = 0;
  int enable = 0;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "records %d", &cjm->num_records))
	matched = 1;
      else if (unformat (input, "on"))
	enable = 1;
      else
	return clib_error_return (0, "cj_config: unknown input '%U'",
				  format_unformat_error, input);
    }

  if (matched == 0)
    return 0;

  cjm->num_records = max_pow2 (cjm->num_records);
  vec_validate (cjm->records, cjm->num_records - 1);
  memset (cjm->records, 0xff, cjm->num_records * sizeof (cj_record_t));
  cjm->tail = ~0;
  cjm->enable = enable;

  return 0;
}

/*?
 * Configure the circular journal diagnostic mechanism. This is only useful
 * if you, the deveoper, have written code to make use of the circular
 * journal.
 *
 * @cfgcmd{records, &lt;number&gt;}
 * Configure the number of records to allocate for the circular journal.
 *
 * @cfgcmd{on}
 * Enable the collection of records in the circular journal at the
 * earliest opportunity.
?*/
VLIB_CONFIG_FUNCTION (cj_config, "cj");

void
cj_enable_disable (int is_enable)
{
  cj_main_t *cjm = &cj_main;

  if (cjm->num_records)
    cjm->enable = is_enable;
  else
    vlib_cli_output (cjm->vlib_main, "CJ not configured...");
}

static inline void
cj_dump_one_record (cj_record_t * r)
{
  fprintf (stderr, "[%d]: %10.6f T%02d %llx %llx\n",
	   r->thread_index, r->time, r->type,
	   (long long unsigned int) r->data[0],
	   (long long unsigned int) r->data[1]);
}

static void
cj_dump_internal (u8 filter0_enable, u64 filter0,
		  u8 filter1_enable, u64 filter1)
{
  cj_main_t *cjm = &cj_main;
  cj_record_t *r;
  u32 i, index;

  if (cjm->num_records == 0)
    {
      fprintf (stderr, "CJ not configured...\n");
      return;
    }

  if (cjm->tail == (u64) ~ 0)
    {
      fprintf (stderr, "No data collected...\n");
      return;
    }

  /* Has the trace wrapped? */
  index = (cjm->tail + 1) & (cjm->num_records - 1);
  r = &(cjm->records[index]);

  if (r->thread_index != (u32) ~ 0)
    {
      /* Yes, dump from tail + 1 to the end */
      for (i = index; i < cjm->num_records; i++)
	{
	  if (filter0_enable && (r->data[0] != filter0))
	    goto skip;
	  if (filter1_enable && (r->data[1] != filter1))
	    goto skip;
	  cj_dump_one_record (r);
	skip:
	  r++;
	}
    }
  /* dump from the beginning through the final tail */
  r = cjm->records;
  for (i = 0; i <= cjm->tail; i++)
    {
      if (filter0_enable && (r->data[0] != filter0))
	goto skip2;
      if (filter1_enable && (r->data[1] != filter1))
	goto skip2;
      cj_dump_one_record (r);
    skip2:
      r++;
    }
}

void
cj_dump (void)
{
  cj_dump_internal (0, 0, 0, 0);
}

void
cj_dump_filter_data0 (u64 filter0)
{
  cj_dump_internal (1 /* enable f0 */ , filter0, 0, 0);
}

void
cj_dump_filter_data1 (u64 filter1)
{
  cj_dump_internal (0, 0, 1 /* enable f1 */ , filter1);
}

void
cj_dump_filter_data12 (u64 filter0, u64 filter1)
{
  cj_dump_internal (1, filter0, 1, filter1);
}

static clib_error_t *
cj_command_fn (vlib_main_t * vm,
	       unformat_input_t * input, vlib_cli_command_t * cmd)
{
  int is_enable = -1;
  int is_dump = -1;
  unformat_input_t _line_input, *line_input = &_line_input;
  clib_error_t *error = NULL;

  /* Get a line of input. */
  if (!unformat_user (input, unformat_line_input, line_input))
    return clib_error_return (0, "expected enable | disable | dump");

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "enable") || unformat (line_input, "on"))
	is_enable = 1;
      else if (unformat (line_input, "disable")
	       || unformat (line_input, "off"))
	is_enable = 0;
      else if (unformat (line_input, "dump"))
	is_dump = 1;
      else
	{
	  error = clib_error_return (0, "unknown input `%U'",
				     format_unformat_error, line_input);
	  goto done;
	}
    }

  if (is_enable >= 0)
    cj_enable_disable (is_enable);

  if (is_dump > 0)
    cj_dump ();

done:
  unformat_free (line_input);
  return error;
}

/*?
 * Enable, disable the collection of diagnostic data into a
 * circular journal or dump the circular journal diagnostic data.
 * This is only useful if you, the deveoper, have written code to make
 * use of the circular journal.
 *
 * When dumping the data it is formatted and sent to @c stderr of the
 * VPP process; when running VPP in <code>unix interactive</code> mode
 * this is typically the same place as the Debug CLI.
?*/

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cj_command,static) = {
  .path = "cj",
  .short_help = "cj <enable | disable | dump>",
  .function = cj_command_fn,
};
/* *INDENT-ON* */


/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
