HttpTransact::client_result_stat(State* s, ink_hrtime total_time, ink_hrtime request_process_time)
{
  ClientTransactionResult_t client_transaction_result = CLIENT_TRANSACTION_RESULT_UNDEFINED;

  ///////////////////////////////////////////////////////
  // don't count errors we generated as hits or misses //
  ///////////////////////////////////////////////////////
  if ((s->source == SOURCE_INTERNAL) && (s->hdr_info.client_response.status_get() >= 400)) {
    client_transaction_result = CLIENT_TRANSACTION_RESULT_ERROR_OTHER;
  }

  switch (s->squid_codes.log_code) {
  case SQUID_LOG_ERR_CONNECT_FAIL:
    HTTP_INCREMENT_TRANS_STAT(http_cache_miss_cold_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_ERROR_CONNECT_FAIL;
    break;

  case SQUID_LOG_TCP_MEM_HIT:
    HTTP_INCREMENT_TRANS_STAT(http_cache_hit_mem_fresh_stat);
  case SQUID_LOG_TCP_HIT:
    // It's possible to have two stat's instead of one, if needed.
    HTTP_INCREMENT_TRANS_STAT(http_cache_hit_fresh_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_HIT_FRESH;
    break;

  case SQUID_LOG_TCP_REFRESH_HIT:
    HTTP_INCREMENT_TRANS_STAT(http_cache_hit_reval_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_HIT_REVALIDATED;
    break;

  case SQUID_LOG_TCP_IMS_HIT:
    HTTP_INCREMENT_TRANS_STAT(http_cache_hit_ims_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_HIT_FRESH;
    break;

  case SQUID_LOG_TCP_REF_FAIL_HIT:
    HTTP_INCREMENT_TRANS_STAT(http_cache_hit_stale_served_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_HIT_FRESH;
    break;

  case SQUID_LOG_TCP_MISS:
    if ((GET_VIA_STRING(VIA_CACHE_RESULT) == VIA_IN_CACHE_NOT_ACCEPTABLE)
        || (GET_VIA_STRING(VIA_CACHE_RESULT) == VIA_CACHE_MISS)) {
      HTTP_INCREMENT_TRANS_STAT(http_cache_miss_cold_stat);
      client_transaction_result = CLIENT_TRANSACTION_RESULT_MISS_COLD;
    } else {
      // FIX: what case is this for?  can it ever happen?
      HTTP_INCREMENT_TRANS_STAT(http_cache_miss_uncacheable_stat);
      client_transaction_result = CLIENT_TRANSACTION_RESULT_MISS_UNCACHABLE;
    }
    break;

  case SQUID_LOG_TCP_REFRESH_MISS:
    HTTP_INCREMENT_TRANS_STAT(http_cache_miss_changed_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_MISS_CHANGED;
    break;

  case SQUID_LOG_TCP_CLIENT_REFRESH:
    HTTP_INCREMENT_TRANS_STAT(http_cache_miss_client_no_cache_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_MISS_CLIENT_NO_CACHE;
    break;

  case SQUID_LOG_TCP_IMS_MISS:
    HTTP_INCREMENT_TRANS_STAT(http_cache_miss_ims_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_MISS_COLD;
    break;

  case SQUID_LOG_TCP_SWAPFAIL:
    HTTP_INCREMENT_TRANS_STAT(http_cache_read_error_stat);
    client_transaction_result = CLIENT_TRANSACTION_RESULT_HIT_FRESH;
    break;

  case SQUID_LOG_ERR_READ_TIMEOUT:
  case SQUID_LOG_TCP_DENIED:
    // No cache result due to error
    client_transaction_result = CLIENT_TRANSACTION_RESULT_ERROR_OTHER;
    break;

  default:
    // FIX: What is the conditional below doing?
//          if (s->local_trans_stats[http_cache_lookups_stat].count == 1L)
//              HTTP_INCREMENT_TRANS_STAT(http_cache_miss_cold_stat);

    // FIX: I suspect the following line should not be set here,
    //      because it overrides the error classification above.
    //      Commenting out.
    // client_transaction_result = CLIENT_TRANSACTION_RESULT_MISS_COLD;

    break;
  }

  //////////////////////////////////////////
  // don't count aborts as hits or misses //
  //////////////////////////////////////////
  if (s->client_info.abort == ABORTED) {
    client_transaction_result = CLIENT_TRANSACTION_RESULT_ERROR_ABORT;
  } else if (s->client_info.abort == MAYBE_ABORTED) {
    client_transaction_result = CLIENT_TRANSACTION_RESULT_ERROR_POSSIBLE_ABORT;
  }
  // Count the status codes, assuming the client didn't abort (i.e. there is an m_http)
  if ((s->source != SOURCE_NONE) && (s->client_info.abort == DIDNOT_ABORT)) {
    int status_code = s->hdr_info.client_response.status_get();

    switch(status_code) {
    case 100: HTTP_INCREMENT_TRANS_STAT(http_response_status_100_count_stat); break;
    case 101: HTTP_INCREMENT_TRANS_STAT(http_response_status_101_count_stat); break;
    case 200: HTTP_INCREMENT_TRANS_STAT(http_response_status_200_count_stat); break;
    case 201: HTTP_INCREMENT_TRANS_STAT(http_response_status_201_count_stat); break;
    case 202: HTTP_INCREMENT_TRANS_STAT(http_response_status_202_count_stat); break;
    case 203: HTTP_INCREMENT_TRANS_STAT(http_response_status_203_count_stat); break;
    case 204: HTTP_INCREMENT_TRANS_STAT(http_response_status_204_count_stat); break;
    case 205: HTTP_INCREMENT_TRANS_STAT(http_response_status_205_count_stat); break;
    case 206: HTTP_INCREMENT_TRANS_STAT(http_response_status_206_count_stat); break;
    case 300: HTTP_INCREMENT_TRANS_STAT(http_response_status_300_count_stat); break;
    case 301: HTTP_INCREMENT_TRANS_STAT(http_response_status_301_count_stat); break;
    case 302: HTTP_INCREMENT_TRANS_STAT(http_response_status_302_count_stat); break;
    case 303: HTTP_INCREMENT_TRANS_STAT(http_response_status_303_count_stat); break;
    case 304: HTTP_INCREMENT_TRANS_STAT(http_response_status_304_count_stat); break;
    case 305: HTTP_INCREMENT_TRANS_STAT(http_response_status_305_count_stat); break;
    case 307: HTTP_INCREMENT_TRANS_STAT(http_response_status_307_count_stat); break;
    case 400: HTTP_INCREMENT_TRANS_STAT(http_response_status_400_count_stat); break;
    case 401: HTTP_INCREMENT_TRANS_STAT(http_response_status_401_count_stat); break;
    case 402: HTTP_INCREMENT_TRANS_STAT(http_response_status_402_count_stat); break;
    case 403: HTTP_INCREMENT_TRANS_STAT(http_response_status_403_count_stat); break;
    case 404: HTTP_INCREMENT_TRANS_STAT(http_response_status_404_count_stat); break;
    case 405: HTTP_INCREMENT_TRANS_STAT(http_response_status_405_count_stat); break;
    case 406: HTTP_INCREMENT_TRANS_STAT(http_response_status_406_count_stat); break;
    case 407: HTTP_INCREMENT_TRANS_STAT(http_response_status_407_count_stat); break;
    case 408: HTTP_INCREMENT_TRANS_STAT(http_response_status_408_count_stat); break;
    case 409: HTTP_INCREMENT_TRANS_STAT(http_response_status_409_count_stat); break;
    case 410: HTTP_INCREMENT_TRANS_STAT(http_response_status_410_count_stat); break;
    case 411: HTTP_INCREMENT_TRANS_STAT(http_response_status_411_count_stat); break;
    case 412: HTTP_INCREMENT_TRANS_STAT(http_response_status_412_count_stat); break;
    case 413: HTTP_INCREMENT_TRANS_STAT(http_response_status_413_count_stat); break;
    case 414: HTTP_INCREMENT_TRANS_STAT(http_response_status_414_count_stat); break;
    case 415: HTTP_INCREMENT_TRANS_STAT(http_response_status_415_count_stat); break;
    case 416: HTTP_INCREMENT_TRANS_STAT(http_response_status_416_count_stat); break;
    case 500: HTTP_INCREMENT_TRANS_STAT(http_response_status_500_count_stat); break;
    case 501: HTTP_INCREMENT_TRANS_STAT(http_response_status_501_count_stat); break;
    case 502: HTTP_INCREMENT_TRANS_STAT(http_response_status_502_count_stat); break;
    case 503: HTTP_INCREMENT_TRANS_STAT(http_response_status_503_count_stat); break;
    case 504: HTTP_INCREMENT_TRANS_STAT(http_response_status_504_count_stat); break;
    case 505: HTTP_INCREMENT_TRANS_STAT(http_response_status_505_count_stat); break;
    default: break;
    }
    switch(status_code / 100) {
    case 1: HTTP_INCREMENT_TRANS_STAT(http_response_status_1xx_count_stat); break;
    case 2: HTTP_INCREMENT_TRANS_STAT(http_response_status_2xx_count_stat); break;
    case 3: HTTP_INCREMENT_TRANS_STAT(http_response_status_3xx_count_stat); break;
    case 4: HTTP_INCREMENT_TRANS_STAT(http_response_status_4xx_count_stat); break;
    case 5: HTTP_INCREMENT_TRANS_STAT(http_response_status_5xx_count_stat); break;
    default: break;
    }
  }

  // Increment the completed connection count
  HTTP_INCREMENT_TRANS_STAT(http_completed_requests_stat);

  // Set the stat now that we know what happend
  ink_hrtime total_msec = ink_hrtime_to_msec(total_time);
  ink_hrtime process_msec = ink_hrtime_to_msec(request_process_time);
  switch (client_transaction_result) {
  case CLIENT_TRANSACTION_RESULT_HIT_FRESH:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_hit_fresh_stat, total_msec);
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_hit_fresh_process_stat, process_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_HIT_REVALIDATED:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_hit_reval_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_MISS_COLD:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_miss_cold_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_MISS_CHANGED:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_miss_changed_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_MISS_CLIENT_NO_CACHE:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_miss_client_no_cache_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_MISS_UNCACHABLE:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_miss_uncacheable_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_ERROR_ABORT:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_errors_aborts_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_ERROR_POSSIBLE_ABORT:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_errors_possible_aborts_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_ERROR_CONNECT_FAIL:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_errors_connect_failed_stat, total_msec);
    break;
  case CLIENT_TRANSACTION_RESULT_ERROR_OTHER:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_errors_other_stat, total_msec);
    break;
  default:
    HTTP_SUM_TRANS_STAT(http_ua_msecs_counts_other_unclassified_stat, total_msec);
    // This can happen if a plugin manually sets the status code after an error.
    DebugTxn("http", "Unclassified statistic");
    break;
  }
}