🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #10506

problem with STL containers

#10506
From: zero
Date: Tue, 13 Apr 2004 12:54
467 lines
15221 bytes
First a short discription of my program.  I have a bot that connects to an 
internet chess server.  Whenever the bot logs on, it loads certain 
information from file, and puts it in STL containers (specifically sets & 
maps).  When disconnecting for any reason, the containers are converted to 
strings, and saved to disk, so they can be loaded again when the bot logs 
back on.  Periodically (triggered by a timer event), the bot mails a log to 
addresses contained in two of the maps.  The same timer is used to send the 
output buffer to the server (such a buffer is needed because if you send 
too much data at once, the server closes the connection as a security 
precaution).  There is also a mechanism that automatically re-connects the 
bot if it is disconnected.

Now the problem.  If the bot disconnects a few times, the log gets mailed 
normally the first time, but the next time it should be sent, all the 
containters are empty!  This of course means the log can't be sent, 'cause 
it gets the mail addresses from two of the containers.  I have no idea how 
or why this happens.

I'd appreciate any ideas on how to fix this.


Here are some parts of the code:


typedef std::map<AnsiString, int, myless> guideMap;
typedef std::map<AnsiString, AnsiString, myless> adrMap;
typedef std::set<AnsiString> headSet;

class GuideBot :public CNBot
{
private:
   int assistsAsked;
   int unansweredAssists;
   int guestAssists;
   guideMap theGuides;
   guideMap theAdmins;
   headSet theTDHeads;
   adrMap theAAdr;
   adrMap theGAdr;

   void handleLevel1Block();
   void processTell(AnsiString tellFrom, AnsiString theTell, UINT type);
   void findGAlias(AnsiString tellFrom, AnsiString theTell);
   void findTDAlias(AnsiString tellFrom, AnsiString theTell);
   void findAAlias(AnsiString tellFrom, AnsiString theTell);
   void loadAll();
   bool isHead(AnsiString user);
   bool isGHead(AnsiString user);
   bool isAHead(AnsiString user);
   bool isTDHead(AnsiString user);

public:
   GuideBot():CNBot() {}
   GuideBot(AnsiString asHandle, AnsiString asPassword):CNBot(asHandle, 
asPassword) {}
   GuideBot(AnsiString asFileName, TClientSocket *tcsConnection):CNBot
(asFileName, tcsConnection) {}
   GuideBot(AnsiString asFileName, TClientSocket *tcsConnection, AnsiString 
asSection):CNBot(asFileName, tcsConnection, asSection) {}
   ~GuideBot() {}

   void onConnect(TCustomWinSocket *Socket);
   void saveAll();
   void mailDump();
   int countingSince;
};

void __fastcall TForm1::ClientSocketConnect(TObject *Sender,
      TCustomWinSocket *Socket)
{
   Bot->onConnect(Socket);
   HandleEdit->Enabled = false;
   PasswordEdit->Enabled = false;
   CommandEdit->Enabled = true;
   if(Application->ShowMainForm)
      CommandEdit->SetFocus();
   TrayMessage(NIM_MODIFY);
}

void __fastcall TForm1::ClientSocketDisconnect(TObject *Sender,
      TCustomWinSocket *Socket)
{
   Output->Lines->Add("**** DISCONNECTED ****");
   HandleEdit->Enabled = true;
   PasswordEdit->Enabled = true;
   CommandEdit->Enabled = false;
   Bot->saveAll();
   if(Bot->stayConnected)
   {
      reconnectValue = 4000;
      reconnectTimer = 0;
   }
   TrayMessage(NIM_MODIFY);
}

void __fastcall TForm1::ClientSocketError(TObject *Sender,
      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   Bot->saveAll();
   ErrorCode = 0;
   ClientSocket->Close();

   reconnectValue = 4000;
   reconnectTimer = 0;
   TrayMessage(NIM_MODIFY);
}

void __fastcall TForm1::SendTimer(TObject *Sender)
{
   reconnectTimer++;
   if(reconnectTimer == reconnectValue)
   {
      reconnectValue = -1;
      Connect1Click(Sender);
   }

   myCounter++;
   if(Bot != NULL)
   {
      Bot->sendoBuffer(ClientSocket->Socket);
   }

   if(myCounter%120000 == 0)  // every hour
   {
      Bot->saveAll();
      Output->Clear();
   }
//   if(myCounter == 20160000) // every 7 days
   if(myCounter == 2000)
   {
      Bot->mailDump();
      myCounter = 0;
      Bot->countingSince = myCounter;
      Bot->saveAll();
   }
}

void GuideBot::onConnect(TCustomWinSocket *Socket)
{
   stayConnected = true;
   AnsiString command;
   command = setDGLevel();
   Socket->SendText(command + char(10));
   Socket->SendText(getHandle() + char(10));
   Socket->SendText(getPassword() + char(10));
   if(theGuides.begin() == theGuides.end())
      int lalala = 0;
   loadAll();
   if(theGuides.begin() == theGuides.end())
      int lalala = 0;
   countingSince = Form1->myCounter;
}

void GuideBot::loadAll()
{
   int iPos, answered;
   AnsiString theLine, guideName;

   TStringList *strList = new TStringList; // declare the list
   try // use the list in a try block
   {
      strList->LoadFromFile("guides.ini");
      for(int i = 0; i < strList->Count; i++)
      {
         theLine = strList->Strings[i];
         iPos = theLine.Pos("\'");
         guideName = theLine.SubString(1, iPos-1);
         theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1);
         answered = theLine.SubString(1, theLine.Length()).ToInt();
         theGuides.insert(guideMap::value_type(guideName, answered));
      }
      strList->LoadFromFile("admins.ini");
      for(int i = 0; i < strList->Count; i++)
      {
         theLine = strList->Strings[i];
         iPos = theLine.Pos("\'");
         guideName = theLine.SubString(1, iPos-1);
         theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1);
         answered = theLine.SubString(1, theLine.Length()).ToInt();
         theAdmins.insert(guideMap::value_type(guideName, answered));
      }
      strList->LoadFromFile("gheads.ini");
      for(int i = 0; i < strList->Count; i++)
      {
         theLine = strList->Strings[i];
         iPos = theLine.Pos("\'");
         guideName = theLine.SubString(1, iPos-1);
         theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1);
         theGAdr.insert(adrMap::value_type(guideName, theLine));
      }
      strList->LoadFromFile("aheads.ini");
      for(int i = 0; i < strList->Count; i++)
      {
         theLine = strList->Strings[i];
         iPos = theLine.Pos("\'");
         guideName = theLine.SubString(1, iPos-1);
         theLine = theLine.SubString(iPos+1, theLine.Length()-iPos+1);
         theAAdr.insert(adrMap::value_type(guideName, theLine));
      }
      strList->LoadFromFile("tdheads.ini");
      for(int i = 0; i < strList->Count; i++)
         theTDHeads.insert(strList->Strings[i]);
   }
   __finally
   {
      delete strList; // destroy the list object
   }

   TIniFile *times;
   times = new TIniFile(ExtractFilePath(Application->ExeName)+"times.ini");
   assistsAsked = times->ReadInteger("assists", "assistsAsked", 0);
   guestAssists = times->ReadInteger("assists", "guestAssists", 0);
   unansweredAssists = times->ReadInteger("assists", "unansweredAssists", 
0);
   delete times;
}

void GuideBot::saveAll()
{
   AnsiString aLine;

   int sec = 60*(Form1->myCounter - countingSince)/2000;
   int min = 0;
   int hour = 0;
   int day = 0;
   while(sec >= 60)
   {
      min = sec/60;
      sec -= min*60;
   }
   while(min >= 60)
   {
      hour = min/60;
      min -= hour*60;
   }
   while(hour >= 24)
   {
      day = hour/24;
      hour -= day*24;
   }

   TIniFile *times;
   times = new TIniFile(ExtractFilePath(Application->ExeName)+"times.ini");
   times->WriteInteger("guides", "sec", sec);
   times->WriteInteger("guides", "min", min);
   times->WriteInteger("guides", "hour", hour);
   times->WriteInteger("guides", "day", day);

   times->WriteInteger("assists", "assistsAsked", assistsAsked);
   times->WriteInteger("assists", "guestAssists", guestAssists);
   times->WriteInteger("assists", "unansweredAssists", unansweredAssists);

   delete times;

   times = new TIniFile(ExtractFilePath(Application->ExeName)
+"settings.ini");
   times->WriteInteger("Program", "myCounter", Form1->myCounter);
   delete times;

   TStringList *strList = new TStringList; // declare the list
   try // use the list in a try block
   {
      guideMap::iterator itr;
      for(itr = theGuides.begin(); itr != theGuides.end(); itr++)
      {
         aLine.sprintf("%s'%i", (*itr).first, (*itr).second);
         strList->Add(aLine);
      }
//      if(strList->Count > 0)
      strList->SaveToFile("guides.ini");
   }
   __finally
   {
      delete strList; // destroy the list object
   }
   strList = new TStringList;
   try // use the list in a try block
   {
      guideMap::iterator itr;
      for(itr = theAdmins.begin(); itr != theAdmins.end(); itr++)
      {
         aLine.sprintf("%s'%i", (*itr).first, (*itr).second);
         strList->Add(aLine);
      }
      strList->SaveToFile("admins.ini");
   }
   __finally
   {
      delete strList; // destroy the list object
   }
   strList = new TStringList;
   try // use the list in a try block
   {
      adrMap::iterator itr;
      for(itr = theGAdr.begin(); itr != theGAdr.end(); itr++)
      {
         aLine.sprintf("%s'%s", (*itr).first, (*itr).second);
         strList->Add(aLine);
      }
//      if(strList->Count > 0)
      strList->SaveToFile("gheads.ini");
   }
   __finally
   {
      delete strList; // destroy the list object
   }
   strList = new TStringList;
   try // use the list in a try block
   {
      adrMap::iterator itr;
      for(itr = theAAdr.begin(); itr != theAAdr.end(); itr++)
      {
         aLine.sprintf("%s'%s", (*itr).first, (*itr).second);
         strList->Add(aLine);
      }
//      if(strList->Count > 0)
      strList->SaveToFile("aheads.ini");
   }
   __finally
   {
      delete strList; // destroy the list object
   }
   strList = new TStringList;
   try // use the list in a try block
   {
      headSet::iterator itr;
      for(itr = theTDHeads.begin(); itr != theTDHeads.end(); itr++)
         strList->Add(*itr);
//      if(strList->Count > 0)
      strList->SaveToFile("tdheads.ini");
   }
   __finally
   {
      delete strList; // destroy the list object
   }
}

void GuideBot::mailDump()
{
   if(theGuides.begin() == theGuides.end())
   {
      loadAll();
      return;
   }
   TIniFile *times;
   int total = 0;
   int guides = 0;
   int sec;
   AnsiString ending1, ending2, aLine;
   guideMap::iterator itr1;
   adrMap::iterator itr2;
   TStringList *strList;

   Form1->MailSender->PostMessageA->Body->Clear();
   Form1->MailSender->PostMessageA->ToAddress->Clear();

   sec = 60*(Form1->myCounter - countingSince)/2000;
   int min = 0;
   int hour = 0;
   int day = 0;

   times = new TIniFile(ExtractFilePath(Application->ExeName)+"times.ini");
   sec += times->ReadInteger("guides", "sec", 0);
   min += times->ReadInteger("guides", "min", 0);
   hour += times->ReadInteger("guides", "hour", 0);
   day += times->ReadInteger("guides", "day", 0);
   delete times;
   while(sec >= 60)
   {
      min = sec/60;
      sec -= min*60;
   }
   while(min >= 60)
   {
      hour = min/60;
      min -= hour*60;
   }
   while(hour >= 24)
   {
      day = hour/24;
      hour -= day*24;
   }
   ending1.sprintf("Counting since %i days, %i hours, %i minutes and %i 
seconds.", day, hour, min, sec);
   ending2.sprintf("%i assists were asked, of which %i (%2.1f%%) were guest 
assists.  %i assists were left unanswered (%2.1f%%)", assistsAsked, 
guestAssists, ((assistsAsked == 0) ? 0.0 : ((float)guestAssists/(float)
assistsAsked)*100), unansweredAssists, ((assistsAsked == 0) ? 0.0 : 
((float)unansweredAssists/(float)assistsAsked)*100));

   strList = new TStringList();
   try
   {
   for(itr1 = theGuides.begin(); itr1 != theGuides.end(); itr1++)
   {
      aLine.sprintf("%s answered %i assists", (*itr1).first, 
(*itr1).second);
      Form1->MailSender->PostMessageA->Body->Add(aLine);
      strList->Add(aLine);
      guides++;
      total += (*itr1).second;
   }
   aLine.sprintf("%i Guides answered %i assists (%2.1f%% of answered 
assists)", guides, total, ((assistsAsked-unansweredAssists == 0) ? 0.0 : 
((float)total/(float)(assistsAsked-unansweredAssists))*100));
   Form1->MailSender->PostMessageA->Body->Add(aLine);
   strList->Add(aLine);
   Form1->MailSender->PostMessageA->Body->Add(ending1);
   strList->Add(ending1);
   Form1->MailSender->PostMessageA->Body->Add(ending2);
   strList->Add(ending2);
   Form1->MailSender->PostMessageA->Subject = "Guide assist stats";

   for(itr2 = theGAdr.begin(); itr2 != theGAdr.end(); itr2++)
      Form1->MailSender->PostMessageA->ToAddress->Add((*itr2).second);

   Form1->MailSender->Connect();
   Form1->MailSender->SendMail();
   Form1->MailSender->Disconnect();

   Form1->MailSender->PostMessageA->Body->Clear();
   Form1->MailSender->PostMessageA->ToAddress->Clear();

   guides = 0;
   total = 0;
   for(itr1 = theAdmins.begin(); itr1 != theAdmins.end(); itr1++)
   {
      aLine.sprintf("%s answered %i assists", (*itr1).first, 
(*itr1).second);
      Form1->MailSender->PostMessageA->Body->Add(aLine);
      strList->Add(aLine);
      guides++;
      total += (*itr1).second;
   }
   aLine.sprintf("%i Admins answered %i assists (%2.1f%% of answered 
assists)", guides, total, ((assistsAsked-unansweredAssists == 0) ? 0.0 : 
((float)total/(float)(assistsAsked-unansweredAssists))*100));
   Form1->MailSender->PostMessageA->Body->Add(aLine);
   strList->Add(aLine);
   Form1->MailSender->PostMessageA->Body->Add(ending1);
   strList->Add(ending1);
   Form1->MailSender->PostMessageA->Body->Add(ending2);
   strList->Add(ending2);
   Form1->MailSender->PostMessageA->Subject = "Admin assist stats";

   for(itr2 = theAAdr.begin(); itr2 != theAAdr.end(); itr2++)
      Form1->MailSender->PostMessageA->ToAddress->Add((*itr2).second);

   Form1->MailSender->Connect();
   Form1->MailSender->SendMail();
   Form1->MailSender->Disconnect();

   strList->SaveToFile("dump.txt");
   }
   __finally
   {
      delete strList;
   }

   guideMap::iterator itr;
   for(itr = theGuides.begin(); itr != theGuides.end(); itr++)
      (*itr).second = 0;
   theAdmins.clear();
   assistsAsked = 0;
   guestAssists = 0;
   unansweredAssists = 0;
}
Technical Details
Message-ID: <Xns94CA9752D647Azerothishi@195.130.132.68>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!news.glorb.com!ecngs!feeder.ecngs.de!feed1.news.be.easynet.net!ossa.telenet-ops.be!hebe.telenet-ops.be.POSTED!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 10cc67,d8f4075e4715e80c,start
X-Google-Attributes: gid10cc67,public
X-Google-ArrivalTime: 2004-04-13 05:54:32 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!news.glorb.com!ecngs!feeder.ecngs.de!feed1.news.be.easynet.net!ossa.telenet-ops.be!hebe.telenet-ops.be.POSTED!not-for-mail
Newsgroups: borland.public.cppbuilder.nativeapi
Subject: problem with STL containers
From: zero <zero@this.hi>
Organization: Your Company
Message-ID: <Xns94CA9752D647Azerothishi@195.130.132.68>
User-Agent: Xnews/5.04.25
Lines: 467
Date: Tue, 13 Apr 2004 12:54:31 GMT
NNTP-Posting-Host: 213.224.5.250
X-Complaints-To: abuse@telenet.be
X-Trace: hebe.telenet-ops.be 1081860871 213.224.5.250 (Tue, 13 Apr 2004 14:54:31 CEST)
NNTP-Posting-Date: Tue, 13 Apr 2004 14:54:31 CEST