/***************************************************************************
* nameservercpp  -  Program to serve of last name statistics
 *
* copyright : (C) 2009 by Jim Skon
*
* This program runs as a background server to a CGI program, providinging US Census
* Data on the frequency of names in response to requestes.  The rational for this 
* is to demonstrait how a background process can serve up information to a web program,
* saving the web program from the work of intiallizing large data structures for every
* call.
* 
* 
*
***************************************************************************/
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <map>
#include "fifo.h"

using namespace std;

/* Name data structure */
struct name_record
{
  string name;         // Last name
  string percent;      // Frequency of occurance of a given name
  string cumulative;   // Cummulative freqency of all name up to and including this name
  string rank;         // Rank of this Name in terms of frequency
};


char *receive_pipe = "namerequest";
char *send_pipe = "namereply";
map<string,name_record> lname_map;
map<string,name_record> fname_map;
map<string,name_record> mname_map;
map<string,name_record>::iterator it;

/*
 * Read the US Census data file "dist.all.last" and load it into an
 * in memory b+tree with name as the key.
 *
 * Return 1 if success, 0 if fail
 */
int createnamemap(map<string,name_record> &name_map ,string filename) {
	
  name_record namedata;
  fstream infile(filename.c_str());
  if (infile.good()) {
	while (1)
	  {
		infile >> namedata.name;
		infile >> namedata.percent;
		infile >> namedata.cumulative;
		infile >> namedata.rank;
		if (infile.fail()) break;
		name_map[namedata.name] = namedata;
		//cout << namedata.name + " " <<  namedata.percent << " " 
		//	 << namedata.cumulative << " " << namedata.rank << endl;
	  }
	infile.close();
	return(1);
  } else {
	return(0);
  }
}


/* Server main line,create name MAP, wait for and serve requests */
int main() {
  
  string message,name,percent,rank,type;
  name_record result;
  int fifo_status, pos;

  // Create the map of last name data
  if (createnamemap(lname_map,"dist.all.last") != 1) {
	cout << "Error Loading Database" << endl;
	exit(0);
  }
  // Create the map of male name data
  if (createnamemap(mname_map,"dist.male.first") != 1) {
	cout << "Error Loading Database" << endl;
	exit(0);
  }
  // Create the map of last name data
  if (createnamemap(fname_map,"dist.female.first") != 1) {
	cout << "Error Loading Database" << endl;
	exit(0);
  }
  
  cout << "Name data loaded!" << endl;

  // create the FIFOs for communication
  fifo_status = createfifo(receive_pipe);
  if (fifo_status != 1) {
	exit(1);
  }
  fifo_status = createfifo(send_pipe);
  if (fifo_status != 1) {
	exit(1);
  }
  
  /* Get a message from a client */
  message = recv(receive_pipe);
  
  while (name != string("$END")) {

	/* Parse the incoming message */
	/* Form:  $type*name  */
	pos=message.find_first_of("*");
	if (pos!=string::npos) {
	  type = message.substr(0,pos);
	  pos++;
	} else {
	  type = "$LAST";
	  pos = 0;
	}
	name = message.substr(pos,2000);
	cout << "Message: " << type << " : " << name << endl;

	// cout << "Client sent: " << name << endl;
	
	// Try to find the record
	if (type == "$NEXT") {
	  it++;
	  result = (*it).second;
	} else if (type == "$PREV") {
	  it--;
	  result = (*it).second;
	  
	} else  if (type == "$LAST") {
	  //Get the closest match
	  it = lname_map.lower_bound (name);
	  result = (*it).second;

	} else  if (type == "$MALE") {
	  //Get the closest match
	  it = mname_map.lower_bound (name);
	  result = (*it).second;

	} else  if (type == "$FEMALE") {
	  //Get the closest match
	  it = fname_map.lower_bound (name);
	  result = (*it).second;
	}

	name = result.name;
	percent = result.percent;
	rank = result.rank; 
	
	cout << " Results: " << name << "   " <<  percent << "%  Rank: " << rank  << endl;

	message = name + " " + percent + " " + rank;
	cout << "MESS: """ << message << """" << endl;
	send(message,send_pipe);
	message = "";
	message = recv(receive_pipe);

  }
}

-- JimSkon - 2011-03-02

Topic revision: r2 - 2011-03-08 - JimSkon
 
This site is powered by the TWiki collaboration platformCopyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback