Modifications for correct use of timeout and slightly improved error/debug output...
[u/mrichter/AliRoot.git] / SHUTTLE / DCSClient / AliDCSClient.cxx
index 04c73f7..a1456b0 100644 (file)
 
 /*
 $Log$
+Revision 1.8  2007/10/17 17:43:02  acolla
+nextMessage removed from client
+
+Revision 1.7  2007/10/16 15:02:20  jgrosseo
+fixed bug if zero values collected
+
+Revision 1.6  2007/10/16 14:37:16  jgrosseo
+changing to AMANDA protocol version 2
+
+Revision 1.5  2007/10/05 12:40:55  acolla
+
+Result error code added to AliDCSClient data members (it was "lost" with the new implementation of TMap* GetAliasValues and GetDPValues).
+
+Revision 1.4  2007/09/14 16:46:14  jgrosseo
+1) Connect and Close are called before and after each query, so one can
+keep the same AliDCSClient object.
+2) The splitting of a query is moved to GetDPValues/GetAliasValues.
+3) Splitting interval can be specified in constructor
+
+Revision 1.3  2007/09/11 16:42:02  jgrosseo
+starting modifying AliDCSClient to transparently switch between single and multi query
+first step: same alidcsclient can be used for several queries
+
+Revision 1.2  2007/06/09 13:01:09  jgrosseo
+Switching to retrieval of several DCS DPs at a time (multiDPrequest)
+
 Revision 1.1  2006/11/06 14:22:47  jgrosseo
 major update (Alberto)
 o) reading of run parameters from the logbook
@@ -81,6 +107,7 @@ some more descriptions added
 #include <TMap.h>
 #include <TObjString.h>
 #include <TSystem.h>
+#include <TTimeStamp.h>
 
 ClassImp(AliDCSClient)
 
@@ -90,12 +117,13 @@ const char* AliDCSClient::fgkTimeoutString = "Timeout";
 const char* AliDCSClient::fgkBadMessageString = "BadMessage";
 const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
 const char* AliDCSClient::fgkServerErrorString = "ServerError";
+const char* AliDCSClient::fgkUnknownDPString = "UnknownAlias/DP";
 
 //______________________________________________________________________
 AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
-       Int_t retries):
-       fSocket(NULL), fTimeout(timeout), fRetries(retries),
-       fServerErrorCode(AliDCSMessage::kNoneError), fServerError("")
+       Int_t retries, Int_t multiSplit):
+       fSocket(NULL), fHost(host), fPort(port), fTimeout(timeout), fRetries(retries), fMultiSplit(multiSplit),
+       fServerErrorCode(AliDCSMessage::kNoneError), fServerError(""), fResultErrorCode(0)
 {
        // 
        // host: DCS server host
@@ -105,54 +133,48 @@ AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
        // retries: the number of retries after which the connection is 
        //              is considered as invalid and error is returned.
        //
-
-       Int_t tries = 0;        
-       
-       while (tries < fRetries) {
-               fSocket = new TSocket(host, port);
-               if (fSocket->IsValid()) {
-                       AliDebug(1, Form("Connected to %s:%d", host, port));
-                       fSocket->SetOption(kNoBlock, 1);
-                       break;
-               }
-
-               AliDebug(1, Form("Connection timeout! tries <%d> ...", tries));
-
-               delete fSocket;
-               fSocket = NULL;
-
-               gSystem->Sleep(fTimeout);
-               tries ++;
-       }
 }
 
 //______________________________________________________________________
-AliDCSClient::AliDCSClient(const AliDCSClient& /*other*/):
-       TObject(), fSocket(NULL), fTimeout(0), fRetries(0),
-       fServerErrorCode(AliDCSMessage::kNoneError), fServerError("")
-
+AliDCSClient::~AliDCSClient() 
 {
-// copy constructor (not implemented)
+       // destructor
 
+       Close();
 }
 
 //______________________________________________________________________
-AliDCSClient &AliDCSClient::operator=(const AliDCSClient& /*other*/)
+Bool_t AliDCSClient::Connect()
 {
-// assignment operator (not implemented)
-
-return *this;
-}
+       //  connects to the AMANDA server
+       
+       Close();
+       
+       Int_t tries = 0;
+       Int_t sleeptime=300;
+       
+       while (tries < fRetries) 
+       {
+               fSocket = new TSocket(fHost, fPort);
+                       
+               if (fSocket && fSocket->IsValid()) 
+               {
+                       AliDebug(1, Form("%s  *** Connected to %s:%d", TTimeStamp(time(0)).AsString("s"), fHost.Data(), fPort));
+                       fSocket->SetOption(kNoBlock, 1);
+                       return kTRUE;
+               }
 
-//______________________________________________________________________
-AliDCSClient::~AliDCSClient() 
-{
-// destructor
+               AliError(Form("%d *** Connection to AMANDA server failed! Tried <%d> times ...", tries+1));
+               if(tries<fRetries-1) AliInfo(Form("%d *** Waiting %d seconds before next retry.", sleeptime));
 
-       if (fSocket) {
-               Close();
                delete fSocket;
+               fSocket = NULL;
+
+               gSystem->Sleep(sleeptime);
+               tries ++;
        }
+       
+       return kFALSE;
 }
 
 //______________________________________________________________________
@@ -165,7 +187,7 @@ Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
 
         while (sentSize < size && tries < fRetries) {
 
-                Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout);
+                Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout*1000); //timeout for TSocket::Select is in msec
 
                 if (sResult == 0) {
                        AliDebug(1, Form("Timeout! tries <%d> ...", tries));
@@ -207,9 +229,10 @@ Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
 
         while (receivedSize < size && tries < fRetries) {
 
-                Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout);
+                Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout*1000); //timeout for TSocket::Select is in msec
 
                 if (sResult == 0) {
+                       AliDebug(1, Form("Time when timing out: %s   Timeout value: %d seconds",TTimeStamp(time(0)).AsString("s"),fTimeout));
                         AliDebug(1, Form("Timeout! tries <%d> ...", tries));
                         tries ++;
                         continue;
@@ -253,7 +276,7 @@ Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
 }
 
 //______________________________________________________________________
-Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message) 
+Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
 {
 // receive message from the DCS server
        
@@ -291,17 +314,19 @@ Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
 Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
        const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
 {
-// get array of DCS values from the DCS server
-// reqString: alias name
-// startTime, endTime: start time and end time of the query
-// result: contains the array of retrieved AliDCSValue's
+       // get array of DCS values from the DCS server
+       // reqString: alias name
+       // startTime, endTime: start time and end time of the query
+       // result: contains the array of retrieved AliDCSValue's
 
+       Connect();
+       
        if (!IsConnected()) {
                AliError("Not connected!");
                return AliDCSClient::fgkBadState;
        }
 
-       Int_t sResult;
+       Int_t sResult = -1;
        AliDCSMessage requestMessage;
        requestMessage.CreateRequestMessage(reqType, startTime, endTime,
                        reqString);
@@ -313,11 +338,20 @@ Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
                return sResult;
        }
 
-       sResult = ReceiveValueSet(result);
+       Int_t receivedValues = 0;
+
+       while (1)
+       {
+               Int_t tmp = 0;
+               sResult = ReceiveValueSet(result, tmp);
+               if (sResult <= 0)
+                       break;
+               receivedValues += sResult;
+       }
 
        Close();
 
-       return sResult;
+       return receivedValues;
 }
 
 //______________________________________________________________________
@@ -331,139 +365,178 @@ TMap* AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
        // Result: map containing the array of alias names. It will be filled with
        // the values retrieved for each alias
 
-       if (!IsConnected()) {
-               AliError("Not connected!");
-               return 0;
-       }
-
-       AliDCSMessage multiRequestMessage;
-       multiRequestMessage.CreateMultiRequestMessage(reqType,
-                       startTime, endTime);
+       TMap* result = new TMap;
+       result->SetOwner(1);
 
        if (endIndex < 0 || endIndex > list->GetEntries())
                endIndex = list->GetEntries();
-                       
-       for (Int_t i=startIndex; i<endIndex; i++)
-       {
-               TObjString* aRequest = (TObjString*) list->At(i);
-               if (!multiRequestMessage.AddRequestString(aRequest->String()))
-                       return 0;
-       }
-       
-       Int_t sResult = 0;
-       if ((sResult = SendMessage(multiRequestMessage)) < 0)
-       {
-                AliError(Form("Can't send request message! Reason: %s",
-                        GetErrorString(sResult)));
-                Close();
-                return 0;
-        }
-
-       TMap* result = new TMap;
-       result->SetOwner(1);
 
-       for (Int_t i=startIndex; i<endIndex; i++)
+       for (Int_t subsetBegin = startIndex; subsetBegin < endIndex; subsetBegin += fMultiSplit)
        {
-               TObjString* aRequest = (TObjString*) list->At(i);
-               
-               TObjArray* resultSet = new TObjArray();
-               resultSet->SetOwner(1);
+               Connect();
 
-               if ((sResult = ReceiveValueSet(resultSet)) < 0) {
-                       AliError(Form("Can't get values for %s!" ,
-                               aRequest->String().Data()));
-
-                       delete resultSet;
-                       result->DeleteValues();
+               if (!IsConnected())
+               {
+                       AliError("Not connected!");
                        delete result;
+                       fResultErrorCode = fgkBadState;
                        return 0;
                }
 
-               result->Add(aRequest, resultSet);
-       }
-
-       Close();
-
-       return result;
-}
+               Int_t subsetEnd = subsetBegin + fMultiSplit;
+               if (subsetEnd > endIndex)
+                   subsetEnd = endIndex;
        
-//______________________________________________________________________
-Int_t AliDCSClient::ReceiveValueSet(TObjArray* result)
-{
-// receive set of values 
-
-       Int_t sResult;
+               AliDCSMessage requestMessage;
+               if (fMultiSplit == 1)
+               {
+                       // single dp request
+
+                       TObjString* aRequest = (TObjString*) list->At(subsetBegin);
+                       requestMessage.CreateRequestMessage(reqType, startTime, endTime, aRequest->String());
+               }
+               else
+               {
+                       // multi dp request
+
+                       requestMessage.CreateMultiRequestMessage(reqType,
+                               startTime, endTime);
+
+                       for (Int_t i=subsetBegin; i<subsetEnd; i++)
+                       {
+                               TObjString* aRequest = (TObjString*) list->At(i);
+                               if (!requestMessage.AddRequestString(aRequest->String()))
+                               {
+                                       delete result;
+                                       fResultErrorCode = fgkBadMessage;
+                                       return 0;
+                               }
+                       }
+               }
 
-       AliDCSMessage responseMessage;
-       if ((sResult = ReceiveMessage(responseMessage)) < 0) {
-               AliError(Form("Can't receive response message! Reason: %s",
-                       GetErrorString(sResult)));
-               return sResult;
-       }       
+               if ((fResultErrorCode = SendMessage(requestMessage)) < 0)
+               {
+                       AliError(Form("Can't send request message! Reason: %s",
+                               GetErrorString(fResultErrorCode)));
+                       Close();
+                       delete result;
+                       return 0;
+               }
 
-       UInt_t valueCount;
+               while (1)
+               {
+                       TObjArray* resultSet = new TObjArray();
+                       resultSet->SetOwner(1);
 
-       if (responseMessage.GetType() == AliDCSMessage::kCount) {
-               valueCount = responseMessage.GetCount();
+                       Int_t ownerIndex = -1;
+                       fResultErrorCode = ReceiveValueSet(resultSet, ownerIndex);
 
-       } else if (responseMessage.GetType() == AliDCSMessage::kError) {
-               fServerErrorCode = responseMessage.GetErrorCode();
-               fServerError = responseMessage.GetErrorString();
+                       if (fResultErrorCode < 0)
+                       {
+                               if (fResultErrorCode == fgkUnknownDP)
+                               {
+                                       AliError(Form("%s",fServerError.Data()));
+                               }
+                               
+                               AliError("Can't get values");
 
-               return AliDCSClient::fgkServerError;
+                               delete resultSet;
+                               result->DeleteValues();
+                               delete result;
+                               return 0;
+                       }
 
-       } else {
-               AliError("Bad message type received!"); 
-               return AliDCSClient::fgkBadMessage;
-       }
+                       if (ownerIndex < 0)
+                       {
+                               // no more values
+                               delete resultSet;
+                               break;
+                       }
 
-       UInt_t receivedValues = 0;
+                       TObjString* aRequest = (TObjString*) list->At(ownerIndex + subsetBegin);
+                       //AliInfo(Form("Received %d values for entry %d, that is %s", resultSet->GetEntries(),
+                       //      ownerIndex + subsetBegin, aRequest->String().Data()));
+
+                       TObjArray* target = dynamic_cast<TObjArray*> (result->GetValue(aRequest));
+                       if (target)
+                       {
+                               target->AddAll(resultSet);
+                               //AliInfo(Form("Now we have %d entries", target->GetEntries()));
+                               resultSet->SetOwner(0);
+                               delete resultSet;
+                       }
+                       else
+                               result->Add(aRequest, resultSet);
+               }
 
-       AliDCSValue::Type valueType = AliDCSValue::kInvalid;
+               Close();
 
-       while (receivedValues < valueCount) {
+               Int_t nValues = 0;
+               TObjArray* example = (TObjArray*) result->GetValue(list->At(subsetBegin));
+               if (example)
+                       nValues = example->GetEntries();
+               AliInfo(Form("Retrieved entries %d..%d (total %d..%d); E.g. %s has %d values collected",
+                       subsetBegin, subsetEnd-1, startIndex, endIndex-1, list->At(subsetBegin)->GetName(), nValues));
+       }
 
-                AliDCSMessage message;
+       return result;
+}
+       
+//______________________________________________________________________
+Int_t AliDCSClient::ReceiveValueSet(TObjArray* result, Int_t& ownerIndex)
+{
+       // receive set of values
 
-                if ((sResult = ReceiveMessage(message)) < 0) {
-                        AliError(Form("Can't receive message! Reason: %s",
-                               GetErrorString(sResult)));
-                        return sResult;
-                }
+       AliDCSMessage message;
+       Int_t sResult = ReceiveMessage(message);
+       if (sResult < 0)
+       {
+               AliError(Form("Can't receive message! Reason: %s", GetErrorString(sResult)));
+               return sResult;
+       }
 
-                if (message.GetType() == AliDCSMessage::kResultSet) {
+       if (message.GetType() == AliDCSMessage::kResultSet)
+       {
+               // this was the last message
+               ownerIndex = message.GetOwnerIndex();
+               if (ownerIndex < 0)
+                       return 0;
 
-                       if (valueType == AliDCSValue::kInvalid) {
-                               valueType = message.GetValueType();
-                       } else {
-                               if (valueType != message.GetValueType()) {
-                                       AliError("Unexpected value type!");
-                                       return AliDCSClient::fgkBadMessage;
-                               }
-                       }
+               sResult = message.GetValues(result);
 
-                       receivedValues += message.GetValues(result);
+//             AliDCSMessage nextMessage;
+//             nextMessage.CreateNextMessage();
+// 
+//             if ((fResultErrorCode = SendMessage(nextMessage)) < 0)
+//             {
+//                     AliError(Form("Can't send next message! Reason: %s",
+//                             GetErrorString(fResultErrorCode)));
+//                     Close();
+//                     return AliDCSClient::fgkCommError;
+//             }
 
-                       if (receivedValues > valueCount) {
-                               AliError("Message contains more values than expected!");
-                               return AliDCSClient::fgkBadMessage;
-                       }
+               return sResult;
+       }
+       else if (message.GetType() == AliDCSMessage::kError)
+       {
+               fServerErrorCode = message.GetErrorCode();
+               fServerError = message.GetErrorString();
 
-               } else if (message.GetType() == AliDCSMessage::kError) {
-                               fServerErrorCode = 
-                                       responseMessage.GetErrorCode();
-                               fServerError = responseMessage.GetErrorString();
+               return AliDCSClient::fgkServerError;
+       }
+       
+       else if (message.GetType() == AliDCSMessage::kUnknownDP)
+       {
+               fServerError = message.GetErrorString();
 
-                               return AliDCSClient::fgkServerError;
-               } else {
-                        AliError("Bad message type received!");
-                        return AliDCSClient::fgkBadMessage;
-                }       
-        }       
+               return AliDCSClient::fgkUnknownDP;
+       }
        
-       return receivedValues;
+
+       AliError("Bad message type received!");
+       return AliDCSClient::fgkBadMessage;
 }
-               
+
 //______________________________________________________________________
 Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
                                UInt_t endTime, TObjArray* result)
@@ -560,7 +633,10 @@ void AliDCSClient::Close()
        //
 
        if (fSocket) {
+               AliDebug(1, Form("%s  *** Closing connection to %s:%d", TTimeStamp(time(0)).AsString("s"), fHost.Data(), fPort));
                fSocket->Close();
+               delete fSocket;
+               fSocket = 0;
        }
 }
 
@@ -591,6 +667,9 @@ const char* AliDCSClient::GetErrorString(Int_t code)
 
                case AliDCSClient::fgkServerError:
                        return AliDCSClient::fgkServerErrorString;
+               
+               case AliDCSClient::fgkUnknownDP:
+                       return AliDCSClient::fgkUnknownDPString;
 
                default:
                        AliErrorGeneral("AliDCSClient::GetErrorString",