Merge pull request #2832 from razzfazz/handle_eintr
[mono.git] / mcs / class / System.Data.OracleClient / System.Data.OracleClient.Oci / OciHandle.cs
1 // 
2 // OciHandle.cs 
3 //  
4 // Part of managed C#/.NET library System.Data.OracleClient.dll
5 //
6 // Part of the Mono class libraries at
7 // mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci
8 //
9 // Assembly: System.Data.OracleClient.dll
10 // Namespace: System.Data.OracleClient.Oci
11 // 
12 // Author: 
13 //     Tim Coleman <tim@timcoleman.com>
14 //     Daniel Morgan <danielmorgan@verizon.net>
15 //         
16 // Copyright (C) Tim Coleman, 2003
17 // Copyright (C) Daniel Morgan, 2005
18 // 
19
20 using System;
21 using System.Runtime.InteropServices;
22 using System.Text;
23 using System.Security.Cryptography;
24 using System.Globalization;
25
26 namespace System.Data.OracleClient.Oci {
27         internal abstract class OciHandle : IDisposable {
28                 #region Fields
29
30                 bool disposed = false;
31
32                 protected internal IntPtr handle = IntPtr.Zero;
33                 OciHandle parent = null;
34                 OciHandleType type;
35
36                 #endregion // Fields
37
38                 #region Constructors
39
40                 internal OciHandle (OciHandleType type, OciHandle parent, IntPtr newHandle) {
41                         this.type = type;
42                         this.parent = parent;
43                         this.handle = newHandle;
44                 }
45
46                 ~OciHandle () {
47                         Dispose (false);
48                 }
49
50                 #endregion // Constructors
51
52                 #region Properties
53
54                 internal OciHandle Parent {
55                         get { return parent; }
56                 }
57
58                 internal IntPtr Handle { 
59                         get { return handle; }
60                 }
61
62                 internal OciHandleType HandleType { 
63                         get { return type; }
64                 }
65
66                 #endregion // Properties
67
68                 #region Methods
69
70                 internal OciHandle Allocate (OciHandleType type) {
71                         int status = 0;
72                         IntPtr newHandle = IntPtr.Zero;
73
74                         if (type < OciHandleType.LobLocator)
75                                 status = OciCalls.OCIHandleAlloc (this,
76                                         out newHandle,
77                                         type,
78                                         0,
79                                         IntPtr.Zero);
80                         else
81                                 status = OciCalls.OCIDescriptorAlloc (this,
82                                         out newHandle,
83                                         type,
84                                         0,
85                                         IntPtr.Zero);
86                 
87                         if (status != 0 && status != 1)
88                                 throw new Exception (String.Format ("Could not allocate new OCI Handle of type {0}", type));
89
90                         switch (type) {
91                         case OciHandleType.Service:
92                                 return new OciServiceHandle (this, newHandle);
93                         case OciHandleType.Error:
94                                 return new OciErrorHandle (this, newHandle);
95                         case OciHandleType.Server:
96                                 return new OciServerHandle (this, newHandle);
97                         case OciHandleType.Session:
98                                 return new OciSessionHandle (this, newHandle);
99                         case OciHandleType.Statement:
100                                 return new OciStatementHandle (this, newHandle);
101                         case OciHandleType.Transaction:
102                                 return new OciTransactionHandle (this, newHandle);
103                         case OciHandleType.LobLocator:
104                                 return new OciLobLocator (this, newHandle);
105                         case OciHandleType.RowId:
106                                 return new OciRowIdDescriptor (this, newHandle);
107                         case OciHandleType.TimeStamp:
108                                 return new OciDateTimeDescriptor (this, newHandle);
109                         case OciHandleType.IntervalDayToSecond:
110                         case OciHandleType.IntervalYearToMonth:
111                                 return new OciIntervalDescriptor (this, type, newHandle);
112                         }
113                         return null;
114                 }
115
116                 protected virtual void Dispose (bool disposing) {
117                         if (!disposed) {
118                                 FreeHandle ();
119                                 if (disposing) {
120                                         parent = null;
121                                 }
122                                 disposed = true;
123                         }
124                 }
125
126                 public void Dispose () {
127                         Dispose (true);
128                         GC.SuppressFinalize (this);
129                 }
130
131                 protected virtual void FreeHandle () 
132                 {
133                         if (type < OciHandleType.LobLocator) {
134                                 switch (type) {
135                                 case OciHandleType.Bind:
136                                 case OciHandleType.Define:
137                                         // Bind and Define handles are freed when Statement handle is disposed
138                                         break;
139                                 case OciHandleType.Environment:
140                                         if (handle != IntPtr.Zero) {
141                                                 OciCalls.OCIHandleFree (handle, type);
142                                         }
143                                         break;
144                                 default:
145                                         if ( handle != IntPtr.Zero &&
146                                                 parent != null && 
147                                                 parent.Handle != IntPtr.Zero )  {
148
149                                                 OciCalls.OCIHandleFree (handle, type);
150                                         }
151                                         break;
152                                 }
153                                 handle = IntPtr.Zero;
154                         }
155                 }
156
157                 internal bool GetAttributeBool (OciAttributeType attrType, OciErrorHandle errorHandle) {
158                         return (GetAttributeInt32 (attrType, errorHandle) != 0);
159                 }
160
161                 internal sbyte GetAttributeSByte (OciAttributeType attrType, OciErrorHandle errorHandle) {
162                         int status = 0;
163                         sbyte output;
164
165                         status = OciCalls.OCIAttrGetSByte (Handle,
166                                 HandleType,
167                                 out output,
168                                 IntPtr.Zero,
169                                 attrType,
170                                 errorHandle);
171
172                         if (status != 0) {
173                                 OciErrorInfo info = errorHandle.HandleError ();
174                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
175                         }
176
177                         return output;
178                 }
179
180                 internal byte GetAttributeByte (OciAttributeType attrType, OciErrorHandle errorHandle) {
181                         int status = 0;
182                         byte output;
183
184                         status = OciCalls.OCIAttrGetByte (Handle,
185                                 HandleType,
186                                 out output,
187                                 IntPtr.Zero,
188                                 attrType,
189                                 errorHandle);
190
191                         if (status != 0) {
192                                 OciErrorInfo info = errorHandle.HandleError ();
193                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
194                         }
195
196                         return output;
197                 }
198
199                 internal ushort GetAttributeUInt16 (OciAttributeType attrType, OciErrorHandle errorHandle) {
200                         int status = 0;
201                         ushort output;
202
203                         status = OciCalls.OCIAttrGetUInt16 (Handle,
204                                 HandleType,
205                                 out output,
206                                 IntPtr.Zero,
207                                 attrType,
208                                 errorHandle);
209
210                         if (status != 0) {
211                                 OciErrorInfo info = errorHandle.HandleError ();
212                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
213                         }
214
215                         return output;
216                 }
217
218                 internal int GetAttributeInt32 (OciAttributeType attrType, OciErrorHandle errorHandle) {
219                         int status = 0;
220                         int output;
221
222                         status = OciCalls.OCIAttrGetInt32 (Handle,
223                                 HandleType,
224                                 out output,
225                                 IntPtr.Zero,
226                                 attrType,
227                                 errorHandle);
228
229                         if (status != 0) {
230                                 OciErrorInfo info = OciErrorHandle.HandleError (errorHandle, status);
231                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
232                         }
233
234                         return output;
235                 }
236
237                 [DllImport ("oci", EntryPoint = "OCIAttrGet")]
238                 internal static extern int OCIAttrGetRowIdDesc (IntPtr trgthndlp,
239                         [MarshalAs (UnmanagedType.U4)] OciHandleType trghndltyp,
240                         IntPtr attributep,
241                         ref uint sizep,
242                         [MarshalAs (UnmanagedType.U4)] OciAttributeType attrtype,
243                         IntPtr errhp);
244                 internal OciRowIdDescriptor GetAttributeRowIdDescriptor (OciErrorHandle errorHandle, OciHandle env)
245                 {
246                         OciRowIdDescriptor descriptor = null;                           
247                         IntPtr outputPtr = IntPtr.Zero;
248                         int outSize = 16;
249                         int status = 0;
250                         OciAttributeType attrType = OciAttributeType.RowId; 
251
252                         outputPtr = OciCalls.AllocateClear (outSize);
253
254                         uint siz = (uint) outSize;
255                         status = OCIAttrGetRowIdDesc (Handle,
256                                 HandleType,
257                                 outputPtr,
258                                 ref siz,
259                                 attrType,
260                                 errorHandle);
261
262                         if (status != 0) {
263                                 OciErrorInfo info = errorHandle.HandleError ();
264                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
265                         }
266
267                         if (outputPtr != IntPtr.Zero && siz > 0) {
268                                 descriptor = (OciRowIdDescriptor) env.Allocate(OciHandleType.RowId);
269                                 descriptor.SetHandle (outputPtr);
270                         }
271
272                         return descriptor;
273                 }
274
275                 internal IntPtr GetAttributeIntPtr (OciAttributeType attrType, OciErrorHandle errorHandle) {
276                         int status = 0;
277                         IntPtr output = IntPtr.Zero;
278                         status = OciCalls.OCIAttrGetIntPtr (Handle,
279                                 HandleType,
280                                 out output,
281                                 IntPtr.Zero,
282                                 attrType,
283                                 errorHandle);
284
285                         if (status != 0) {
286                                 OciErrorInfo info = errorHandle.HandleError ();
287                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
288                         }
289
290                         return output;
291                 }
292
293                 internal string GetAttributeString (OciAttributeType attrType, OciErrorHandle errorHandle) {
294                         string output = String.Empty;
295                         IntPtr outputPtr = IntPtr.Zero;
296                         int outSize;
297                         int status = 0;
298
299                         status = OciCalls.OCIAttrGet (Handle,
300                                 HandleType,
301                                 out outputPtr,
302                                 out outSize,
303                                 attrType,
304                                 errorHandle);
305
306                         if (status != 0) {
307                                 OciErrorInfo info = errorHandle.HandleError ();
308                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
309                         }
310
311                         if (outputPtr != IntPtr.Zero && outSize > 0) {                          
312                                 object str = Marshal.PtrToStringAnsi (outputPtr, outSize);
313                                 if (str != null) 
314                                         output = String.Copy ((string) str);
315                         }
316
317                         return output;
318                 }
319
320                 internal void SetAttributeString (string attribute, OciAttributeType attrType, OciErrorHandle errorHandle) 
321                 {
322                         int status = 0;
323                         
324                         status = OciCalls.OCIAttrSetString (Handle,
325                                 HandleType,
326                                 attribute,
327                                 (uint) attribute.Length,
328                                 attrType,
329                                 errorHandle);
330
331                         if (status != 0) {
332                                 OciErrorInfo info = errorHandle.HandleError ();
333                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
334                         }
335                 }
336
337                 internal void SetHandle (IntPtr h)
338                 {
339                         handle = h;
340                 }
341
342                 #endregion // Methods
343
344                 #region Operators and Type Conversions
345
346                 public static implicit operator IntPtr (OciHandle h)
347                 {
348                         return h.Handle;
349                 }
350
351                 #endregion // Operators and Type Conversions
352         }
353 }