blob: 10b247b60bacf4ae8362787407d4d80366872f4d [file] [log] [blame]
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jdo.impl.fostore;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Iterator;
import javax.jdo.JDOFatalInternalException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jdo.util.I18NHelper;
import org.netbeans.mdr.persistence.Streamable;
import org.netbeans.mdr.persistence.StorageException;
import org.netbeans.mdr.persistence.StorageIOException;
/**
* Represents a set of instances of a given class stored in the database.
* <p>
* This class is <code>public</code> so that it can be used as a
* <code>Streamable</code> and stored in the database.
*
* @author Dave Bristor
*/
public class DBExtent implements Streamable {
/** This DBExtent lives in a database.
*/
private FOStoreDatabase fodb;
/** Name of the class of instances in this extent.
*/
private String name;
/* Along with name, determines equality of extent instances.
*/
private FOStoreSchemaUID fsuid;
/** CLID of the class of the instances of this extent.
*/
private CLID classCLID;
/** OID of this extent. Cached so that we don't have to calculate each
* time we store the extent
*/
private OID extentOID;
/** OIDs of instances of this extent.
*/
private HashSet instances = new HashSet();
/** I18N support. */
private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
/** Logger */
static final Log logger = LogFactory.getFactory().getInstance(
"org.apache.jdo.impl.fostore"); // NOI18N
/**
* Create a new DBExtent
*/
private DBExtent(FOStoreDatabase fodb, String name,
FOStoreSchemaUID fsuid, CLID classCLID) {
this.fodb = fodb;
this.name = name;
this.fsuid = fsuid;
this.classCLID = classCLID;
this.extentOID = DBInfo.getExtentOID(classCLID);
if (logger.isDebugEnabled()) { dump("()"); } // NOI18N
}
/**
* Return a new DBExtent to the caller.
*/
static DBExtent create(FOStoreDatabase fodb, String name,
FOStoreSchemaUID fsuid, CLID classCLID) {
return new DBExtent(fodb, name, fsuid, classCLID);
}
/** @return true if the given name and FOStoreSchemaUID are equal to those
* in this DBExtent.
*/
boolean isExtentFor(String n, FOStoreSchemaUID f) {
boolean rc = false;
if (null != n && null != f) {
rc = name.equals(n) && fsuid.equals(f);
}
return rc;
}
String getName() {
return name;
}
OID getExtentOID() {
return extentOID;
}
CLID getExtentCLID() {
return extentOID.getCLID();
}
OID getDBClassOID() {
return DBInfo.getDBClassOID(classCLID);
}
CLID getClassCLID() {
return classCLID;
}
synchronized void add(OID oid) {
if (instances.contains(oid)) {
throw new JDOFatalInternalException(
msg.msg("ERR_SecondInstance", oid, name)); // NOI18N
}
instances.add(oid);
if (logger.isDebugEnabled()) {
logger.debug(
"DBExtent: added " + oid + ", size=" + size()); // NOI18N
}
}
synchronized void remove(OID oid) {
instances.remove(oid);
}
synchronized int size() {
return instances.size();
}
Iterator iterator() {
return instances.iterator();
}
synchronized void store(FOStoreDatabase db)
throws FOStoreDatabaseException {
db.put(extentOID, this);
if (logger.isDebugEnabled()) { dump(" store"); } // NOI18N
}
//
// Implement Streamable
//
public DBExtent() { }
public void write(OutputStream os) throws StorageException {
DataOutputStream dos = new DataOutputStream(os);
try {
if (logger.isDebugEnabled()) { dump(" write"); } // NOI18N
dos.writeUTF(name);
classCLID.write(dos);
fsuid.write(dos);
int numInstances = instances.size();
dos.writeInt(numInstances);
for (Iterator i = instances.iterator(); i.hasNext();) {
OID oid = (OID)i.next();
oid.write(dos);
if (logger.isDebugEnabled()) {
logger.debug("DBExtent.write: wrote " + oid); // NOI18N
}
}
} catch (IOException ex) {
throw new StorageIOException(ex);
}
}
public void read(InputStream is) throws StorageException {
DataInputStream dis = new DataInputStream(is);
try {
name = dis.readUTF();
classCLID = CLID.read(dis);
fsuid = FOStoreSchemaUID.read(dis);
extentOID = DBInfo.getExtentOID(classCLID);
int numInstances = dis.readInt();
if (logger.isDebugEnabled()) {
logger.debug(
"DBExtent.read: numInstances=" + numInstances); // NOI18N
}
instances = new HashSet(numInstances);
for (int i = 0; i < numInstances; i++) {
instances.add(OID.read(dis));
}
if (logger.isDebugEnabled()) { dump(".read"); } // NOI18N
} catch (IOException ex) {
throw new StorageIOException(ex);
}
}
private void dump(String where) {
logger.debug("DBExtent" + where + ": " + toString()); // NOI18N
}
public String toString() {
return name + " " + extentOID + " " + // NOI18N
Tester.toHex(extentOID.oid, 16) +
", numInstances=" + instances.size(); // NOI18N
}
}