Changeset 13294 for trunk/FACT++


Ignore:
Timestamp:
03/30/12 22:29:56 (13 years ago)
Author:
tbretz
Message:
Added an automatic reconnect under certain conditions.
Location:
trunk/FACT++/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/ConnectionUSB.cc

    r12540 r13294  
    6969// ------------------------ close --------------------------
    7070// close from another thread
    71 void ConnectionUSB::CloseImp(bool restart)
     71void ConnectionUSB::CloseImp(int64_t delay)
    7272{
    7373    if (IsConnected())
    74     {
    75         ostringstream str;
    76         str << "Closing connection to " << URL() << ".";
    77         Info(str);
    78     }
     74        Info("Closing connection to "+URL()+".");
    7975
    8076    // Close possible open connections
    8177    bs::error_code ec;
    8278    cancel(ec);
    83     if (ec)
    84         Error("Cancel async requests on "+URL()+": "+ec.message());
     79    if (ec && ec!=ba::error::basic_errors::bad_descriptor)
     80    {
     81        ostringstream msg;
     82        msg << "Cancel async requests on " << URL() << ": " << ec.message() << " (" << ec << ")";
     83        Error(msg);
     84    }
    8585
    8686    if (IsConnected())
     
    8888        close(ec);
    8989        if (ec)
    90             Error("Closing "+URL()+": "+ec.message());
     90        {
     91            ostringstream msg;
     92            msg << "Closing " << URL() << ": " << ec.message() << " (" << ec << ")";
     93            Error(msg);
     94        }
    9195        else
    92             Info("Connection closed succesfully.");
     96            Info("Closed connection to "+URL()+" succesfully.");
    9397    }
    9498
     
    96100    fInTimeout.cancel();
    97101    fOutTimeout.cancel();
     102    fConnectTimeout.cancel();
    98103
    99104    // Reset the connection status
     
    112117#endif
    113118
    114     if (!restart || IsConnecting())
     119    if (delay<0 || IsConnecting())
    115120        return;
    116121
    117122    // We need some timeout before reconnecting!
    118123    // And we have to check if we are alreayd trying to connect
    119     // We shoudl wait until all operations in progress were canceled
     124    // We should wait until all operations in progress were canceled
     125    fConnectTimeout.expires_from_now(boost::posix_time::seconds(delay));
     126    fConnectTimeout.async_wait(boost::bind(&ConnectionUSB::HandleReconnectTimeout, this, dummy::error));
     127}
     128
     129void ConnectionUSB::PostClose(int64_t delay)
     130{
     131    get_io_service().post(boost::bind(&ConnectionUSB::CloseImp, this, delay));
     132}
     133
     134void ConnectionUSB::HandleReconnectTimeout(const bs::error_code &error)
     135{
     136    if (error==ba::error::basic_errors::operation_aborted)
     137        return;
     138
     139    // 125: Operation canceled (bs::error_code(125, bs::system_category))
     140    if (error)
     141    {
     142        ostringstream str;
     143        str << "Reconnect timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
     144        Error(str);
     145
     146        CloseImp(-1);
     147        return;
     148    }
     149
     150
     151    if (is_open())
     152    {
     153        Error("HandleReconnectTimeout - "+URL()+" is already open.");
     154        return;
     155    }
     156
     157    // Check whether the deadline has passed. We compare the deadline
     158    // against the current time since a new asynchronous operation
     159    // may have moved the deadline before this actor had a chance
     160    // to run.
     161    if (fConnectTimeout.expires_at() > ba::deadline_timer::traits_type::now())
     162        return;
    120163
    121164    // Start trying to reconnect
     
    123166}
    124167
    125 void ConnectionUSB::PostClose(bool restart)
    126 {
    127     get_io_service().post(boost::bind(&ConnectionUSB::CloseImp, this, restart));
    128 }
    129168
    130169// ------------------------ write --------------------------
     
    141180        Error(str);
    142181
    143         CloseImp(false);
     182        CloseImp(-1);
    144183        return;
    145184    }
     
    161200    Error("fOutTimeout has expired, writing data to "+URL());
    162201
    163     CloseImp(false);
     202    CloseImp(-1);
    164203}
    165204
     
    172211        Error(str);
    173212
    174         CloseImp(false);
     213        CloseImp(-1);
    175214        return;
    176215    }
     
    329368fCharacterSize(8), fParity(parity::none), fStopBits(stop_bits::one),
    330369fFlowControl(flow_control::hardware),
    331 fInTimeout(ioservice), fOutTimeout(ioservice),
     370fInTimeout(ioservice), fOutTimeout(ioservice), fConnectTimeout(ioservice),
    332371fConnectionStatus(kDisconnected)
    333372{
  • trunk/FACT++/src/ConnectionUSB.h

    r12236 r13294  
    3636private:
    3737    boost::asio::deadline_timer   fOutTimeout;
     38    boost::asio::deadline_timer   fConnectTimeout;
    3839    std::deque<std::vector<uint8_t>> fOutQueue;
    3940
     
    5253
    5354protected:
    54     void CloseImp(bool restart=true);
     55    void CloseImp(int64_t delay=0);
    5556
    5657private:
     
    6061    void HandleWriteTimeout(const boost::system::error_code &error);
    6162    void HandleSentData(const boost::system::error_code& error, size_t);
     63    void HandleReconnectTimeout(const boost::system::error_code &error);
    6264
    6365    int Write(const Time &t, const std::string &txt, int qos=kInfo);
     
    7577
    7678    // ------------------------ close --------------------------
    77     void PostClose(bool restart=true);
     79    void PostClose(int64_t delay=0);
    7880
    7981    // ------------------------ write --------------------------
  • trunk/FACT++/src/biasctrl.cc

    r13258 r13294  
    5555    uint32_t fUpdateTime;
    5656    uint16_t fSyncTime;
     57    uint32_t fReconnectDelay;
    5758
    5859    int  fIsInitializing;
     
    6162
    6263    vector<uint64_t> fCounter;
     64
     65    Time fLastConnect;
    6366
    6467protected:
     
    274277
    275278private:
     279    void DelayedReconnect()
     280    {
     281        const Time now;
     282
     283        // If we have been connected without a diconnect for at least 60s
     284        // we can reset the delay.
     285        if (now-fLastConnect>boost::posix_time::seconds(60))
     286            fReconnectDelay = 1;
     287
     288        ostringstream msg;
     289        msg << "Automatic reconnect in " << fReconnectDelay << "s after being connected for ";
     290        msg << (now-fLastConnect).seconds() << "s";
     291        Info(msg);
     292
     293        CloseImp(fReconnectDelay);
     294        fReconnectDelay *= 2;
     295    }
     296
    276297    void HandleReceivedData(const vector<uint8_t> &buf, size_t bytes_received, int command, int send_counter)
    277298    {
     
    312333            (cmd==kExpertChannelSet && !CheckMessageLength(bytes_received, 3,                "CmdExpertChannelSet")))
    313334        {
    314             CloseImp(false);
     335            CloseImp(-1);
    315336            return;
    316337        }
     
    321342            if (!EvalAnswer(buf.data(), i, command))
    322343            {
    323                 CloseImp(false);
     344                DelayedReconnect();
    324345                return;
    325346            }
     
    345366            msg << "Corrupted answer: received wrap counter " << fWrapCounter  << " is not send counter " << send_counter << "%8.";
    346367            Error(msg);
    347             CloseImp(false);
     368
     369            DelayedReconnect();
    348370        }
    349371
     
    418440        if (command==kCmdGlobalSet)
    419441            fCounter[7]++;
    420 
    421442    }
    422443
     
    443464                Error(str);
    444465            }
    445             CloseImp(false);//err!=ba::error::basic_errors::operation_aborted);
     466            CloseImp(-1);//err!=ba::error::basic_errors::operation_aborted);
    446467            return;
    447468        }
     
    452473        {
    453474            Error("Number of received bytes not a multiple of 3, can't read data.");
    454             CloseImp(false);
     475            CloseImp(-1);
    455476            return;
    456477        }
     
    517538            Error(str);
    518539
    519             CloseImp(false);
     540            CloseImp(-1);
    520541            return;
    521542        }
     
    538559            {
    539560                Error("Synchronization attempt timed out.");
    540                 CloseImp(false);
     561                CloseImp(-1);
    541562                return;
    542563            }
     
    576597        fIsRamping      = false;
    577598
     599        fLastConnect = Time();
     600
    578601        // Send a single 0 (and possible two consecutive 0's
    579602        // to make sure we are in sync with the device)
     
    603626            Error(str);
    604627
    605             PostClose(false);
     628            CloseImp(-1);
    606629            return;
    607630        }
     
    763786            Error(str);
    764787
    765             PostClose(false);
    766788            fIsRamping = false;
     789            CloseImp(-1);
    767790            return;
    768791        }
     
    813836        fUpdateTime(3000),
    814837        fSyncTime(333),
     838        fReconnectDelay(1),
    815839        fIsRamping(false),
    816840        fWaitingForAnswer(-1),
     
    860884            ostringstream msg;
    861885            msg << "CheckChannelVoltage - Set voltage " << volt << "V of channel " << ch << " exeeds absolute limit of " << fVoltageMaxAbs << "V.";
    862             Error(msg);
     886            Warn(msg);
    863887            return false;
    864888        }
     
    14481472        return BIAS::kVoltageOn;
    14491473    }
     1474
     1475    void SetReconnectDelay(uint32_t delay=1)
     1476    {
     1477        fReconnectDelay = delay;
     1478    }
    14501479};
    14511480
     
    17451774    {
    17461775        // Close all connections
    1747         fBias.PostClose(false);
     1776        fBias.PostClose(-1);
    17481777
    17491778        /*
     
    17591788    {
    17601789        // Close all connections to supress the warning in SetEndpoint
    1761         fBias.PostClose(false);
     1790        fBias.PostClose(-1);
    17621791
    17631792        // Now wait until all connection have been closed and
     
    17691798
    17701799        // Now we can reopen the connection
    1771         fBias.PostClose(true);
     1800        fBias.SetReconnectDelay();
     1801        fBias.PostClose(0);
    17721802
    17731803        return T::GetCurrentState();
Note: See TracChangeset for help on using the changeset viewer.