001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.db.store;
031:
032: import com.caucho.vfs.TempBuffer;
033:
034: import java.io.IOException;
035: import java.io.OutputStream;
036: import java.util.logging.Logger;
037:
038: public class BlobOutputStream extends OutputStream {
039: private static final Logger log = Logger
040: .getLogger(BlobOutputStream.class.getName());
041:
042: private StoreTransaction _xa;
043: private Store _store;
044:
045: private TempBuffer _tempBuffer;
046: private byte[] _buffer;
047: private int _offset;
048: private int _bufferEnd;
049:
050: private Inode _inode;
051:
052: private byte[] _inodeBuffer;
053: private int _inodeOffset;
054:
055: /**
056: * Creates a blob output stream.
057: *
058: * @param store the output store
059: */
060: public BlobOutputStream(Transaction xa, Store store, byte[] inode,
061: int inodeOffset) {
062: init(store, inode, inodeOffset);
063:
064: _xa = xa;
065: }
066:
067: /**
068: * Creates a blob output stream.
069: *
070: * @param store the output store
071: */
072: public BlobOutputStream(Store store, byte[] inode, int inodeOffset) {
073: init(store, inode, inodeOffset);
074: }
075:
076: /**
077: * Creates a blob output stream.
078: *
079: * @param store the output store
080: */
081: BlobOutputStream(Inode inode) {
082: init(inode.getStore(), inode.getBuffer(), 0);
083:
084: _inode = inode;
085: }
086:
087: /**
088: * Initialize the output stream.
089: */
090: public void init(Store store, byte[] inode, int inodeOffset) {
091: _store = store;
092: _xa = RawTransaction.create();
093:
094: _inodeBuffer = inode;
095: _inodeOffset = inodeOffset;
096:
097: Inode.clear(_inodeBuffer, _inodeOffset);
098:
099: _offset = 0;
100:
101: _tempBuffer = TempBuffer.allocate();
102: _buffer = _tempBuffer.getBuffer();
103: _bufferEnd = _buffer.length;
104: }
105:
106: /**
107: * Writes a byte.
108: */
109: public void write(int v) throws IOException {
110: if (_bufferEnd <= _offset) {
111: flushBlock();
112: }
113:
114: _buffer[_offset++] = (byte) v;
115: }
116:
117: /**
118: * Writes a buffer.
119: */
120: @Override
121: public void write(byte[] buffer, int offset, int length)
122: throws IOException {
123: while (length > 0) {
124: if (_bufferEnd <= _offset) {
125: flushBlock();
126: }
127:
128: int sublen = _bufferEnd - _offset;
129: if (length < sublen)
130: sublen = length;
131:
132: System.arraycopy(buffer, offset, _buffer, _offset, sublen);
133:
134: offset += sublen;
135: _offset += sublen;
136:
137: length -= sublen;
138: }
139: }
140:
141: /**
142: * Completes the stream.
143: */
144: @Override
145: public void close() throws IOException {
146: try {
147: if (_tempBuffer == null)
148: return;
149:
150: flushBlock();
151: } finally {
152: Inode inode = _inode;
153: _inode = null;
154:
155: if (inode != null)
156: inode.closeOutputStream();
157:
158: _inodeBuffer = null;
159:
160: TempBuffer tempBuffer = _tempBuffer;
161: _tempBuffer = null;
162:
163: if (tempBuffer != null) {
164: TempBuffer.free(tempBuffer);
165: tempBuffer = null;
166: }
167: }
168: }
169:
170: /**
171: * Updates the buffer.
172: */
173: private void flushBlock() throws IOException {
174: int length = _offset;
175: _offset = 0;
176:
177: Inode.append(_inodeBuffer, _inodeOffset, _store, _xa, _buffer,
178: 0, length);
179: }
180: }
|