1 package com.quadcap.sql.types; 2 3 40 41 import java.io.BufferedInputStream ; 42 import java.io.BufferedOutputStream ; 43 import java.io.ByteArrayInputStream ; 44 import java.io.Externalizable ; 45 import java.io.InputStream ; 46 import java.io.IOException ; 47 import java.io.ObjectInput ; 48 import java.io.ObjectOutput ; 49 import java.io.OutputStream ; 50 51 import java.sql.Blob ; 53 import java.sql.SQLException ; 55 56 import com.quadcap.sql.DbException; 57 58 import com.quadcap.sql.file.BlockFile; 59 import com.quadcap.sql.file.Datafile; 60 import com.quadcap.sql.file.RandomAccess; 61 import com.quadcap.sql.file.RandomAccessInputStream; 62 import com.quadcap.sql.file.RandomAccessOutputStream; 63 64 import com.quadcap.util.text.TextMatch; 65 66 import com.quadcap.util.Debug; 67 import com.quadcap.util.Util; 68 69 74 public class ValueBlob extends Value 75 implements Blob , Externalizable 79 { 81 static final boolean trace = false; 83 static int serial = 0; 84 int mySerial = serial++; 85 public String show() { 86 return "ValueBlob[" + mySerial + "] @ " + Util.stackTrace(); 87 } 88 90 Datafile file; 91 long permBlock = -1; 92 long tempBlock = -1; 93 94 RandomAccess ra; 95 96 byte[] bytes; 97 98 public ValueBlob() { 99 if (trace) { 101 Debug.println(show() + "()"); 102 } 103 } 105 106 public ValueBlob(byte[] bytes) { 107 if (trace) { 109 Debug.println(show() + "(" + Util.hexBytes(bytes) + ")"); 110 } 111 this.bytes = bytes; 113 } 114 115 public ValueBlob(Datafile file, long transId, 116 InputStream is, int length) 117 throws IOException 118 { 119 init(file, transId, is, length); 120 } 121 122 public void init(Datafile file, long transId, 123 InputStream is, int length) 124 throws IOException 125 { 126 synchronized (file.getFileLock()) { 127 this.file = file; 128 BlockFile perm = file.getFile(); 129 this.permBlock = perm.newPage(); 130 131 if (trace) { 133 Debug.println(show() + ".init(" + file + ", " + transId + 134 " [" + length + " bytes]) -> " + permBlock); 135 } 136 138 BlockFile temp = file.getTempFile(); 139 this.tempBlock = temp.newPage(); 140 141 RandomAccessOutputStream ps = perm.getOutputStream(permBlock); 142 RandomAccessOutputStream ts = temp.getOutputStream(tempBlock); 143 ps.resize(length); 144 ts.resize(length); 145 byte[] buf = new byte[4096]; 146 int cnt; 147 int toread = Math.min(4096, length); 148 if (length < 0) toread = 4096; 149 while ((cnt = is.read(buf, 0, toread)) > 0) { 150 ps.write(buf, 0, cnt); 151 ts.write(buf, 0, cnt); 152 if (length > 0) { 153 length -= cnt; 154 toread = Math.min(4096, length); 155 } 156 } 157 ps.close(); 158 ts.close(); 159 } 160 } 161 162 163 public byte[] getBytesVal() { 164 return bytes; 165 } 166 167 public void passivate(Datafile file, long transId) 168 throws IOException 169 { 170 synchronized (file.getFileLock()) { 171 this.file = file; 172 BlockFile perm = file.getFile(); 173 this.permBlock = perm.newPage(); 174 175 if (trace) { 177 Debug.println(show() + ".passivate(" + file + ", " + 178 transId + ")"); 179 } 180 182 BlockFile temp = file.getTempFile(); 183 this.tempBlock = temp.newPage(); 184 185 RandomAccessOutputStream ps = perm.getOutputStream(permBlock); 186 ps.resize(0); 187 ps.write(bytes); 188 ps.close(); 189 190 RandomAccessOutputStream ts = temp.getOutputStream(tempBlock); 191 ts.resize(0); 192 ts.write(bytes); 193 ts.close(); 194 195 this.bytes = null; 196 } 197 198 } 199 200 public void close() { 201 file = null; 202 } 203 204 public void setDatafile(Datafile file) { 205 this.file = file; 206 } 207 208 public long getPermBlock() { return permBlock; } 209 public long getTempBlock() { return tempBlock; } 210 211 public void setPermBlock(long block) { 212 permBlock = block; 213 } 214 215 public Value unop(int op) throws ValueException { 216 switch (op) { 217 case Op.NULL: return ValueBoolean.falseBoolean; 219 default: 220 throw new ValueException("Unary op: " + Op.toString(op) + 221 " not implemented for this type"); 222 } 223 } 224 225 public Value binop(int op, Value v) throws ValueException { 226 throw badBinop(op, this, v); 227 } 228 229 public Object asJavaObject() { 230 return this; 231 } 232 233 public void fromJavaObject(Object obj) throws ValueException { 234 throw new ValueException("bad type: " + obj); 235 } 236 237 public Type getType() throws SQLException { 238 return new TypeBlob((int)(length() * 8)); 239 } 240 241 public InputStream getBinaryStream() throws SQLException { 242 if (bytes == null) { 243 RandomAccessInputStream is = 244 new RandomAccessInputStream(getRandomAccess()); 245 BufferedInputStream bis = new BufferedInputStream (is); 246 return bis; 247 } else { 248 return new ByteArrayInputStream (bytes); 249 } 250 } 251 252 RandomAccess getRandomAccess() throws SQLException { 253 try { 254 if (ra == null) { 255 if (file != null) { 256 ra = file.getFile().getStream(permBlock); 257 } 258 } 259 return ra; 260 } catch (Exception e2) { 261 throw DbException.wrapThrowable(e2); 262 } 263 } 264 265 284 public byte[] getBytes(long lpos, int length) throws SQLException { 285 int pos = (int)(lpos - 1); 286 try { 287 byte[] buf = new byte[length]; 288 if (bytes == null) { 289 getRandomAccess().read(pos, buf, 0, length); 290 } else { 291 System.arraycopy(bytes, pos, buf, 0, length); 292 } 293 return buf; 294 } catch (IOException e) { 295 throw new SQLException (e.toString(), "Q001G"); 296 } 297 } 298 299 307 public long length() throws SQLException { 308 if (bytes == null) { 309 return getRandomAccess().size(); 310 } else { 311 return bytes.length; 312 } 313 } 314 315 public long position(Blob blob, long start) throws SQLException { 317 byte[] pattern = blob.getBytes(1, (int)blob.length()); 318 return position(pattern, start); 319 } 320 322 325 final InputStream getPositionedStream(int pos) throws SQLException { 326 InputStream is; 327 if (bytes == null) { 328 RandomAccessInputStream ris = 329 new RandomAccessInputStream(getRandomAccess()); 330 ris.setPosition(pos); 331 is = new BufferedInputStream (ris); 332 } else { 333 is = new ByteArrayInputStream (bytes, pos, bytes.length - pos); 334 } 335 return is; 336 } 337 338 public long position(byte[] pattern, long start) throws SQLException { 339 try { 340 int pos = (int)(start - 1); 341 InputStream is = getPositionedStream(pos); 342 long ret = TextMatch.match(is, pattern); 343 if (ret < 0) return -1; 344 return ret + start; 345 } catch (IOException e) { 346 throw new SQLException (e.toString(), "Q001E"); 347 } 348 } 349 350 public void readExternal(ObjectInput in) 351 throws IOException , ClassNotFoundException 352 { 353 permBlock = in.readLong(); 354 } 355 356 public void writeExternal(ObjectOutput out) throws IOException { 357 out.writeLong(permBlock); 358 } 359 360 public Value convert(TypeBlob type) throws ValueException { 361 return this; 362 } 363 364 public Value convert(TypeVarBinary type) throws ValueException { 365 try { 366 byte[] b = getBytes(1L, (int)length()); 367 return new ValueOctets(b, (int)(length() * 8)); 368 } catch (SQLException e) { 369 throw new ValueException(e.toString()); 370 } 371 } 372 373 public void serializeKey(KeyStream out) throws IOException { 374 throw new IOException ("Can't use BLOB as key"); 375 } 376 377 public String toString() { 378 try { 379 if (length() < 4 * 1024L) { 380 byte[] b = getBytes(1L, (int)length()); 381 return Util.hexBytes(b); 382 } else { 383 return "Too long (" + length() + ") bytes"; 384 } 385 } catch (SQLException e) { 386 return "ValueBlob.toString() error: " + e.toString(); 387 } 388 } 389 390 391 393 408 public int setBytes(long lpos, byte[] bytes) 409 throws SQLException 410 { 411 int pos = (int)(lpos - 1); 412 try { 413 getRandomAccess().write(pos, bytes, 0, bytes.length); 414 return bytes.length; 415 } catch (IOException e) { 416 throw new SQLException (e.toString(), "Q001G"); 417 } 418 } 419 420 441 public int setBytes(long lpos, byte[] bytes, int offset, int len) 442 throws SQLException 443 { 444 int pos = (int)(lpos - 1); 445 try { 446 getRandomAccess().write(pos, bytes, offset, len); 447 return len; 448 } catch (IOException e) { 449 throw new SQLException (e.toString(), "Q001G"); 450 } 451 } 452 453 467 public java.io.OutputStream setBinaryStream(long lpos) 468 throws SQLException 469 { 470 int pos = (int)(lpos - 1); 471 RandomAccessOutputStream rao = 472 new RandomAccessOutputStream(getRandomAccess()); 473 rao.setPosition(pos); 474 return rao; 475 } 476 477 487 public void truncate(long len) 488 throws SQLException 489 { 490 try { 491 getRandomAccess().resize(len); 492 } catch (IOException e) { 493 throw new SQLException (e.toString(), "Q001G"); 494 } 495 } 496 } 497 | Popular Tags |