1 /******************************************************************************
2 
3     Fiber Select Protocol I/O Exception Classes
4 
5     Copyright:
6         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
7         All rights reserved.
8 
9     License:
10         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
11         Alternatively, this file may be distributed under the terms of the Tango
12         3-Clause BSD License (see LICENSE_BSD.txt for details).
13 
14  ******************************************************************************/
15 
16 module ocean.io.select.protocol.generic.ErrnoIOException;
17 
18 
19 import ocean.meta.types.Qualifiers;
20 
21 import ocean.sys.ErrnoException;
22 
23 import ocean.io.model.IConduit: ISelectable;
24 
25 import core.stdc.errno: errno;
26 
27 /******************************************************************************
28 
29     IOWarning class; to be thrown on end-of-flow conditions where neither errno
30     nor getsockopt() indicate an error.
31 
32  ******************************************************************************/
33 
34 class IOWarning : ErrnoException
35 {
36     /**************************************************************************
37 
38         File handle of I/O device
39 
40      **************************************************************************/
41 
42     public int handle ()
43     {
44         return this.conduit.fileHandle;
45     }
46 
47     /**************************************************************************
48 
49         Select client hosting the I/O device
50 
51      **************************************************************************/
52 
53     protected ISelectable conduit;
54 
55     /**************************************************************************
56 
57         Constructor
58 
59         Params:
60             conduit =  Select client hosting the I/O device
61 
62      **************************************************************************/
63 
64     this ( ISelectable conduit )
65     {
66         this.conduit = conduit;
67     }
68 }
69 
70 class IOError : IOWarning
71 {
72     /**************************************************************************
73 
74         Constructor
75 
76         Params:
77             client =  Select client hosting the I/O device
78 
79      **************************************************************************/
80 
81     this ( ISelectable conduit )
82     {
83         super(conduit);
84     }
85 
86     /**************************************************************************
87 
88         Obtains the current error code of the underlying device of the conduit.
89 
90         To be overridden by a subclass for I/O devices that support querying a
91         device specific error status (e.g. sockets with getsockopt()).
92 
93         Returns:
94             the current error code of the underlying device of the conduit.
95 
96      **************************************************************************/
97 
98     public int error_code ( )
99     {
100         return 0;
101     }
102 
103     /**************************************************************************
104 
105         Checks the error state of the underlying device of the conduit and
106         throws this instance on error.
107 
108         This will in fact only happen if a subclass overrides error_code().
109 
110         Params:
111             msg    = message
112             file   = source code file name
113             line   = source code line
114 
115         Throws:
116             this instance if an error is reported for the underlying device of
117             the conduit.
118 
119      **************************************************************************/
120 
121     public void checkDeviceError ( istring msg, istring file = __FILE__,
122                                    int line = __LINE__ )
123     {
124         int device_errnum = this.error_code;
125 
126         if (device_errnum)
127         {
128             throw this.set(device_errnum, msg, file, line);
129         }
130     }
131 }
132 
133 class SocketError : IOError
134 {
135     import ocean.io.device.Conduit : ISelectable;
136     import ocean.sys.socket.model.ISocket;
137 
138     /**************************************************************************
139 
140         Constructor
141 
142         Params:
143             conduit = I/O device, the file descriptor is expected to be
144                       associated with a socket.
145 
146      **************************************************************************/
147 
148     this ( ISelectable conduit )
149     {
150         super(conduit);
151     }
152 
153     /**************************************************************************
154 
155         Returns:
156             the current socket error code.
157 
158      **************************************************************************/
159 
160     override int error_code ( )
161     {
162         return ISocket.error(this.conduit);
163     }
164 
165 
166     /**************************************************************************
167 
168         Throws this instance if ok is false.
169 
170         Params:
171             ok   = condition that should not be false
172             msg  = message
173             file = source code file name
174             line = source code line
175 
176         Throws:
177             this instance if ok is false, 0 or null
178 
179      **************************************************************************/
180 
181     void assertExSock ( bool ok, istring msg, istring file = __FILE__,
182                         int line = __LINE__ )
183     {
184         if (!ok) throw this.setSock(msg, file, line);
185     }
186 
187     /**************************************************************************
188 
189         Queries and resets errno and sets the exception parameters.
190 
191         Params:
192             msg  = message
193             file = source code file name
194             line = source code line
195 
196         Returns:
197             this instance
198 
199      **************************************************************************/
200 
201     public typeof (this) setSock ( lazy int errnum, istring msg,
202                                    istring file = __FILE__,
203                                    int line = __LINE__ )
204     {
205         int socket_errnum = this.error_code;
206 
207         this.set(socket_errnum? socket_errnum : errnum, msg, file, line);
208 
209         return this;
210     }
211 
212     /**************************************************************************
213 
214         Queries and resets errno and sets the exception parameters.
215 
216         Params:
217             msg  = message
218             file = source code file name
219             line = source code line
220 
221         Returns:
222             this instance
223 
224      **************************************************************************/
225 
226     public typeof (this) setSock ( istring msg, istring file = __FILE__,
227                                    int line = __LINE__ )
228     {
229         return this.setSock(.errno, msg, file, line);
230     }
231 }