/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * This software is the proprietary information of Sun Microsystems, Inc.
 * Use is subject to license terms.
 * 
 * Copyright 2004 Sun Microsystems, Inc.  Tous droits réservés.
 * Ce logiciel est propriété de Sun Microsystems, Inc.
 * Distribué par des licences qui en restreignent l'utilisation.
 *
 * ident        "@(#)txn_display.c 1.8     04/05/19 SMI"
 *
 */

#include <pthread.h>
#include "nspr.h"
#include "string.h"
 
#include "mfTransaction.h"
#include "mfTransactionPrivate.h"
/*
 * Some display, debugging routines.
 * This code only exists in the debug version, not the optimized
 "* version.
 */

#if defined(DEBUG_BUILD)

extern int global_num_txn_types;
extern pthread_mutex_t global_mutex_num_txn_types;
extern transaction_type_info_t global_txn_types_array[MF_MAX_NUM_TXN_TYPES];

pthread_mutex_t global_mutex_txn_display;

static void txn_display_one_txn_needs_lock(one_transaction_info_t *one_txnp);
static void txn_display_metrics_needs_lock(mfTransactionMetrics_t *txntype_metricsp);
 

void debug_printf(int tran_id, char *fmt, ... ){
  va_list ap;
  char message_buf[256];
  unsigned int thread_id = (unsigned int)pthread_self();

  snprintf(message_buf, 256, "(%s:thread_id=%d trans_id=%d)",
          LIBNAME, thread_id, tran_id);

 va_start(ap, fmt);
 vsnprintf(&message_buf[strlen(message_buf)],
           256-strlen(message_buf), fmt, ap);
 printf("%s", message_buf);
 va_end(ap);
}


/*
 * The number of transaction types never decreases,
 * as there is no "mfUnregisterTransaction()" call.
 * So, if we take a snapshot of the number
 * of txn types then we are guaranteed that
 * the list up to that point will be valid.
 *
 * Naturally, when looking into a given transaction type,
 * we will respect the locking required to look at it.
*/

void txn_display_txn_types() {

  int i = 0;
  int current_num_txn_types = 0;

  pthread_mutex_lock(&global_mutex_num_txn_types);
  current_num_txn_types = global_num_txn_types;
  pthread_mutex_unlock(&global_mutex_num_txn_types);

  printf("current_num_txn_types: %d\n", current_num_txn_types);
  i = 0;
  while( i < current_num_txn_types ) {

	txn_display_txn_type(&global_txn_types_array[i]);
	i++;
  }
}

/* routine to display a txn type structure
 * Takes a display mutex so all this data
 * won't be mixed up wioth another one, though it could
 * have other printfs mixed up that do not
 
 * take the txn_display mutex.
 */
void txn_display_txn_type( transaction_type_info_t *txn_typep ) {

  pthread_mutex_lock(&global_mutex_txn_display);
  printf("{");
  printf(" txntype_name '%s'", txn_typep->txntype_name);
    
  pthread_mutex_lock(&txn_typep->txntype_mutex_metrics);
  txn_display_metrics_needs_lock( txn_typep->txntype_metricsp );
  pthread_mutex_unlock(&txn_typep->txntype_mutex_metrics);

  pthread_mutex_lock(&txn_typep->txntype_freelist.otl_mutex);
  printf(" txntype_num_active_txns %lu",
		 txn_typep->txntype_freelist.otl_num_active_txns);
  printf(" txntype_num_txns_in_freelist %lu",
		 txn_typep->txntype_freelist.otl_num_txns_in_list);
  /* Free list seems to be ok, pretty boring to look at. 
   * txn_display_txns_needs_lock(txn_typep->txntype_onetxn_freelistp );
  */  
  pthread_mutex_unlock(&txn_typep->txntype_freelist.otl_mutex);	  
			
  printf("\n}\n");
  pthread_mutex_unlock(&global_mutex_txn_display);
}

static void txn_display_metrics_needs_lock(mfTransactionMetrics_t *txntype_metricsp){

  printf("{");
  printf(" uri '%s'", txntype_metricsp->Uri);
  printf(" NbInRequests %lld", txntype_metricsp->NbInRequests);
  printf(" NbOutRequests %lld", txntype_metricsp->NbOutRequests);
  printf(" NbFailedRequests %lld", txntype_metricsp->NbFailedRequests);

  printf(" accumulatedResponseTime %lld", 
		 txntype_metricsp->AccumulatedResponseTime);
  printf(" minResponseTime %lld", 
		 txntype_metricsp->MinResponseTime);
  printf(" maxResponseTime %lld", 
		 txntype_metricsp->MaxResponseTime);
  printf(" accumulatedSqResponseTime %lld",
		 txntype_metricsp->AccumulatedSqResponseTime);
  
  printf(" accumulatedServiceTime %lld", 
		 txntype_metricsp->AccumulatedServiceTime);
  printf(" minServiceTime %lld", 
		 txntype_metricsp->MinServiceTime);
  printf(" maxServiceTime %lld", 
		 txntype_metricsp->MaxServiceTime);  
  printf(" accumulatedSqServiceTime %lld",
		 txntype_metricsp->AccumulatedSqServiceTime);
 
  printf("}\n");
  
}

void txn_display_txns_needs_lock(
							one_transaction_info_t *txntype_onetxn_listp) {

  one_transaction_info_t *one_txnp = txntype_onetxn_listp;

  while( one_txnp != NULL ){
	
	txn_display_one_txn_needs_lock(one_txnp);
	one_txnp = one_txnp->onetxn_next_txnp;

  }
 
}

static void txn_display_one_txn_needs_lock(one_transaction_info_t *one_txnp){

  printf(" {");
  printf(" transaction_type '%s'",
		 ( one_txnp->onetxn_txntypep != NULL &&
		   one_txnp->onetxn_txntypep->txntype_name[0] != '\0' ?
		   &(one_txnp->onetxn_txntypep->txntype_name[0]): "NIL")
		 );
  printf(" onetxn_cputime_start %lld", 
         one_txnp->onetxn_cputime_start);
  printf(" onetxn_blocked_cputime_start %lld", 
		 one_txnp->onetxn_blocked_cputime_start);
  printf(" onetxn_accumulated_blocked_cputime %lld", 
		 one_txnp->onetxn_accumulated_blocked_cputime);
  printf(" onetxn_status %d", one_txnp->onetxn_status);
  printf("\n }\n");
}


#endif /* DEBUG_BUILD */


 
