Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DBInfo.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DBInfo.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DBInfo.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DBInfo.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,430 @@
+/*
+ * 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.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+
+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;
+
+/**
+* This class represents the information about the contents of the store
+* itself which must be durable across JVMs.
+* <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
+*/
+// Streamable requires that the class be public. I think!.
+// This class is server-side only, not needed in client.
+public class DBInfo implements Streamable {
+ // There is only ever one instance of DBInfo in a store.
+ //
+ // When a database is first created, we use the initial values here
+ // specified. If the database is being brought up from an existing
+ // backing store, then the read method below will provide the correct
+ // values from the store.
+ //
+ private FOStoreDatabase fodb = null;
+
+ /**
+ * This is the OID of the DBInfo.
+ */
+ // See CLID.java: This relies on the facts that (a) CLID's less than 100
+ // are reserved, and (b) the primitive types are final and cannot be
+ // subclassed.
+ private static final OID dbInfoOID = new OID(0);
+
+ // Next available CLID.
+ private CLID nextCLID = CLID.firstCLID;
+
+ // For the OID of the DBClass corresponding to a given CLID.
+ private static final int DBCLASS_UID = 0;
+
+ // For the OID of the OID's which are of DBClass instances that are
+ // subclasses of an OID's CLID's class. Got that? No? Then see
+ // GetExtentHandler.java.
+ private static final int SUBCLASS_UID = 1;
+
+ // For the OID of the extent of instances of the class indicated by a
+ // CLID.
+ private static final int EXTENT_UID = 2;
+
+ // Reserve the first N UID's in each OID for future use.
+ //
+ // Note to maintainers: Make sure that this is greater than
+ // LAST_RESERVED_UID.
+ private static final int FIRST_CLASS_UID = 10;
+
+ // Indexed by CLID: the value in a given position is the value of the
+ // next available UID for that CLID. That is, when we need a new
+ // datastore OID for a particular CLID, we use that CLID's id value as an
+ // index into this list, and extract the value there. We use that value
+ // as the UID part of the OID being created. And we update the list
+ // element by incrementing the value in the list by 1.
+ private ArrayList nextUIDs = new ArrayList(CLID.firstCLID.getId());
+
+ /** Set of extents that are currently modified and need to be stored when
+ * a transaction commits.
+ */
+ // XXX This relies on the fact that transactions are serialized. Once
+ // that goes away, index a set of dirtyExtents HashSets by some kind of
+ // transaction id.
+ private HashSet dirtyExtents = 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 instance.
+ * Use this constructor when creating an instance for a brand new
+ * database (as opposed to an existing database, in which we use the
+ * Streamable-required default constructor, below).
+ * @param fodb The FOStoreDatabase instance.
+ * @exception FOStoreFatalInternalException Thrown when there is an attempt
+ * to create a second DBInfo within a store.
+ */
+ DBInfo(FOStoreDatabase fodb) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("DBInfo: new for " + fodb); // NOI18N
+ }
+ this.fodb = fodb;
+ // Initialize nextUIDs for the reserved CLIDs.
+ int size = nextCLID.getId();
+ for (int i = 0; i < size; i++) {
+ // FIRST_CLASS_UID number of uid's are reserved per-CLID.
+ nextUIDs.add(i, new Long(FIRST_CLASS_UID));
+ }
+ }
+
+ void store() throws FOStoreDatabaseException {
+ fodb.put(dbInfoOID, this);
+ }
+
+ static DBInfo get(FOStoreDatabase db) throws FOStoreDatabaseException {
+ DBInfo rc = (DBInfo)db.getIfExists(dbInfoOID);
+ if (null == rc) {
+ rc = new DBInfo(db);
+ rc.fodb = db;
+ rc.store();
+ }
+ rc.fodb = db;
+ if (logger.isDebugEnabled()) {
+ logger.debug("DBInfo.get: " + rc); // NOI18N
+ }
+ return rc;
+ }
+
+ //
+ // The intent of the next 2 methods is to provide an OID which can be
+ // used to store information about the class represented by the CLID.
+ // ActivateClassHandler uses newClassOID to create an OID for storing
+ // class metadata, GetClassHandler uses getDBClassOID to get that OID.
+ //
+
+ /**
+ * Provide a new OID to represent a class. Use this when activating a
+ * class.
+ * @return An OID for a class just now known to this store.
+ */
+ OID newClassOID() {
+ // FIRST_CLASS_UID number of uid's are reserved per-CLID.
+ nextUIDs.add(nextCLID.getId(), new Long(FIRST_CLASS_UID));
+
+ OID rc = OID.create(nextCLID, DBCLASS_UID);
+
+ nextCLID = nextCLID.next();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "newClassOID: returning; nextCLID now=" + nextCLID); // NOI18N
+ }
+
+ return rc;
+ }
+
+ /**
+ * Provides the OID which represents the given CLID's class.
+ * @param clid The CLID for which the corresponding OID is needed.
+ * @return The OID of the CLID.
+ */
+ static OID getDBClassOID(CLID clid) {
+ return OID.create(clid, DBCLASS_UID);
+ }
+
+ /**
+ * Provides the OID which at which is stored the ArrayList of the CLIDs of
+ * of subclasses of the class corresponding to the CLID.
+ * @param clid The CLID for which the corresponding OID is needed.
+ * @return The OID of the ArrayList of CLIDs of the given CLID's
+ * subclasses.
+ */
+ static OID getSubclassSetOID(CLID clid) {
+ return OID.create(clid, SUBCLASS_UID);
+ }
+
+ /**
+ * Provides the OID which represents extent of instances of objects all of
+ * which have the given CLID.
+ * @param clid CLID of extent to return.
+ * @return OID of the extent of instances of CLID's class.
+ */
+ static OID getExtentOID(CLID clid) {
+ return OID.create(clid, EXTENT_UID);
+ }
+
+ /**
+ * @return Iterator of DBClass objects
+ */
+ Iterator getDBClasses() {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "DBInfo.getDBClasses: first=" + CLID.firstCLID + // NOI18N
+ ", next=" + nextCLID); // NOI18N
+ }
+ return new DBClassIterator(CLID.firstCLID, nextCLID);
+ }
+
+ class DBClassIterator implements Iterator {
+ private int current;
+ private final int finish;
+
+ DBClassIterator(CLID start, CLID finish) {
+ this.current = start.getId();
+ this.finish = finish.getId();
+ }
+
+ public boolean hasNext() {
+ return current < finish;
+ }
+
+ public Object next() {
+ Object rc = null;
+ try {
+ rc = fodb.get(getDBClassOID(CLID.create(current++, false)));
+ } catch (FOStoreDatabaseException ex) {
+ }
+ return rc;
+ }
+
+ public void remove() { }
+ }
+
+ //
+ // Dirty extent handling
+ //
+
+ /**
+ * Marks the given extent as dirty, so that it can later be stored.
+ */
+ boolean makeExtentDirty(DBExtent e) {
+ return dirtyExtents.add(e);
+ }
+
+ /**
+ * Stores all extents that have been marked dirty since the last time this
+ * method was invoked.
+ */
+ void storeDirtyExtents() throws FOStoreDatabaseException {
+ for (Iterator i = dirtyExtents.iterator(); i.hasNext();) {
+ DBExtent dbExtent = (DBExtent)i.next();
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOSCI.commit:" + dbExtent); // NOI18N
+ }
+ dbExtent.store(fodb);
+ }
+ clearDirtyExtents();
+ }
+
+ /**
+ * Causes this DBInfo to forget about the dirty state of all extents
+ * marked as dirty since the last time storeDirtyExtents was invoked.
+ */
+ void clearDirtyExtents() {
+ dirtyExtents.clear();
+ }
+
+ /**
+ * @return Iterator of DBExtent objects
+ */
+ Iterator getExtents() {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "DBInfo.getExtents: first=" + CLID.firstCLID + // NOI18N
+ ", next=" + nextCLID); // NOI18N
+ }
+ return new ExtentIterator(CLID.firstCLID, nextCLID);
+ }
+
+ class ExtentIterator implements Iterator {
+ private int current;
+ private final int finish;
+
+ ExtentIterator(CLID start, CLID finish) {
+ this.current = start.getId();
+ this.finish = finish.getId();
+ }
+
+ public boolean hasNext() {
+ return current < finish;
+ }
+
+ public Object next() {
+ Object rc = null;
+ try {
+ rc = fodb.get(getExtentOID(CLID.create(current++, false)));
+ } catch (FOStoreDatabaseException ex) {
+ }
+ return rc;
+ }
+
+ public void remove() { }
+ }
+
+ /**
+ * Provide a new OID for the given CLID. Use this when creating an
+ * instance in the store. The OID will have its CLID part as per the
+ * given CLID, and its UID part one greater than the last-created
+ * newInstanceOID.
+ * @param clid CLID for which a new OID is needed.
+ * @return An OID for the CLID.
+ * @exception FOStoreFatalInternalException thrown if the CLID is invalid.
+ */
+ OID newInstanceOID(CLID clid) {
+ OID rc = null;
+ int clidIndex = clid.getId();
+
+ synchronized(nextUIDs) {
+ if (nextUIDs.size() > clidIndex) {
+
+ // Get the next-uid value, increment by one, store the new
+ // next-uid. Make an OID to return.
+ Long UID = (Long)nextUIDs.get(clidIndex);
+ long uid = UID.longValue();
+ if (uid == OID.MAX_UID) {
+ throw new FOStoreFatalInternalException(
+ this.getClass(), "newInstance", // NOI18N
+ msg.msg("ERR_OutOfUIDs", // NOI18N
+ new Long(OID.MAX_UID)));
+ }
+ uid++;
+ UID = new Long(uid);
+ nextUIDs.set(clidIndex, UID);
+
+ rc = OID.create(clid, uid);
+ } else {
+ throw new FOStoreFatalInternalException(
+ this.getClass(), "newInstance", // NOI18N
+ msg.msg("ERR_NoUIDsForCLID", clid)); // NOI18N
+ }
+ }
+ return rc;
+ }
+
+ /** Returns a human-readable description of this DBInfo. If system
+ * property "dbinfo.shortname" is true, then the description includes the
+ * name of the database (e.g. 'foo'), otherwise it includes the complete
+ * pathname of the database (e.g. '/bleem/foo').
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("DBInfo '"); // NOI18N
+ String name = fodb.getName();
+ // Default is to provide full pathname of database; for testing the
+ // short name is more appropriate.
+ if (Boolean.getBoolean("dbinfo.shortname")) { // NOI18N
+ int pos = name.lastIndexOf(File.separatorChar);
+ if (pos > 0) {
+ name = name.substring(pos + 1);
+ }
+ }
+ sb.append(name).append("'\n"); // NOI18N
+
+ sb.append("Next ").append(nextCLID.toString()).append("\n"); // NOI18N
+
+ for (Iterator i = getExtents(); i.hasNext();) {
+ DBExtent e = (DBExtent)i.next();
+ CLID clid = e.getClassCLID();
+ Long uid = (Long)nextUIDs.get(clid.getId());
+
+ sb.append(
+ " class ").append(e.toString()).append(", "); // NOI18N
+ sb.append(
+ "next UID: ").append(uid.toString()).append(".\n"); // NOI18N
+ }
+
+ return sb.toString();
+ }
+
+ //
+ // Implement Streamable
+ //
+
+ public DBInfo() {
+ this(null);
+ }
+
+ public void write(OutputStream os) throws StorageException {
+ DataOutputStream dos = new DataOutputStream(os);
+
+ try {
+ nextCLID.write(dos);
+
+ int size = nextUIDs.size();
+ dos.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ Long clid = (Long)nextUIDs.get(i);
+ dos.writeLong(clid.longValue());
+ }
+ } catch (IOException ex) {
+ throw new StorageIOException(ex);
+ }
+ }
+
+ public void read(InputStream is) throws StorageException {
+ DataInputStream dis = new DataInputStream(is);
+ try {
+ nextCLID = CLID.read(dis);
+
+ int size = dis.readInt();
+ nextUIDs = new ArrayList(size);
+ for (int i = 0; i < size; i++) {
+ nextUIDs.add(i, new Long(dis.readLong()));
+ }
+ } catch (IOException ex) {
+ throw new StorageIOException(ex);
+ }
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteHandler.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,103 @@
+/*
+ * 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.IOException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Processes requests to delete objects from the datastore.
+*
+* @author Dave Bristor
+*/
+class DeleteHandler extends RequestHandler {
+
+ /** I18N Support */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ private DeleteHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ super(reply, length, con);
+ }
+
+ public static HandlerFactory factory =
+ new HandlerFactory() {
+ public RequestHandler getHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ return new DeleteHandler(reply, length, con);
+ }};
+
+
+ RequestFinisher handleRequest()
+ throws IOException, FOStoreDatabaseException {
+
+ if (logger.isDebugEnabled()) logger.debug("DeleteHandler.hR"); //NOI18N
+
+ DataInput in = con.getInputFromClient();
+ OID oid = OID.read(in);
+ boolean optimistic = in.readBoolean();
+
+ FOStoreDatabase fodb = con.getDatabase();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("DeleteHandler.hR: deleting " + oid + // NOI18N
+ ", optimistic=" + optimistic); // NOI18N
+ }
+
+ if (logger.isTraceEnabled()) {
+ Block block = (Block)fodb.get(oid);
+ block.dump();
+ }
+
+ // Remove instance from database and from its Extent
+ boolean found = fodb.remove(oid);
+
+ if (found) {
+ DBInfo dbInfo = fodb.getDBInfo();
+ OID extentOID = dbInfo.getExtentOID(oid.getCLID());
+ DBExtent dbExtent = (DBExtent)fodb.get(extentOID);
+ dbExtent.remove(oid);
+ con.addExtent(dbExtent);
+ reply.setStatus(Status.OK);
+ } else {
+ // Instance to be deleted not in database. If Tx is optimistic,
+ // it's a consistency failure; if datastore it's a bug.
+ if (optimistic) {
+ // XXX when delete verify is added, write the oid there also
+ oid.write(reply);
+ reply.setStatus(
+ Status.OPTIMISTIC,
+ msg.msg("EXC_DeleteVerifyFailed", oid)); // NOI18N
+ } else {
+
+ // Should not happen: datastore tx and instance not in store
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "DeleteHandler.hR: " + oid + " not in db"); // NOI18N
+ }
+ reply.setStatus(
+ Status.FATAL,
+ msg.msg("ERR_DatastoreFailed", oid)); // NOI18N
+ }
+ }
+
+ return null;
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DeleteRequest.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,87 @@
+/*
+ * 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.IOException;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Transaction;
+import javax.jdo.JDOHelper;
+
+import org.apache.jdo.state.StateManagerInternal;
+
+
+/**
+ * Represents a requests to remove a persistent object in the store.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code. It does not need to live in the server.
+//
+class DeleteRequest extends AbstractRequest {
+ /** OID of the instance being deleted. */
+ private final OID oid;
+
+ /** Optimistic/datastore state of current transaction. */
+ private final boolean optimistic;
+
+ DeleteRequest(StateManagerInternal sm, Message m, FOStorePMF pmf) {
+ super(sm, m, pmf);
+ this.oid = (OID)sm.getInternalObjectId();
+ PersistenceManager pm = sm.getPersistenceManager();
+ Transaction tx = pm.currentTransaction();
+ this.optimistic = tx.getOptimistic();
+ }
+
+ protected void doRequestBody() throws IOException {
+ //
+ // The format of this request is (aside from the request header):
+ //
+ // oid: OID
+ // optimistic: boolean
+ // numFields: int
+ // fieldValue: Object...
+ //
+
+ // XXX Need in optimistic Tx, verify w/ dirtyFields? ; see StoreManger#delete
+ if (logger.isDebugEnabled()) {
+ logger.debug("DeleteRequest.dRB: " + oid); // NOI18N
+ }
+ oid.write(out);
+ out.writeBoolean(optimistic);
+ }
+
+ //
+ // Methods from Request
+ //
+
+ /**
+ * @see Request#handleReply
+ */
+ public void handleReply(Status status, DataInput in, int length)
+ throws IOException {
+
+ //
+ // The format of this reply is
+ //
+ // empty, that's right, no data needed.
+ //
+ if (logger.isDebugEnabled()) logger.debug("DeleteRequest.hR"); // NOI18N
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DoubleTranscriber.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,48 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+
+/**
+* Transcribes double values.
+*
+* @author Dave Bristor
+*/
+class DoubleTranscriber extends FOStoreTranscriber {
+ private static DoubleTranscriber instance = new DoubleTranscriber();
+
+ private DoubleTranscriber() {}
+
+ static DoubleTranscriber getInstance() {
+ return instance;
+ }
+
+ void storeDouble(double value, DataOutput out) throws IOException {
+ out.writeDouble(value);
+ }
+
+ double fetchDouble(DataInput in) throws IOException {
+ return in.readDouble();
+ }
+
+ void skip(DataInput in) throws IOException {
+ in.readDouble();
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DummyTranscriber.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,42 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+
+/**
+* This Transcriber is used to skip managed non-persistent fields.
+* Any attempt to use it for fetching or storing a field will
+* result in FOStoreAbstractMethodException.
+*
+* @author Marina Vatkina
+*/
+class DummyTranscriber extends FOStoreTranscriber {
+ private static DummyTranscriber instance = new DummyTranscriber();
+
+ private DummyTranscriber() {}
+
+ static DummyTranscriber getInstance() {
+ return instance;
+ }
+
+ void skip(DataInput in) throws IOException {}
+
+}
+
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpHandler.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpHandler.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpHandler.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,261 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Process dump requests. A dump request provides information about the
+* store. Currently, two options are supported:
+* <ul>
+* <li>dbInfo: Provide information about all classes stored in the store.</li>
+* <li>ClassMetadata: Provide the stored metadata information for the class
+* <code>className</code>.</li>
+* </ul>
+*
+* @see org.apache.jdo.impl.fostore.DumpOption
+* @author Markus Fuchs
+*/
+// This is server-side code. It does not need to live in the client.
+class DumpHandler extends RequestHandler {
+
+ /** Maps <code>DumpOptions</code> to
+ * <code>DumpOptionSubHandlers</code>. The option table must match
+ * the <code>optionTable</code> in <code>Dumper</code>.
+ * <p>
+ * Because the <code>DumpOptionSubHandler</code> are bound to
+ * the state of the enclosing <code>DumpHander</code> instance, the
+ * <code>optionTable</code> has to be non-static. */
+ private static HashMap optionTable = new HashMap();
+
+ /** List of results. A SubRequest might report more than one result. */
+ private final ArrayList results = new ArrayList();
+
+ /** Return status. */
+ private Status status;
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /** Initializes the <code>optionTable</code>.
+ * The option table must match the <code>optionTable</code> in
+ * <code>Dumper</code>.
+ * @see Dumper
+ */
+ // Note that there is no entry for DumpOption.CLASS_INSTANCES: that option
+ // is handled entirely by the Dumper on the client side, with help of
+ // FOStoreStoreManager.getExtent.
+ private void initOptionTable() {
+ optionTable.put(DumpOption.DBINFO,
+ new DBInfoHandler());
+ optionTable.put(DumpOption.CLASS_METADATA,
+ new ClassMetadataHandler());
+ optionTable.put(DumpOption.CLASS_SUBCLASSES,
+ new ClassSubclassesHandler());
+ }
+
+ private DumpHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+
+ super(reply, length, con);
+ initOptionTable();
+ }
+
+ public static final HandlerFactory factory =
+ new HandlerFactory() {
+ public RequestHandler getHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ return new DumpHandler(reply, length, con);
+ }};
+
+ RequestFinisher handleRequest()
+ throws IOException, FOStoreDatabaseException {
+
+ FOStoreInput in = con.getInputFromClient();
+ FOStoreDatabase db = con.getDatabase();
+
+ // read arguments
+ DumpOption option = DumpOption.read(in);
+ String className = in.readUTF();
+
+ DumpOptionSubHandler h =
+ (DumpOptionSubHandler) optionTable.get(option);
+ if (null == h) {
+ reply.setStatus(Status.FATAL,msg.msg("ERR_NoSubHandler", option)); // NOI18N
+ } else {
+ h.run(db, className);
+
+ int size = results.size();
+ reply.writeInt(size);
+ if (size > 0) {
+ for (int i = 0; i < size; i++) {
+ Object o = results.get(i);
+ if (null != o) {
+ reply.writeUTF(o.toString());
+ }
+ }
+ }
+ reply.setStatus(status);
+ }
+
+ return null;
+ }
+
+ /**
+ * Abstract class for dumping database information. The server creates
+ * instances of subclasses and then invoke <code>run</code>. Subclasses
+ * implement <code>run</code> method to do the real work.
+ */
+ abstract class DumpOptionSubHandler {
+
+ /** Must be implemented to dump particular kind of info.
+ */
+ protected abstract void run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException;
+ }
+
+ /**
+ * OptionHandler that dumps DBInfo.
+ */
+ class DBInfoHandler extends DumpOptionSubHandler {
+ protected void run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ results.add(db.getDBInfo());
+ status = Status.OK;
+ }
+ }
+
+ /**
+ * Abstract OptionHandler that assists in dumping information about
+ * classes.
+ */
+ abstract class ClassHandler extends DumpOptionSubHandler {
+ protected void run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ if (null == className) {
+ reply.setStatus(
+ Status.ERROR,
+ msg.msg("MSG_MissingParameter", className)); //NOI18N
+ } else {
+ _run(db, className);
+ }
+ }
+
+ DBClass[] getDBClasses(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ DBClass rc[] = null;
+
+ // look for class info in store
+ DBInfo dbInfo = db.getDBInfo();
+ ArrayList found = new ArrayList();
+ for (Iterator i = dbInfo.getDBClasses(); i.hasNext();) {
+ DBClass dbClass = (DBClass)i.next();
+ if (className.equals(dbClass.getName())) {
+ found.add(dbClass);
+ }
+ }
+ int size = found.size();
+ if (size > 0) {
+ rc = new DBClass[size];
+ for (int i = 0; i < size; i++) {
+ rc[i] = (DBClass)found.get(i);
+ }
+ }
+ return rc;
+ }
+
+ /** Subclasses must implement, to dump their particular kind of info.
+ */
+ abstract void _run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException;
+ }
+
+
+ /**
+ * OptionHandler that dumps metadata about a class.
+ */
+ class ClassMetadataHandler extends ClassHandler {
+ protected void _run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ DBClass dbClasses[] = getDBClasses(db, className);
+ for (int i = 0; i < dbClasses.length; i++) {
+ results.add(dbClasses[i]);
+ }
+ status = Status.OK;
+ }
+ }
+
+ /**
+ * OptionHandler that dumps information about the subclasses of a class.
+ */
+ class ClassSubclassesHandler extends ClassHandler {
+ protected void _run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ // Sort results in String order.
+ TreeSet sorted = new TreeSet();
+
+ DBClass dbClasses[] = getDBClasses(db, className);
+ if (null == dbClasses || 0 == dbClasses.length){
+ results.add(
+ msg.msg("MSG_DbClassNotFound", className)); // NOI18N
+ } else {
+ // For each DBClass known by className, get all of its
+ // subclasses.
+ for (int i = 0; i < dbClasses.length; i++) {
+ String result = null;
+ CLID clid = dbClasses[i].getCLID();
+ OID ssOID = DBInfo.getSubclassSetOID(clid);
+ SubclassSet sl = (SubclassSet)db.getIfExists(ssOID);
+ if (null == sl) {
+ result = msg.msg("MSG_NoSubclasses", className); // NOI18N
+ } else {
+ result = msg.msg("MSG_Subclasses", className); // NOI18N
+ // Get results into the TreeSet
+ for (Iterator j = sl.iterator(); j.hasNext();) {
+ CLID subCLID = (CLID)j.next();
+ OID subDBClassOID = DBInfo.getDBClassOID(subCLID);
+ DBClass subDBClass =
+ (DBClass)db.get(subDBClassOID);
+ sorted.add("\n\t" + subDBClass.getName()); // NOI18N
+ }
+
+ // Put sorted subclasses from TreeSet to string
+ for (Iterator k = sorted.iterator(); k.hasNext();) {
+ result += (String)k.next();
+ }
+ }
+ results.add(result);
+ }
+ }
+ status = Status.OK;
+ }
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpOption.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpOption.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpOption.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpOption.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,134 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.jdo.JDOUserException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/** Diagnostic code to identify a dump request to the store. Currently,
+* there are the following options supported:
+* <ul>
+* <li>DBINFO: Provide information about all classes in the store.</li>
+* <li>CLASS_METADATA: Provide metadata information about a special class.</li>
+* <li>CLASS_INSTANCES: List all instances of a special class.</li>
+* </ul>
+*
+* @author Markus Fuchs
+*/
+class DumpOption {
+ /** Value of this DumpOption. */
+ private final int value;
+
+ /** String name of this option. */
+ private final String name;
+
+ /** Map from name to DumpOption. */
+ private static final HashMap options = new HashMap();
+
+ /** Provide information about all classes in the store. */
+ static final DumpOption DBINFO =
+ new DumpOption(1, "dbInfo"); // NOI18N
+
+ /** Provide metadata information about a particular class.*/
+ static final DumpOption CLASS_METADATA =
+ new DumpOption(2, "classMetadata"); // NOI18N
+
+ /** List all instances of a particular class. */
+ static final DumpOption CLASS_INSTANCES =
+ new DumpOption(3, "classInstances"); // NOI18N
+
+ /** List all subclasses of a particular class. */
+ static final DumpOption CLASS_SUBCLASSES =
+ new DumpOption(4, "classSubclasses"); // NOI18N
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /**
+ * Create a DumpOption with the given value and name.
+ */
+ private DumpOption(int value, String name) {
+ this.value = value;
+ this.name = name;
+ options.put(name, this);
+ }
+
+ /** Provide a DumpOption given a name. */
+ static DumpOption forName(String name) {
+ DumpOption rc = (DumpOption)options.get(name);
+ if (null == rc) {
+ throw new JDOUserException(
+ msg.msg("EXC_BadValue", name)); // NOI18N
+ }
+ return rc;
+ }
+
+ //
+ // I/O support
+ //
+
+ /**
+ * Write this DumpOption's value.
+ */
+ void write(DataOutput out) throws IOException {
+ out.writeUTF(name);
+ }
+
+ /**
+ * Return the instance of a DumpOption that corresponds to the value read
+ * from the DataInput.
+ * @throws IOException if there is an IOException reading the value.
+ * <em>or</em> if the value read does not correspond to a DumpOption.
+ */
+ static DumpOption read(DataInput in) throws IOException {
+ String optionName = in.readUTF();
+ DumpOption rc = forName(optionName);
+ if (null == rc) {
+ throw new IOException(
+ msg.msg("EXC_BadValue", optionName)); // NOI18N
+ }
+ return rc;
+ }
+
+ //
+ // Override java.lang.Object methods
+ //
+
+ public String toString() {
+ return name;
+ }
+
+ public boolean equals(Object o) {
+ boolean rc = false;
+ if ((null != o) && (o instanceof DumpOption)) {
+ rc = (value == ((DumpOption)o).value);
+ }
+ return rc;
+ }
+
+ public int hashCode() {
+ // Same as for java.lang.Integer
+ return value;
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpRequest.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpRequest.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/DumpRequest.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,109 @@
+/*
+ * 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.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOHelper;
+import javax.jdo.JDOUserException;
+import javax.jdo.PersistenceManager;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+
+
+/**
+ * Represents a request to dump information from the store.
+ *
+ * @author Markus Fuchs
+ */
+//
+// This is client-side code. It does not need to live in the server.
+//
+class DumpRequest extends AbstractRequest {
+ /** The DumpOption.
+ */
+ private final DumpOption option;
+
+ /** The name of the class queried by this request.
+ */
+ private final String className;
+
+ /** Returned dump information.
+ */
+ private String dump;
+
+ DumpRequest(DumpOption option, String className, Message m,
+ FOStorePMF pmf) {
+
+ super(m, pmf);
+ this.option = option;
+ this.className = className;
+ }
+
+ protected void doRequestBody() throws IOException {
+ //
+ // The format of this request is:
+ //
+ // int: option code
+ // String: className
+ //
+
+ option.write(out);
+ out.writeUTF((null != className) ? className : ""); // NOI18N
+ if (logger.isDebugEnabled()) {
+ logger.debug("DR.dRB: " + option // NOI18N
+ + " class=" + className); // NOI18N
+ }
+ }
+
+ public void handleReply(Status status, DataInput in, int length) throws IOException {
+ //
+ // The format of the reply is:
+ // int: number of objects (<= one)
+ // String: information dump
+ //
+ // The status might be Status.WARN, in which case either
+ // * The class to be queried wasn't found.
+ // * The className parameter was null.
+
+ int count = in.readInt();
+ if (logger.isDebugEnabled()) {
+ logger.debug("DR.hR/0: count=" + count); // NOI18N
+ }
+
+ StringBuffer results = new StringBuffer();
+ for (int i = 0; i < count; i++) {
+ results.append(in.readUTF());
+ }
+ dump = results.toString();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("DR.hR/1: dump=" + dump); // NOI18N
+ }
+ }
+
+ String getDump() {
+ return dump;
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/Dumper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/Dumper.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/Dumper.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/Dumper.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,280 @@
+/*
+ * 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.File;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOUserException;
+import javax.jdo.PersistenceManager;
+
+import org.apache.jdo.impl.pm.PersistenceManagerWrapper;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Provides information such as metadata, extents, objects about the store.
+* <pre>
+* FOStore dumper program usage:
+* -DdumpOption=OPTION -DclassNames=CLASSNAMES
+* OPTION parameter can be one of the following:
+* dbInfo: prints general information about the store.
+* classMetadata: prints the metadata for the classes CLASSNAMES.
+* classInstances: prints all instances of the classes CLASSNAMES.
+* classSubclasses: prints all information about the subclasses
+* of the classes CLASSNAMES.
+* </pre>
+* This class is <code>public</code> because it has a <code>main</code> entry
+* point for running as a standalone program.
+*
+* @author Markus Fuchs
+* @author Dave Bristor
+*/
+public class Dumper {
+
+ /** Maps <code>DumpOptions</code> to
+ * <code>DumpOptionSubRequests</code>. The option table must match
+ * the <code>optionTable</code> in <code>DumpHandler</code>.
+ * <p>
+ * Because there is no non-static state to be shared between
+ * <code>Dumper</code> and the <code>DumpOptionSubRequest</code>s,
+ * the <code>optionTable</code> can be initilialzed only once.
+ * @see org.apache.jdo.impl.fostore.DumpOption
+ */
+ private static final HashMap optionTable = new HashMap();
+
+ private static FOStorePMF pmf;
+
+ /** Class names to dump informations about. */
+ private static String classNames;
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /**
+ * Initializes the <code>optionTable</code>.
+ * The option table must match the <code>optionTable</code> in
+ * <code>DumpHandler</code>.
+ * @see org.apache.jdo.impl.fostore.DumpHandler
+ */
+ static {
+ optionTable.put(DumpOption.DBINFO,
+ new DBInfoRequest());
+ optionTable.put(DumpOption.CLASS_METADATA,
+ new ClassMetadataRequest());
+ optionTable.put(DumpOption.CLASS_INSTANCES,
+ new ClassInstancesRequest());
+ optionTable.put(DumpOption.CLASS_SUBCLASSES,
+ new ClassSubclassesRequest());
+ }
+
+ /**
+ * Given a command line argument that specifies what information
+ * to dump, gets that information from the database and prints it
+ * on standard output.
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+
+ String optionName = System.getProperty("dumpOption"); // NOI18N
+ if (null == optionName) {
+ exit(msg.msg("MSG_MissingDumpOption")); // NOI18N
+ }
+ classNames = System.getProperty("classNames"); // NOI18N
+
+ try {
+ DumpOption option = DumpOption.forName(optionName);
+
+ DumpOptionSubRequest r =
+ (DumpOptionSubRequest)optionTable.get(option);
+ r.run();
+ } catch (Exception ex) {
+ exit(msg.msg("MSG_DumperException", ex)); // NOI18N
+ }
+ }
+
+ /**
+ * Abstract class for dumping database information. Clients create
+ * instances of subclasses and then invoke <code>run</code>. Subclasses
+ * implement <code>dump</code> method to do the real work.
+ */
+ static abstract class DumpOptionSubRequest {
+ protected PersistenceManager pm;
+ protected FOStoreStoreManager srm;
+ protected StringTokenizer st;
+
+ /** Called by clients to cause information to be dumped.
+ */
+ void run() {
+ try {
+ setupPMF();
+ pm = pmf.getPersistenceManager();
+ srm = (FOStoreStoreManager)pmf.getStoreManager(pm);
+ dump();
+ } catch (Exception ex) {
+ exit(msg.msg("MSG_DumperException", ex)); // NOI18N
+ }
+ }
+
+ /** Subclasses must implement, to dump their particular kind of info.
+ */
+ protected abstract void dump();
+ }
+
+ /**
+ * DumpRequest that can dump DBInfo.
+ */
+ static class DBInfoRequest extends DumpOptionSubRequest {
+ protected void dump() {
+ println(srm.dump(DumpOption.DBINFO, "")); // NOI18N
+ }
+ }
+
+ /**
+ * Abstract DumpRequest that assists in dumping
+ * information about classes.
+ */
+ static abstract class ClassRequest extends DumpOptionSubRequest {
+ protected void dump() {
+ StringTokenizer st =
+ new StringTokenizer(classNames, ","); // NOI18N
+ while (st.hasMoreElements()) {
+ subDump((String)st.nextElement());
+ }
+ }
+
+ /** Subclasses must implement, to dump their particular kind
+ * of info.
+ */
+ protected abstract void subDump(String className);
+ }
+
+ /**
+ * DumpRequest that dumps metadata about a class.
+ */
+ static class ClassMetadataRequest extends ClassRequest {
+ protected void subDump(String className) {
+ println(srm.dump(DumpOption.CLASS_METADATA, className));
+ }
+ }
+
+ /**
+ * DumpRequest that dumps information about the instances
+ * of a class.
+ */
+ static class ClassInstancesRequest extends ClassRequest {
+ protected void subDump(String className) {
+ int objCount = 0;
+ Class cls = null;
+ try {
+ cls = Class.forName(className);
+ } catch (ClassNotFoundException ex) {
+ throw new JDOUserException(
+ msg.msg("EXC_InstantiateClass", className)); // NOI18N
+ }
+
+ println("\n" + msg.msg("MSG_ExtentName", className)); // NOI18N
+ Extent e = pm.getExtent(cls, false);
+ for (Iterator i = e.iterator(); i.hasNext();) {
+ Object pc = i.next();
+ println("" + pc); // NOI18N
+ objCount++;
+ }
+ println(msg.msg("MSG_ExtentCount", className, // NOI18N
+ new Integer(objCount)));
+ }
+ }
+
+ /**
+ * DumpRequest that dumps information about the subclasses
+ * of a class.
+ */
+ static class ClassSubclassesRequest extends ClassRequest {
+ protected void subDump(String className) {
+ int objCount = 0;
+ Class cls = null;
+ try {
+ cls = Class.forName(className);
+ } catch (ClassNotFoundException ex) {
+ throw new JDOUserException(
+ msg.msg("EXC_InstantiateClass", className)); // NOI18N
+ }
+
+ println(srm.dump(DumpOption.CLASS_SUBCLASSES, className));
+ }
+ }
+
+ /** Print an error message and exit.
+ */
+ private static void exit(String message) {
+ println(message);
+ usage();
+ System.exit(1);
+ }
+
+ /** Print the usage message on standard output.
+ */
+ private static void usage() {
+ println(msg.msg("MSG_Usage")); // NOI18N
+ }
+
+ /**
+ * Configures a PMF with some basic properties, and creates the
+ * corresponding database.
+ */
+ private static void setupPMF() throws Exception {
+ pmf = new FOStorePMF();
+ pmf.setConnectionCreate(false);
+
+ pmf.setConnectionUserName(System.getProperty("user", // NOI18N
+ "fred")); // NOI18N
+ pmf.setConnectionPassword(System.getProperty("password", // NOI18N
+ "wombat")); // NOI18N
+
+ // Create url in string form.
+ String path = ""; // NOI18N
+
+ String dir = System.getProperty("dir"); // NOI18N
+ if (null == dir) {
+ dir = System.getProperty("user.dir"); // NOI18N
+ }
+
+ String name = System.getProperty("name"); // NOI18N
+ if (null == name) {
+ name = "FOStoreTestDB"; // NOI18N
+ }
+
+ path += dir + File.separator;
+ path += name;
+
+ path = "fostore:" + path; // NOI18N
+
+ pmf.setConnectionURL(path);
+ }
+
+ /** Print a message on the standard output.
+ * @param s the message to print.
+ */
+ private static void println(String s) {
+ System.out.println(s);
+ }
+
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,31 @@
+/*
+ * 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 javax.jdo.JDOFatalInternalException;
+
+/**
+ * This exception means that a subclass didn't override a method that it should
+ * have. When thrown, it means there is an implementation bug.
+ *
+ * @author Dave Bristor
+ */
+class FOStoreAbstractMethodException extends JDOFatalInternalException {
+ FOStoreAbstractMethodException(String msg) {
+ super(msg); // NOI18N
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,142 @@
+/*
+ * 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.util.HashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.netbeans.mdr.persistence.MOFID;
+import org.netbeans.mdr.persistence.ObjectResolver;
+import org.netbeans.mdr.persistence.StorageException;
+import org.netbeans.mdr.persistence.btreeimpl.btreestorage.BtreeFactory;
+import org.netbeans.mdr.persistence.btreeimpl.btreestorage.BtreeStorage;
+
+/**
+ * FOStore specific BtreeStorage subclass. This class manages MOFIDs for a
+ * FOStore datastore. A MOFID consists of two parts: a storageId of type
+ * String and a serial number of type long. When storing on disk the
+ * storageId is converted into a number and stored as 16-bit value. Only 48
+ * bits of the serial number get represented on disk. FOStore uses the
+ * serial number to encode the uid part of an OID and the storageId for the
+ * class id of an OID. The btree class MOFIDInfo converts a MOFID into a
+ * byte array of 8 bytes that is stored on disk. The two high order bytes
+ * represent the storageId. Class MOFIDInfo calls method storageIdToNumber
+ * to convert a String storageId into a number. The remaining 6 bytes
+ * represent the serial number.
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class FOStoreBtreeStorage extends BtreeStorage {
+
+ /**
+ * Dummy ObjectResolver instance required by BtreeStorage create and
+ * open methods.
+ */
+ private static final ObjectResolver resolver = new Resolver();
+
+ /** Prefix for the storageId generated from an class id. */
+ private static final String CLID_PREFIX = "FOSTORE_CLID";
+
+ /** Length of class id prefix. */
+ private static final int CLID_PREFIX_LENGTH = 12;
+
+ /** Logger */
+ static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.fostore"); // NOI18N
+
+ /**
+ * Creates a new FOStoreBtreeStorage instance. The constructor creates
+ * or opens a storage based on the specified argument <code>isNew</code>.
+ * @param name the name of the storage.
+ * @param isNew true if the database is being created
+ */
+ public FOStoreBtreeStorage(String name, boolean isNew)
+ throws StorageException {
+ super(name);
+ if (isNew) {
+ create(true, resolver);
+ }
+ else {
+ open(false, resolver);
+ }
+ }
+
+ /**
+ * Returns Creates a MOFID based on the class id and uid taken from a
+ * FOStore OID. The storageId of the returned MOFID represents the
+ * class id and the serial number represents the uid.
+ * @param clid the class id
+ * @param uid the unique id
+ * @return MOFID representing class id and uid taken from FOStore OID.
+ */
+ public MOFID createMOFID(int clid, long uid) {
+ // Add FIRST_EXTERNAL_ID to avoid clashes with
+ // internal btree serial numbers
+ long serialNumber = uid + BtreeFactory.FIRST_EXTERNAL_ID;
+ // The prefix CLID_PREFIX check whether the storageId denotes a
+ // fostore class id. Add FIRST_EXTERNAL_CODE to avoid clashes with
+ // internal btree storageId codes
+ String storageId =
+ CLID_PREFIX + (clid + BtreeFactory.FIRST_EXTERNAL_CODE);
+ return new MOFID(serialNumber, storageId);
+ }
+
+ /**
+ * Converts a storageId to an int. If the specified storageId starts
+ * with CLID_PREFIX, then the storageId represents a class id. In this
+ * case use the class id as the numeric reresentation.
+ * @param storageId the storageId as String
+ * @return the numeric representation of the storageId
+ */
+ public int storageIdToNumber(String storageId) throws StorageException {
+ if (storageId.startsWith(CLID_PREFIX))
+ return Integer.parseInt(storageId.substring(CLID_PREFIX_LENGTH));
+ else
+ return super.storageIdToNumber(storageId);
+ }
+
+ /**
+ * Creates a storage id from an int. It returns the FOStore specific
+ * String representation for a storageId representing a class id.
+ * @param number the numberic representation of the storageId
+ * @return the storageId as String
+ */
+ public String numberToStorageId(int number) throws StorageException {
+ if (number >= BtreeFactory.FIRST_EXTERNAL_CODE)
+ return CLID_PREFIX + number;
+ else
+ return super.numberToStorageId(number);
+ }
+
+ /** Dummy implementation. */
+ static class Resolver implements ObjectResolver {
+
+ /** */
+ public Object resolve(String storageID, Object key) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOStoreBtreeStorage: called Resolver.resolve(" +
+ storageID + ", " + key + ")");
+ }
+ return new Object();
+ }
+ }
+}
+
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,82 @@
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * Represents the connection as seen by the client. This contains two types
+ * of interface: that used by the ConnectionFactory, and that used by the
+ * Message. It provides a means for managing the data sent and received
+ * from the store, as well as for being managed in a pool.
+ *
+ * @author Dave Bristor
+ */
+interface FOStoreClientConnection extends FOStoreConnection {
+
+ /** Connect to the data source.
+ */
+ public void connect() throws IOException;
+
+ /**
+ * Provides DataInput from which the client can read replies from
+ * the server.
+ * @return DataInput from which the client can read replies.
+ */
+ public DataInput getInputFromServer() throws IOException;
+
+ /**
+ * Indicates that the client has finished writing. The data is sent to the
+ * server and processed there.
+ */
+ public void sendToStore(byte[] buffer, int start, int length) throws IOException;
+
+ /**
+ * Put this connection back into the connection pool managed by the
+ * ConnectionFactory.
+ */
+ public void close() throws IOException;
+
+ /** Set the connection id used to create this connection. This is used
+ * to determine which connection pool is used.
+ */
+ public void setConnectionId (FOStoreConnectionId connectionId);
+
+ /** Get the connection id used to create this connection. Connections
+ * are pooled based on this connection id.
+ */
+ public FOStoreConnectionId getConnectionId();
+
+ /** Set the connection id used to create this connection. This is used
+ * to determine which connection pool is used.
+ */
+ public void setConnectionFactory (FOStoreConnectionFactory connectionFactory);
+
+ /** Get the connection Factory used to create this connection. Connections
+ * are pooled based on this connection Factory.
+ */
+ public FOStoreConnectionFactory getConnectionFactory();
+
+ /** Close the database associated with this connection. In the remote case,
+ * close the socket.
+ */
+ public void closeDatabase() throws IOException, FOStoreDatabaseException ;
+
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreClientConnectionImpl.java
+ *
+ * Created on June 7, 2001, 3:17 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.OutputStream;
+
+import java.net.URLConnection;
+import java.net.URL;
+import java.net.Socket;
+
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Implementation of the client side of a FOStore connection.
+ *
+ * @author Craig Russell
+ * @version 1.0
+ */
+abstract class FOStoreClientConnectionImpl extends URLConnection implements FOStoreClientConnection {
+
+ /** Message to handle connection-to-connection messages (login).
+ */
+ Message message = new Message();
+
+ FOStoreConnectionFactory connectionFactory;
+
+ FOStoreConnectionId connectionId;
+
+ /** Flag set while logging in. This flag, when set, causes close() to
+ * retain the connection instead of returning the connection to the pool.
+ */
+ private boolean loggingIn = true;
+
+ /** Logger */
+ static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.fostore"); // NOI18N
+
+ /** Creates new FOStoreClientConnectionImpl */
+ public FOStoreClientConnectionImpl(URL url) {
+ super (url);
+ if (logger.isDebugEnabled()) logger.debug("FOCCI<init>" + // NOI18N
+ " Host: " + url.getHost() + // NOI18N
+ " Port: " + url.getPort() + // NOI18N
+ " Path: " + url.getPath()); // NOI18N
+ }
+
+ /**
+ * Return this connection to the connection pool.
+ */
+ public void close() throws IOException {
+ if (!loggingIn) {
+ if (logger.isDebugEnabled()) {
+ logger.debug ("FOCCI.close: closing"); // NOI18N
+ }
+ connectionFactory.closeConnection(this);
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug ("FOCCI.close: loggingIn; not closing"); // NOI18N
+ }
+ }
+ }
+
+ /** Log in to the datastore. This will be done for both local and
+ * remote connections.
+ */
+ protected void login() throws IOException {
+ String path = localizePath(url.getPath());
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCCI:login " + // NOI18N
+ " Database: " + path + // NOI18N
+ " User: " + connectionId.getUser() + // NOI18N
+ " Password: " + connectionId.getPassword() + // NOI18N
+ " Create: " + connectionId.getCreate()); // NOI18N
+ }
+ LoginRequest logreq =
+ new LoginRequest(
+ message, connectionFactory.getPMF(),
+ path, connectionId.getUser(), connectionId.getPassword(),
+ connectionId.getCreate());
+ logreq.doRequest();
+ // false => NOT ok to close (this) connection
+ message.processInStore(this, false);
+ loggingIn = false;
+ }
+
+ public void setConnectionFactory(FOStoreConnectionFactory cf) {
+ this.connectionFactory = cf;
+ }
+
+ /** Get the connection Factory used to create this connection. Connections
+ * are pooled based on this connection Factory.
+ */
+ public FOStoreConnectionFactory getConnectionFactory() {
+ return connectionFactory;
+ }
+
+ /** Set the connection id used to create this connection. This is used
+ * to determine which connection pool is used.
+ */
+ public void setConnectionId (FOStoreConnectionId id) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCCI.setConnectionId(): " + // NOI18N
+ " URL: " + id.getUrl() + // NOI18N
+ " User: " + id.getUser() + // NOI18N
+ " Password: " + id.getPassword() + // NOI18N
+ " Create: " + id.getCreate()); // NOI18N
+ }
+ this.connectionId = id;
+ }
+
+ /** Get the connection id used to create this connection. The id
+ * encapsulates URL, user, and password. Connections
+ * are pooled based on this connection id.
+ */
+ public FOStoreConnectionId getConnectionId() {
+ return connectionId;
+ }
+
+ /**
+ * @return The path, modified as required for the kind of connection.
+ */
+ abstract protected String localizePath(String path);
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+* Tagging interface at root of all kinds of FOStore connections.
+*
+* @author Dave Bristor
+*/
+interface FOStoreConnection {
+}
|