blob: 7dd9e3985246a0ed49d27d63c997f040d6a4c213 [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
/****************************************************************************
TestDns.cc
Test module to test the DNS processor
The main state machine is encapulated in the StateMachine instance.
****************************************************************************/
#include "DNS.h"
#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include "VConnection.h"
#include "stdio.h"
#include "ts/ink_platform.h"
#define N_STATE_MACHINES 1000
#define MEASUREMENT_INTERVAL 100
class TestDnsStateMachine;
//////////////////////////////////////////////////////////////////////////////
//
// Globals
//
//////////////////////////////////////////////////////////////////////////////
unsigned g_host_ip = 0;
char *in_file_name = "test_dns.in";
char *out_file_name = "test_dns.out";
char *rate_file_name = "rates.out";
char *rate_misc_file_name = "rates.misc.out";
ofstream fout;
ofstream fout_rate, fout_rate_misc;
FILE *fin;
//////////////////////////////////////////////////////////////////////////////
//
// TestDnsStateMachine
//
// An instance of TestDnsStateMachine is created for each host
//
//////////////////////////////////////////////////////////////////////////////
class TestDnsStateMachine : public Continuation
{
public:
TestDnsStateMachine(char *ahost, size_t size);
~TestDnsStateMachine()
{
// cout << "StateMachine::~StateMachine(). Terminating ... " << endl;
return;
}
const char *currentStateName();
int processEvent(int event, void *data);
enum {
START,
DNS_LOOKUP,
};
int m_state;
char host[100];
};
TestDnsStateMachine::TestDnsStateMachine(char *ahost, size_t size) : Continuation(new_ProxyMutex())
{
ink_strlcpy(host, ahost, size);
m_state = START;
SET_HANDLER(processEvent);
return;
}
inline const char *
TestDnsStateMachine::currentStateName()
{
switch (m_state) {
case START:
return ("START");
case DNS_LOOKUP:
return ("DNS_LOOKUP");
default:
return ("unknown state");
}
}
//////////////////////////////////////////////////////////////////////////////
//
// TestDnsStateMachine::processEvent()
//
// This routine is the main callback entry point of the TestTunnel
// state machine.
//
//////////////////////////////////////////////////////////////////////////////
int
TestDnsStateMachine::processEvent(int event, void *data)
{
int rvalue = VC_EVENT_DONE;
void complete();
// printf("<<< state machine processEvent() called in state '%s' >>>\n",currentStateName());
switch (m_state) {
case START: {
// cout << " started up TestDnsStateMachine" << endl;
// cout << " dns lookup for <" << host << ">" << endl;
//
// asynchronously do DNS, calling <this> back when done
//
m_state = DNS_LOOKUP;
dnsProcessor.gethostbyname(this, host);
break;
}
case DNS_LOOKUP: {
ink_assert(event == DNS_EVENT_LOOKUP);
if (!host)
ink_assert(!"Error - host has no value\n");
if (data) {
HostEnt *ent = (HostEnt *)data;
g_host_ip = ((struct in_addr *)ent->h_addr_list[0])->s_addr;
// cout << " dns lookup is done <" << g_host_ip << ">" << endl;
// cout << "<" << host << "> <" << g_host_ip << ">\n";
fout << "<" << host << "> <" << g_host_ip << ">\n";
// cout << " finishing up" << endl;
// printf("*** NOTE: We Need To Somehow Free 'this' Here! How?\n");
} else {
fout << "<" << host << "> <>\n";
}
fout.flush();
rvalue = VC_EVENT_DONE;
m_state = 99; // Some Undefined state value
complete();
delete this;
break;
}
default: {
ink_assert(!"unexpected m_state");
break;
}
}
return (rvalue);
}
int state_machines_created, state_machines_finished, measurement_interval;
ink_hrtime start_time, last_measurement_time;
// Following function is called to measure the throughput
void
complete()
{
float throughput, cumul_throughput;
ink_hrtime now;
state_machines_finished++;
if (!(state_machines_finished % measurement_interval)) {
now = Thread::get_hrtime();
cumul_throughput = state_machines_finished * 1.0 * HRTIME_SECOND / (now - start_time);
throughput = measurement_interval * 1.0 * HRTIME_SECOND / (now - last_measurement_time);
last_measurement_time = now;
// cout << state_machines_finished << ": " <<
// "Cumul. Thrput " << cumul_throughput <<
// " per sec; Thrput for last " << measurement_interval << " requests: "
// << throughput << " per sec\n";
// cout.flush();
// fout_rate << state_machines_finished << ": " <<
// "Cumul. Thrput " << cumul_throughput <<
// " per sec; Thrput for last " << measurement_interval << " requests: "
// << throughput << " per sec\n";
fout_rate << (now - start_time) * 1.0 / HRTIME_SECOND << " " << state_machines_finished << " " << cumul_throughput << " "
<< throughput << "\n";
fout_rate.flush();
}
if (state_machines_finished == state_machines_created) {
now = Thread::get_hrtime();
fout_rate_misc << (now - start_time) * 1.0 / HRTIME_SECOND << "\n";
fout_rate_misc.flush();
fout.close();
fout_rate.close();
fout_rate_misc.close();
cout << "Dns Testing Complete\n";
exit(0);
}
// printf("%d Hosts left \n",state_machines_unfinished);
}
//////////////////////////////////////////////////////////////////////////////
//
// test
//
// Main entry point for DNS tests
//
//////////////////////////////////////////////////////////////////////////////
void
test()
{
char host[100];
ink_hrtime now;
int i;
TestDnsStateMachine *test_dns_state_machine;
printf("removing file '%s'\n", out_file_name);
unlink(out_file_name);
printf("removing file '%s'\n", rate_file_name);
unlink(rate_file_name);
printf("removing file '%s'\n", rate_misc_file_name);
unlink(rate_misc_file_name);
fin = fopen(in_file_name, "r"); // STDIO OK
fout.open(out_file_name);
fout_rate.open(rate_file_name);
fout_rate_misc.open(rate_misc_file_name);
i = 0;
state_machines_created = N_STATE_MACHINES;
state_machines_finished = 0;
measurement_interval = MEASUREMENT_INTERVAL;
start_time = Thread::get_hrtime();
last_measurement_time = Thread::get_hrtime();
while ((fscanf(fin, "%s", host) != EOF) && (i < state_machines_created)) {
test_dns_state_machine = new TestDnsStateMachine(host, sizeof(host));
test_dns_state_machine->handleEvent();
i++;
}
now = Thread::get_hrtime();
cout << "Finished creating all Continuations at " << (now - start_time) / HRTIME_SECOND << " sec and "
<< (now - start_time) % HRTIME_SECOND << "nanosec\n";
fout_rate_misc << (now - start_time) * 1.0 / HRTIME_SECOND << "\n";
fout_rate_misc.flush();
}