001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.foundation.network;
022:
023: import com.db4o.*;
024: import com.db4o.foundation.*;
025:
026: /**
027: * Transport buffer for C/S mode to simulate a
028: * socket connection in memory.
029: */
030: class BlockingByteChannel {
031:
032: private final static int DISCARD_BUFFER_SIZE = 500;
033: protected byte[] i_cache;
034: boolean i_closed = false;
035: protected int i_readOffset;
036: private int i_timeout;
037: protected int i_writeOffset;
038: protected final Lock4 i_lock = new Lock4();
039:
040: public BlockingByteChannel(int timeout) {
041: i_timeout = timeout;
042: }
043:
044: protected int available() {
045: return i_writeOffset - i_readOffset;
046: }
047:
048: protected void checkDiscardCache() {
049: if (i_readOffset == i_writeOffset
050: && i_cache.length > DISCARD_BUFFER_SIZE) {
051: i_cache = null;
052: i_readOffset = 0;
053: i_writeOffset = 0;
054: }
055: }
056:
057: void close() {
058: i_lock.run(new SafeClosure4() {
059: public Object run() {
060: i_closed = true;
061: i_lock.awake();
062: return null;
063: }
064: });
065: }
066:
067: protected void makefit(int length) {
068: if (i_cache == null) {
069: i_cache = new byte[length];
070: } else {
071: // doesn't fit
072: if (i_writeOffset + length > i_cache.length) {
073: // move, if possible
074: if (i_writeOffset + length - i_readOffset <= i_cache.length) {
075: byte[] temp = new byte[i_cache.length];
076: System.arraycopy(i_cache, i_readOffset, temp, 0,
077: i_cache.length - i_readOffset);
078: i_cache = temp;
079: i_writeOffset -= i_readOffset;
080: i_readOffset = 0;
081:
082: // else append
083: } else {
084: byte[] temp = new byte[i_writeOffset + length];
085: System.arraycopy(i_cache, 0, temp, 0,
086: i_cache.length);
087: i_cache = temp;
088: }
089: }
090: }
091: }
092:
093: public int read() throws Db4oIOException {
094: Integer ret = (Integer) i_lock.run(new SafeClosure4() {
095: public Object run() {
096: waitForAvailable();
097: int retVal = i_cache[i_readOffset++];
098: checkDiscardCache();
099: return new Integer(retVal);
100: }
101: });
102: return ret.intValue();
103:
104: }
105:
106: public int read(final byte[] bytes, final int offset,
107: final int length) throws Db4oIOException {
108: Integer ret = (Integer) i_lock.run(new SafeClosure4() {
109: public Object run() {
110: waitForAvailable();
111: int avail = available();
112: int toRead = length;
113: if (avail < length) {
114: toRead = avail;
115: }
116: System.arraycopy(i_cache, i_readOffset, bytes, offset,
117: toRead);
118: i_readOffset += toRead;
119: checkDiscardCache();
120: return new Integer(toRead);
121: }
122: });
123: return ret.intValue();
124: }
125:
126: public void setTimeout(int timeout) {
127: i_timeout = timeout;
128: }
129:
130: protected void waitForAvailable() {
131: long beginTime = System.currentTimeMillis();
132: while (available() == 0) {
133: checkClosed();
134: i_lock.snooze(i_timeout);
135: if (isTimeout(beginTime)) {
136: throw new Db4oIOException();
137: }
138: }
139: }
140:
141: private boolean isTimeout(long start) {
142: return System.currentTimeMillis() - start >= i_timeout;
143: }
144:
145: public void write(byte[] bytes) throws Db4oIOException {
146: write(bytes, 0, bytes.length);
147: }
148:
149: public void write(final byte[] bytes, final int off, final int len)
150: throws Db4oIOException {
151: i_lock.run(new SafeClosure4() {
152: public Object run() {
153: checkClosed();
154: makefit(len);
155: System.arraycopy(bytes, off, i_cache, i_writeOffset,
156: len);
157: i_writeOffset += len;
158: i_lock.awake();
159: return null;
160: }
161: });
162: }
163:
164: public void write(final int i) throws Db4oIOException {
165: i_lock.run(new SafeClosure4() {
166: public Object run() {
167: checkClosed();
168: makefit(1);
169: i_cache[i_writeOffset++] = (byte) i;
170: i_lock.awake();
171: return null;
172: }
173: });
174: }
175:
176: public void checkClosed() {
177: if (i_closed) {
178: throw new Db4oIOException();
179: }
180: }
181: }
|