2 * Firebird ADO.NET Data provider for .NET and Mono
4 * The contents of this file are subject to the Initial
5 * Developer's Public License Version 1.0 (the "License");
6 * you may not use this file except in compliance with the
7 * License. You may obtain a copy of the License at
8 * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10 * Software distributed under the License is distributed on
11 * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
12 * express or implied. See the License for the specific
13 * language governing rights and limitations under the License.
15 * Copyright (c) 2002, 2005 Carlos Guzman Alvarez
16 * All Rights Reserved.
22 using FirebirdSql.Data.Common;
24 namespace FirebirdSql.Data.Gds
26 internal sealed class GdsBlob : BlobBase
30 private GdsDatabase db;
36 public override IDatabase DB
38 get { return this.db; }
45 public GdsBlob(IDatabase db, ITransaction transaction) : this(db, transaction, 0)
49 public GdsBlob(IDatabase db, ITransaction transaction, long blobId) : base(db)
51 if (!(db is GdsDatabase))
53 throw new ArgumentException("Specified argument is not of GdsDatabase type.");
55 if (!(transaction is GdsTransaction))
57 throw new ArgumentException("Specified argument is not of GdsTransaction type.");
60 this.db = (GdsDatabase)db;
61 this.transaction = transaction;
69 #region Protected Methods
71 protected override void Create()
75 this.CreateOrOpen(IscCodes.op_create_blob, null);
76 this.RblAddValue(IscCodes.RBL_create);
84 protected override void Open()
88 this.CreateOrOpen(IscCodes.op_open_blob, null);
96 protected override byte[] GetSegment()
98 int requested = this.SegmentSize;
104 this.db.Send.Write(IscCodes.op_get_segment);
105 this.db.Send.Write(this.blobHandle);
106 this.db.Send.Write((requested + 2 < short.MaxValue) ? requested + 2 : short.MaxValue);
107 this.db.Send.Write((int)0); // Data segment
108 this.db.Send.Flush();
110 GdsResponse r = this.db.ReadGenericResponse();
112 this.RblRemoveValue(IscCodes.RBL_segment);
113 if (r.ObjectHandle == 1)
115 this.RblAddValue(IscCodes.RBL_segment);
117 else if (r.ObjectHandle == 2)
119 this.RblAddValue(IscCodes.RBL_eof_pending);
122 byte[] buffer = r.Data;
124 if (buffer.Length == 0)
126 // previous segment was last, this has no data
133 while (srcpos < buffer.Length)
135 len = IscHelper.VaxInteger(buffer, srcpos, 2);
138 Buffer.BlockCopy(buffer, srcpos, buffer, destpos, len);
143 byte[] result = new byte[destpos];
144 Buffer.BlockCopy(buffer, 0, result, 0, destpos);
150 throw new IscException(IscCodes.isc_net_read_err);
155 protected override void PutSegment(byte[] buffer)
161 this.db.Send.Write(IscCodes.op_batch_segments);
162 this.db.Send.Write(this.blobHandle);
163 this.db.Send.WriteBlobBuffer(buffer);
164 this.db.Send.Flush();
166 this.db.ReadGenericResponse();
170 throw new IscException(IscCodes.isc_net_read_err);
175 protected override void Seek(int position)
181 this.db.Send.Write(IscCodes.op_seek_blob);
182 this.db.Send.Write(this.blobHandle);
183 this.db.Send.Write(0); // Seek mode
184 this.db.Send.Write(position); // Seek offset
185 this.db.Send.Flush();
187 GdsResponse r = db.ReadGenericResponse();
189 this.position = r.ObjectHandle;
193 throw new IscException(IscCodes.isc_network_error);
198 protected override void GetBlobInfo()
200 throw new NotSupportedException();
203 protected override void Close()
205 this.db.ReleaseObject(IscCodes.op_close_blob, this.blobHandle);
208 protected override void Cancel()
210 this.db.ReleaseObject(IscCodes.op_cancel_blob, this.blobHandle);
215 #region Private API Methods
217 private void CreateOrOpen(int op, BlobParameterBuffer bpb)
223 this.db.Send.Write(op);
226 this.db.Send.WriteTyped(IscCodes.isc_bpb_version1, bpb.ToArray());
228 this.db.Send.Write(this.transaction.Handle);
229 this.db.Send.Write(this.blobId);
230 this.db.Send.Flush();
232 GdsResponse r = this.db.ReadGenericResponse();
234 this.blobId = r.BlobId;
235 this.blobHandle = r.ObjectHandle;
239 throw new IscException(IscCodes.isc_net_read_err);