libt2n, arnied: (gerd) set logging on existing connections too, show t2n-debugging...
[libt2n] / src / socket_wrapper.cpp
1 /***************************************************************************
2  *   Copyright (C) 2008 by Gerd v. Egidy                                   *
3  *   gve@intra2net.com                                                     *
4  *                                                                         *
5  *   This library is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Lesser General Public License version   *
7  *   2.1 as published by the Free Software Foundation.                     *
8  *                                                                         *
9  *   This library is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU Lesser General Public License for more details.                   *
13  *                                                                         *
14  *   You should have received a copy of the GNU Lesser General Public      *
15  *   License along with this program; if not, write to the                 *
16  *   Free Software Foundation, Inc.,                                       *
17  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18  ***************************************************************************/
19
20 #include <functional>
21 #include <string>
22
23 #include <socket_wrapper.hxx>
24
25 namespace libt2n
26 {
27
28 /// set logging for coming and current connections
29 void BasicSocketWrapper::set_logging(std::ostream *_logstream, log_level_values _log_level)
30 {
31     ConnectionWrapper::set_logging(_logstream,_log_level);
32
33     if (connection_established())
34         get_connection()->set_logging(_logstream,_log_level);
35 }
36
37
38 /// return active connection, create new tcp or unix connection if not existing
39 client_connection* BasicSocketWrapper::get_connection(void)
40 {
41     if (c.get() == NULL)
42     {
43         if (socket_type == tcp_s)
44             c=std::auto_ptr<socket_client_connection>
45                 (new socket_client_connection(port,server,connect_timeout_usec,max_retries,logstream,log_level));
46         else if (socket_type == unix_s)
47             c=std::auto_ptr<socket_client_connection>
48                 (new socket_client_connection(path,connect_timeout_usec,max_retries,logstream,log_level));
49     }
50
51     return c.get();
52 }
53
54 /// try to reconnect max_retries time if we encounter a t2n_communication_error 
55 /// during execution of the command
56 bool ReconnectSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
57 {
58     int tries=0;
59
60     while(true)
61     {
62         try
63         {
64             // we always reconnect if something went wrong before:
65             // makes sure the buffers are clean of half-sent packets etc.
66             if (tries > 0)
67                 c->reconnect();
68
69             f();
70             // we were successful
71             return true;
72         }
73         catch(t2n_connect_error &e)
74         {
75             // reconnect already tries max_tries times to reconnect: we are done if that failed
76             throw(e);
77         }
78         catch(t2n_communication_error &e)
79         {
80             // aborts the loop with an exception after max_retries iterations
81             // retries means that the first try doesn't count: use >
82             if (tries > max_retries)
83                 throw(e);
84
85             // otherwise ignore the exception and reconnect in the next iteration
86         }
87         catch(...)
88         {
89             throw;
90         }
91
92         tries++;
93     }
94
95     return false;
96 }
97
98 /// return active connection, return a dummy-connection if we can't establish one
99 client_connection* ReconnectIgnoreFailureSocketWrapper::get_connection(void)
100 {
101     client_connection* tmp=BasicSocketWrapper::get_connection();
102
103     if (tmp->is_closed())
104     {
105         // throw away the closed connection...
106         c.reset();
107         // ...return the dummy one instead
108         tmp=&dc;
109     }
110
111     return tmp;
112 }
113
114 /// try to execute the command, may ignore the command if server not available
115 bool ReconnectIgnoreFailureSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
116 {
117     if (!connection_established())
118     {
119         // dummy connection is in place: try to establish a real one
120         client_connection* tmp=get_connection();
121
122         if (tmp != &dc)
123         {
124             // success! we've got a real connection
125             stubBase->replace_connection(tmp);
126         }
127     }
128
129     // only try to handle the call if we've got a real connection
130     if (connection_established())
131     {
132         try
133         {
134             ReconnectSocketWrapper::handle(stubBase,f);
135             return true;
136         }
137         catch(t2n_communication_error &e)
138         {
139             // ignore
140         }
141         catch(...)
142         {
143             throw;
144         }
145     }
146
147     return false;
148 }
149
150 }