www.pudn.com > net_oss.rar > collection.cc
#include "collection.h"
using namespace std;
collection::collection()
{
last.ut_type = -1;
key = ftok("/dev/null",0);
if((msgid = msgget(key,0))== -1){
msgid = msgget(key,IPC_CREAT | IPC_EXCL | 0600);
if(msgid < 0) exit(-1);
}
}
collection::~collection()
{
dump_lastposition();
dump_unfinished();
multimap::iterator it;
for(it = login.begin(); it!=login.end();it++)
delete it->second;
for(it = logoff.begin(); it!=logoff.end();it++)
delete it->second;
list::iterator it2;
for(it2 = data.begin(); it2 != data.end();it2++)
delete *it2;
}
void collection::setdefault()
{
backup_file = BACKUP;
position_file = POSITION;
system_file = SYSTEM;
}
string collection::localIP()
{
static string ip = NOT_ASSIGNED;
if(ip == NOT_ASSIGNED)
{
char* name = new char[255];
gethostname(name,255);
hostent* h = gethostbyname(name);
inet_ntop(AF_INET,h->h_addr_list[0],name,16);
ip = name;
delete name;
}
return ip;
}
void collection::loadconfiguration(const char* file)
{
if(file == NULL)
{
setdefault();
}
else
{
if(access(file,F_OK)<0){
setdefault();
}
else
{
ifstream fin(file);
if(!fin)
{
setdefault();
}
else
{
while(!fin.eof())
{
char buf[MAX_BUF];
memset(buf,0x00,MAX_BUF);
fin.getline(buf,MAX_BUF);
string input = buf;
if(input.find(COMMENT_TAG,0) != input.npos) continue;
if(input.find(BACKUP_TAG,0) != input.npos){
backup_file = input.erase(0,input.find(DELIMITER_TAG,0)+1);
}
if(input.find(POSITION_TAG,0) != input.npos){
position_file = input.erase(0,input.find(DELIMITER_TAG,0)+1);
}
if(input.find(SYSTEM_TAG,0) != input.npos){
system_file = input.erase(0,input.find(DELIMITER_TAG,0)+1);
}
}//end of while(!fin.eof())
fin.close();
}//end of else [if(!fin)]
}//end of else [if(access(file,F_OK)<0)]
}//end of else [if(file == NULL)]
#ifdef __DEBUG
cout << " BACKUP =" << backup_file << endl;
cout << " POSITION =" << position_file << endl;
cout << " SYSTEM =" << system_file << endl;
#endif
}//end of function
void collection::retrieve()
{
utmpx* tmp;
#ifdef __TIMER
_timer.start("collection::retrieve");
#endif
//check backup
if(access(backup_file.c_str(),F_OK)==0){
ifstream ifs(backup_file.c_str(),ios::in | ios::binary);
while(1)
{
utmpx* p;
p = new utmpx;
ifs.read((char*)p,sizeof(utmpx));
if(ifs.eof()) break;
login.insert(pair(p->ut_pid,p));
}
ifs.close();
}
//load system file
//set position
if(access(position_file.c_str(),F_OK)==0)
{
utmpxname(position_file.c_str());
setutxent();
utmpx* pos = new utmpx;
tmp = getutxent();
memcpy(pos,tmp,sizeof(utmpx));
#ifdef __DEBUG
show(pos);
#endif
endutxent();
utmpxname(system_file.c_str());
setutxent();
tmp = getutxline(pos);
#ifdef __DEBUG
cout << endl << endl;
show(tmp);
#endif
while(1)
{
if(tmp == NULL) {
setutxent();
break;
}
else if(tmp->ut_tv.tv_sec != pos->ut_tv.tv_sec)
{
getutxent();
tmp = getutxline(pos);
}
else break;
}
#ifdef __DEBUG
cout << " ------------ " << endl;
show(tmp);
#endif
delete pos;
}
else
{
utmpxname(system_file.c_str());
setutxent();
}
while((tmp = getutxent()) != NULL)
{
if(tmp->ut_type == USER_PROCESS)
{
utmpx* t = new utmpx;
memcpy(t,tmp,sizeof(utmpx));
login.insert(pair(tmp->ut_pid,t));
memcpy(&last,tmp,sizeof(last));
}
if(tmp->ut_type == DEAD_PROCESS)
{
utmpx* t = new utmpx;
memcpy(t,tmp,sizeof(utmpx));
logoff.insert(pair(tmp->ut_pid,t));
}
#ifdef __DEBUG
printf("\x0d\tLogin: %d\tLogoff: %d",login.size(), logoff.size());
#endif
}
#ifdef __DEBUG
utmpx* u = &last;
show(u);
cout << endl;
#endif
endutxent();
#ifdef __TIMER
_timer.end();
_timer.show();
#endif
}
int collection::processing()
{
#ifdef __DEBUG
int s = login.size();
int count = 0;
#endif
multimap::iterator it = login.begin();
#ifdef __TIMER
_timer.start("collection::processing");
#endif
for(it = login.begin();it != login.end();it++)
{
time_t min = -1;
multimap::iterator start,end,matched;
start = logoff.lower_bound(it->first);
end = logoff.upper_bound(it->first);
matched = logoff.end();
if(start == end && start == logoff.end()) continue;
while(start != end)
{
if(start->second->ut_tv.tv_sec > it->second->ut_tv.tv_sec
&& !strcmp(start->second->ut_name,it->second->ut_name))
{
if(min == -1) {
matched = start;
min = start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec;
}
else
{
if(start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec < min &&
start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec > 0) {
min = start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec;
matched = start;
}
}
}
start++;
}
if(matched != logoff.end())
{
store(it->second,min);
#ifdef __DEBUG
count++;
#endif
login.erase(it);
it--;
logoff.erase(matched);
}
}
#ifdef __DEBUG
printf("\nThere are %d matched. \n", count);
#endif
////sending finish
/*
msg _msg;
_msg.mtype = END;
while(msgsnd(msgid,&_msg,sizeof(_msg),0)) sleep(1);
*/
#ifdef __TIMER
_timer.end();
_timer.show();
cout << " there are still " << login.size() << " login no matched." << endl;
#endif
return 0;
}
void collection::store(const utmpx* u, const time_t& t)
{
info inf;
memset(&inf,0x00,sizeof(inf));
strcpy(inf.user_name,u->ut_name);
inf.start_time = u->ut_tv.tv_sec;
inf.duration = t;
strcpy(inf.IP,localIP().c_str());
//data.push_back(inf);
msg _msg;
_msg.mtype = 1;
memcpy(&_msg.inf,&inf,sizeof(info));
#ifdef __DEBUG
/*cout << " ***************** " << endl;
cout << inf.user_name << "\t" << inf.duration << "\t";
cout << inf.IP << endl;
cout << " ***************** " << endl;
*/
#endif
while(msgsnd(msgid,&_msg,sizeof(_msg),IPC_NOWAIT)) sleep(1);
}
void collection::dump_unfinished()
{
remove(backup_file.c_str());
string cmd = "touch " + string(backup_file);
system(cmd.c_str());
int fd = open(backup_file.c_str(),O_WRONLY);
if(fd < 0) {
#ifdef __DEBUG
cout << " cannot open file for output." << endl;
#endif
return;
}
for(multimap::iterator it = login.begin(); it != login.end(); it++)
{
if(write(fd,(char*)(it->second),sizeof(utmpx))<0)
{
#ifdef __DEBUG
perror("write");
#endif
}
}
close(fd);
}
void collection::dump_lastposition()
{
if(last.ut_type == -1) return;
remove(position_file.c_str());
string cmd = "touch " + string(position_file);
system(cmd.c_str());
utmpxname(position_file.c_str());
setutxent();
pututxline(&last);
endutxent();
}
void collection::show(struct utmpx*& tmp)
{
cout << tmp->ut_user << endl;
cout << tmp->ut_id << endl;
cout << tmp->ut_line << endl;
cout << tmp->ut_pid << endl;
cout << tmp->ut_type << endl;
cout << tmp->ut_tv.tv_sec << endl;
}
void collection::start_cllection(){
retrieve();
processing();
}
void collection::receive()
{
msg _msg;
while(msgrcv(msgid,&_msg,sizeof(msg),0,0)>0)
{
info * _inf;
_inf = new info;
if(_msg.mtype == END) break;
memcpy(_inf,&_msg.inf,sizeof(info));
#ifdef __DEBUG
//cout << _inf->user_name << "\t" << _inf->duration << "\t";
//cout << _inf->IP << endl;
#endif
data.push_back(_inf);
}
#ifdef __DEBUG
cout << " Threre are " << data.size() << " records matched" << endl;
ofstream fout("result.txt");
fout << " Threre are " << data.size() << " records matched" << endl;
for(list::iterator it = data.begin(); it!= data.end(); it++)
{
fout << (*it)->user_name << "\t" << (*it)->duration << "\t";
fout << (*it)->IP << endl;
}
fout.close();
#endif
}