You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 20:40:21 UTC
svn commit: r171355 [8/31] - in /incubator/jdo/trunk/fostore20: ./ src/
src/conf/ src/java/ src/java/org/ src/java/org/apache/
src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/
src/java/org/apache/jdo/impl/fostore/ test/ test/conf/ test/fsuid2/
test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/
test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/
test/java/org/apache/ test/java/org/apache/jdo/
test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/
test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/
test/java/org/apache/jdo/pc/empdept/
test/java/org/apache/jdo/pc/serializable/
test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/
test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/
test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/
test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/
test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/
test/jdo/org/apache/jdo/pc/xempdept/
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,254 @@
+/*
+ * 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.HashSet;
+import java.util.Iterator;
+
+/**
+* Process GetExtent requests.
+*
+* @author Dave Bristor
+*/
+// This is server-side code. It does not need to live in the client.
+class GetExtentHandler extends RequestHandler {
+
+ private GetExtentHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+
+ super(reply, length, con);
+ }
+
+ public static final HandlerFactory factory =
+ new HandlerFactory() {
+ public RequestHandler getHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ return new GetExtentHandler(reply, length, con);
+ }};
+
+ /**
+ * The desired extent's class can be specified either by CLID (i.e., the
+ * class's CLID was already loaded from store to the client) or classname
+ * and FSUID (in case the CLID wasn't known). In the latter case, look
+ * up the CLID.
+ * <br>
+ * With the CLID, get the set of extents: it will be only one if
+ * subclasses is false, an aribtrary number otherwise.
+ * <br>
+ * Iterate over the extents, writing the items into the reply.
+ * @see RequestHandler#handleRequest
+ * @see GetExtentRequest#doRequestBody
+ */
+ RequestFinisher handleRequest()
+ throws IOException, FOStoreDatabaseException {
+
+ FOStoreInput in = con.getInputFromClient();
+ FOStoreDatabase db = con.getDatabase();
+ HashSet dbExtents = null;
+
+ // true => resulting extent to include subclasses of indicated class.
+ boolean subclasses;
+
+ int maxInstances = in.readInt();
+
+ // By CLID or by classname/fsuid?
+ boolean isCLID = in.readBoolean();
+
+ CLID clid = null;
+ if (isCLID) {
+ clid = CLID.read(in);
+ subclasses = in.readBoolean();
+
+ } else {
+ // Find the clid for the given name/fsuid.
+
+ String name = in.readUTF();
+ FOStoreSchemaUID fsuid = FOStoreSchemaUID.read(in);
+ subclasses = in.readBoolean();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetExtentHandler for name=" + name); // NOI18N
+ }
+
+ for (Iterator i = db.getDBInfo().getDBClasses(); i.hasNext();) {
+ DBClass dbClass = (DBClass)i.next();
+ if (fsuid.equals(dbClass.getFSUID()) &&
+ name.equals(dbClass.getName())) {
+ clid = dbClass.getCLID();
+ // break because there can be only one match.
+ break;
+ }
+ }
+ }
+
+ // Get the set of CLIDs of extents
+ if (null != clid) {
+ dbExtents = getDBExtents(clid, subclasses, db);
+ }
+
+ if (logger.isDebugEnabled()) {
+ if (null == dbExtents) {
+ logger.debug("GetExtentHandler.hr: no extents"); // NOI18N
+ } else {
+ for (Iterator i = dbExtents.iterator(); i.hasNext();) {
+ logger.debug(
+ "GetExtentHandler.hr: extent=" + i.next()); // NOI18N
+ }
+ }
+ }
+
+ Status status = null;
+ int extentSize = 0;
+ int numInstances = 0;
+ int numOIDs = 0;
+
+ // Write instances into the reply
+ if (null == dbExtents) {
+ reply.writeInt(0);
+ reply.writeInt(0);
+ reply.writeInt(0);
+ status = Status.OK;
+
+ } else {
+ // Save space for writing various counts in the reply.
+ int extentSizePos = reply.beginStash();
+ int numInstancesPos = reply.beginStash();
+ int numOIDsPos = reply.beginStash();
+
+ for (Iterator i = dbExtents.iterator(); i.hasNext();) {
+ DBExtent extent = (DBExtent)i.next();
+
+ if (null != extent && extent.size() > 0) {
+
+ // Fetch some of the instances from the store.
+ // If we fail to get an object, continue, but set status
+ // to WARN.
+ for (Iterator j = extent.iterator(); j.hasNext();) {
+ OID oid = (OID)j.next();
+ try {
+ reply.writeOID(oid);
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetExtentHandler.hR/2: " + // NOI18N
+ oid + " " + // NOI18N
+ Tester.toHex(oid.oid, 16));
+ }
+
+ if (numInstances < maxInstances) {
+ Block block = (Block)db.get(oid);
+ if (logger.isTraceEnabled()) {
+ block.dump();
+ }
+
+ byte data[] = block.getData();
+ reply.writeInt(data.length);
+ reply.write(data);
+ numInstances++;
+ } else {
+ numOIDs++;
+ }
+ extentSize++;
+ } catch (FOStoreDatabaseException ex) {
+ status = Status.WARN;
+ }
+ }
+ }
+ }
+
+ // Write counts.
+ reply.endStash(extentSize, extentSizePos);
+ reply.endStash(numInstances, numInstancesPos);
+ reply.endStash(numOIDs, numOIDsPos);
+
+ if (null == status) {
+ status = Status.OK;
+ }
+ }
+ reply.setStatus(status);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetExtentHandler.hR/3: " + // NOI18N
+ "extentSize=" + extentSize + // NOI18N
+ ", numInstances=" + numInstances + // NOI18N
+ ", numOIDs=" + numOIDs + " " + status); // NOI18N
+ }
+ return null;
+ }
+
+ /**
+ * Get a set of CLIDs of extents for the given clid. The set will have at
+ * most one element if subclasses is false, or an arbitrary number
+ * otherwise.
+ * @param clid The CLID of the class whose extent is wanted.
+ * @param subclasses If true, then include extents for all subclasses of
+ * the class corresponding to CLID.
+ * @param db Database in which to find extents.
+ * @return Set of extents of clid (and possibly its subclasses).
+ * @throws FOStoreDatabaseException if a database error occurs.
+ */
+ HashSet getDBExtents(CLID clid, boolean subclasses, FOStoreDatabase db)
+ throws FOStoreDatabaseException {
+
+ HashSet rc = null;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetExtentHandler.getExtents: for " + clid); // NOI18N
+ }
+ OID oid = db.getDBInfo().getExtentOID(clid);
+ DBExtent extent = (DBExtent)db.getIfExists(oid);
+ if (null != extent) {
+ rc = new HashSet();
+ rc.add(extent);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetExtentHandler.getExtents: got " + extent); // NOI18N
+ }
+
+ if (subclasses) {
+ OID ssOID = DBInfo.getSubclassSetOID(clid);
+ SubclassSet ss = (SubclassSet)db.getIfExists(ssOID);
+ if (null != ss) {
+ for (Iterator i = ss.iterator(); i.hasNext();) {
+ CLID subCLID = (CLID)i.next();
+ OID subExtentOID = DBInfo.getExtentOID(subCLID);
+ DBExtent subExtent =
+ (DBExtent)db.getIfExists(subExtentOID);
+ if (null != subExtent) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetExtentHandler.getExtents: "+ // NOI18N
+ "subclass " + subExtent); // NOI18N
+ }
+ if (null == rc) {
+ rc = new HashSet();
+ }
+ rc.add(subExtent);
+ }
+ }
+ }
+ }
+ return rc;
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetExtentRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,263 @@
+/*
+ * 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.security.AccessController;
+import java.security.PrivilegedAction;
+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 get the extent of a class and possibly its
+ * subclasses.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code. It does not need to live in the server.
+//
+class GetExtentRequest extends AbstractRequest {
+ /** The PersistenceManagerInternal that is making this request. */
+ private final PersistenceManagerInternal pm;
+
+ /** The class of the extent sought by this request. */
+ private final Class cls;
+
+ /** If true retrieve instances of cls and its subclasses, otherwise just
+ * of cls. */
+ private final boolean subclasses;
+
+ /** Maximum number of instances that should be returned at a time. */
+ private static final int maxInstances;
+
+ /** Extent returned to user. */
+ private FOStoreExtent extent;
+
+ /** List of returned instances */
+ private ArrayList instances;
+
+ /** List of returned object Ids */
+ private ArrayList oids;
+
+ static {
+ int max = 100;
+ try {
+ String property = (String)AccessController.doPrivileged(
+ new PrivilegedAction () {
+ public Object run () {
+ return System.getProperty("maxInstances"); // NOI18N
+ }
+ }
+ );
+ max = Integer.parseInt(property);
+ } catch (SecurityException ex) {
+ // cannot read maxInstances flag => log warning
+ if (logger.isWarnEnabled())
+ logger.warn(msg.msg("MSG_CannotGetSystemProperty", //NOI18N
+ "maxInstances", ex.toString())); //NOI18N
+ } catch (Exception ex) {
+ // use default
+ }
+ maxInstances = max;
+ }
+
+ GetExtentRequest(FOStoreExtent extent, Class cls, boolean subclasses, Message m,
+ PersistenceManagerInternal pm) {
+
+ super(m, (FOStorePMF)pm.getPersistenceManagerFactory());
+ this.pm = pm;
+ this.cls = cls;
+ this.subclasses = subclasses;
+ this.extent = extent;
+ }
+
+ /**
+ * @see AbstractRequest#doRequestBody
+ * @see InsertRequest#doRequestBody
+ */
+ protected void doRequestBody() throws IOException {
+ //
+ // The format of this request is variable, depending on whether or not
+ // we already have in-client metadata for the given class.
+ //
+ // If we do have in-client metadata for the given class:
+ //
+ // int: maximum number of instances to return
+ // boolean: true
+ // clid of the class
+ // boolean: true if subclasses, false otherwise
+ //
+ // Otherwise:
+ //
+ // int: maximum number of instances to return
+ // boolean: flase
+ // String name of the class
+ // FOStoreSchemaUID of the class.
+ // boolean: true if subclasses, false otherwise
+ //
+
+ FOStoreModel model = pmf.getModel();
+ CLID clid = model.getCLID(cls);
+ out.writeInt(maxInstances);
+ if (null != clid && ! clid.isProvisional()) {
+ out.writeBoolean(true);
+ clid.write(out);
+ if (logger.isDebugEnabled()) {
+ logger.debug("GetExtentRequest.dRB: " + clid // NOI18N
+ + " subclasses=" + subclasses); // NOI18N
+ }
+ } else {
+ out.writeBoolean(false);
+ out.writeUTF(cls.getName());
+ FOStoreSchemaUID fsuid = FOStoreSchemaUID.lookup(cls, model);
+ fsuid.write(out);
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetExtentRequest.dRB: " + cls.getName() // NOI18N
+ + " subclasses=" + subclasses); // NOI18N
+ }
+ }
+ out.writeBoolean(subclasses);
+ }
+
+ /**
+ * Handles replies to GetExtentRequests.
+ * The format of the reply is:
+ * <pre>
+ * int: count of number of instances in the extent
+ * int: count of the number of instances returned
+ * int: count of the number of oids returned
+ * that many instances
+ * </pre>
+ * The number of instances returned + number of oid returned = number
+ * of instances in the extent. This is for performance: we don't
+ * want to return *all* the instances at once: we return some, plus
+ * information so that we can get the rest, if the user requests so.
+ * <p>
+ * The status might be Status.WARN, in which case there were OID's in
+ * the database extent which were unreadable. But the count should
+ * be for the actual number of objects returned.
+ */
+ public void handleReply(Status status, DataInput in, int length)
+ throws IOException {
+
+
+ int extentSize = in.readInt();
+ int numInstances = in.readInt();
+ int numOIDs = in.readInt();
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GER.hR/1: extentSize=" + extentSize + // NOI18N
+ ", numInstances=" + numInstances + // NOI18N
+ ", numOIDs=" + numOIDs); // NOI18N
+ }
+
+ // Get instances for the extent
+ instances =
+ readInstances(in, numInstances, pmf.getModel(), pm, cls);
+
+ // Add OIDs for the extent
+ oids = new ArrayList(numOIDs);
+ for (int i = 0; i < numOIDs; i++) {
+ OID oid = OID.read(in);
+ if (logger.isDebugEnabled()) {
+ logger.debug("GER.hR/4: " + oid + // NOI18N
+ " " + Tester.toHex(oid.oid, 16)); // NOI18N
+ }
+ oids.add(oid);
+ }
+ }
+
+
+ /**
+ * Reads instances from given DataInput using a {@link FieldFetcher}.
+ * @param in DataInput from which instances are read.
+ * @param numInstances Number of instances to read from <code>in</code>.
+ * @param model Model required to by {@link FieldFetcher}.
+ * @param pm PersistenceManagerInternal required {@link FieldFetcher}.
+ * @param cls Candidate Class for which instances are being obtained.
+ * @return ArrayList of instances read.
+ */
+ static ArrayList readInstances(DataInput in, int numInstances,
+ FOStoreModel model,
+ PersistenceManagerInternal pm,
+ Class cls)
+ throws IOException {
+
+ ArrayList rc = new ArrayList(numInstances);
+ for (int i = 0; i < numInstances; i++) {
+ OID oid = OID.read(in);
+ if (logger.isDebugEnabled()) {
+ logger.debug("GER.readInstances/1: " + oid + // NOI18N
+ " " + Tester.toHex(oid.oid, 16)); // NOI18N
+ }
+
+ // Fill in pc's fields.
+ int objLength = in.readInt();
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GER.readInstances/2: reading " + objLength + // NOI18N
+ " bytes"); // NOI18N
+ }
+ byte data[] = new byte[objLength];
+ in.readFully(data);
+ FieldFetcher ff =
+ new FieldFetcher(new FOStoreInput(data, 0, objLength),
+ model,
+ pm,
+ cls.getClassLoader());
+ StateManagerInternal sm = ff.fetch(oid);
+ Object pc = sm.getObject();
+ rc.add(pc);
+ }
+ return rc;
+ }
+
+ /** Returns max number of instances */
+ int getMaxInstances() {
+ return maxInstances;
+ }
+
+ /** Returns the list of instances */
+ ArrayList getInstances() {
+ return instances;
+ }
+
+ /** Returns the list of object id's */
+ ArrayList getOIDs() {
+ return oids;
+ }
+
+ /** Returns the Extent associated with this request */
+ Extent getExtent() {
+ return extent;
+ }
+
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,101 @@
+/*
+ * 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.HashSet;
+import java.util.Iterator;
+
+/**
+* Process GetInstances requests.
+*
+* @author Dave Bristor
+*/
+// This is server-side code. It does not need to live in the client.
+class GetInstancesHandler extends RequestHandler {
+
+ private GetInstancesHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+
+ super(reply, length, con);
+ }
+
+ public static final HandlerFactory factory =
+ new HandlerFactory() {
+ public RequestHandler getHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ return new GetInstancesHandler(reply, length, con);
+ }};
+
+ /**
+ * Get some instances from the database, and return them.
+ */
+ RequestFinisher handleRequest()
+ throws IOException, FOStoreDatabaseException {
+
+ FOStoreInput in = con.getInputFromClient();
+ FOStoreDatabase db = con.getDatabase();
+
+ int numInstances = in.readInt();
+
+ Status status = null;
+
+ int numReturned = 0;
+ int numReturnedPos = reply.beginStash();
+
+ for (int i = 0; i < numInstances; i++) {
+ try {
+ OID oid = OID.read(in);
+ reply.writeOID(oid);
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetInstancesHandler.hR/2: " + // NOI18N
+ oid + " " + // NOI18N
+ Tester.toHex(oid.oid, 16));
+ }
+
+ Block block = (Block)db.get(oid);
+ if (logger.isTraceEnabled()) {
+ block.dump();
+ }
+
+ byte data[] = block.getData();
+ reply.writeInt(data.length);
+ reply.write(data);
+ numReturned++;
+ } catch (FOStoreDatabaseException ex) {
+ status = Status.WARN;
+ }
+ }
+
+ reply.endStash(numReturned, numReturnedPos);
+
+ if (null == status) {
+ status = Status.OK;
+ }
+ reply.setStatus(status);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetInstancesHandler.hR/3: " + // NOI18N
+ "numReturned=" + numReturned + ": " +status); // NOI18N
+ }
+ return null;
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetInstancesRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,128 @@
+/*
+ * 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 org.apache.jdo.pm.PersistenceManagerInternal;
+
+
+/**
+ * Represents a request to fetch a batch of instances.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code. It does not need to live in the server.
+//
+class GetInstancesRequest extends AbstractRequest {
+ /** List of oids from which we get instances. */
+ private final ArrayList oids;
+
+ /** Starting position in oids ArrayList. */
+ private final int start;
+
+ /** Number of instances to get. */
+ private final int numInstances;
+
+ /** The PersistenceManagerInternal that is making this request. */
+ private final PersistenceManagerInternal pm;
+
+ /** Candidate class for which instances are being obtained. */
+ private final Class cls;
+
+ /** ArrayList returned to user. */
+ private ArrayList instances;
+
+ GetInstancesRequest(ArrayList oids, int start, int numInstances,
+ Message m, PersistenceManagerInternal pm, Class cls) {
+
+ super(m, (FOStorePMF)pm.getPersistenceManagerFactory());
+ this.oids = oids;
+ this.start = start;
+ this.numInstances = numInstances;
+ this.pm = pm;
+ this.cls = cls;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("GetInstancesRequest: " + // NOI18N
+ "start=" + start + // NOI18N
+ ", numInstances=" + numInstances); // NOI18N
+ }
+ }
+
+ ArrayList getInstances() {
+ return instances;
+ }
+
+ //
+ // Methods from AbstractRequest
+ //
+
+ protected void doRequestBody() throws IOException {
+ //
+ // The format of this request is (aside from the request header):
+ //
+ // int: numOIDs
+ // oid: OID...
+ //
+
+ int numRequested = numInstances;
+ if (start + numInstances > oids.size()) {
+ numRequested = oids.size() - start;
+ }
+
+ out.writeInt(numRequested);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "GetInstancesRequest.dRB/0: max=" + numRequested); // NOI18N
+ }
+
+ int end = start + numRequested;
+ for (int i = start; i < end; i++) {
+ OID oid = (OID)oids.get(i);
+ oid.write(out);
+ }
+ }
+
+
+ //
+ // Methods from Request
+ //
+
+ public void handleReply(Status status, DataInput in, int length)
+ throws IOException {
+
+ //
+ // The format of this reply is
+ //
+ // int: number of instances
+ // that many instances
+ //
+
+ int numReturned = in.readInt();
+ if (logger.isDebugEnabled()) {
+ logger.debug("GetInstancesRequest.hR: numReturned=" + // NOI18N
+ numReturned);
+ }
+ instances = GetExtentRequest.readInstances(
+ in, numReturned, pmf.getModel(), pm, cls);
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/I18N.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/I18N.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/I18N.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/I18N.java Sun May 22 11:40:13 2005
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+* Provides I18N information for FOStore.
+*
+* @author Dave Bristor
+*/
+class I18N {
+ /** Name of the resource bundle for FOStore. */
+ static final String NAME = "org.apache.jdo.impl.fostore.Bundle"; // NOI18N
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,324 @@
+/*
+ * 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 javax.jdo.JDOFatalDataStoreException;
+
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* Process requests to insert objects in the datastore.
+*
+* @author Dave Bristor
+*/
+//
+// This is server-side code. It does not need to live in the client.
+//
+class InsertHandler extends RequestHandler {
+
+ /** I18N help */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ InsertHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+
+ super(reply, length, con);
+ }
+
+ static final HandlerFactory factory =
+ new HandlerFactory() {
+ public RequestHandler getHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ return new InsertHandler(reply, length, con);
+ }};
+
+
+ /**
+ * Changes all provisional OID's in an instance's in-store Block to real,
+ * datastore OID's.
+ */
+ private class InsertFinisher implements RequestFinisher {
+ private final FOStoreDatabase db;
+
+ // This is the oid of the object in which we're going to replace the
+ // provisional OID with a real OID.
+ private final OID oid;
+
+ // Offsets into the Block mapped by OID at which provisional OID's
+ // lie. Replace them with datastore OID's.
+ private final int oidOffsets[];
+
+ // Offsets into the Block's CLID appendix at which provisional CLID's
+ // lie. Replace them with datastore CLID's.
+ private final int clidOffsets[];
+
+ InsertFinisher(FOStoreDatabase db, OID oid, DataInput in)
+ throws IOException {
+ this.db = db;
+ this.oid = oid;
+
+ // Read oidOffsets
+ int numOIDOffsets = in.readInt();
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertFinisher: numOIDOffsets=" + // NOI18N
+ numOIDOffsets);
+ }
+
+ this.oidOffsets = numOIDOffsets > 0 ? new int[numOIDOffsets] : null;
+ if (numOIDOffsets > 0) {
+ for (int i = 0; i < numOIDOffsets; i++) {
+ oidOffsets[i] = in.readInt();
+ }
+ }
+
+ // Read CLID offsets
+ int numCLIDOffsets = in.readInt();
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertFinisher: numCLIDOffsets=" + // NOI18N
+ numCLIDOffsets);
+ }
+ this.clidOffsets = numCLIDOffsets > 0 ? new int[numCLIDOffsets] : null;
+ if (numCLIDOffsets > 0) {
+ for (int i = 0; i < numCLIDOffsets; i++) {
+ clidOffsets[i] = in.readInt();
+ }
+ }
+ }
+
+ /**
+ * Replace all provisional OIDs in the data with real OIDs.
+ * Byte array data is the datablock containing provisional OID's which
+ * need to be converted in-place.
+ */
+ private void finishOIDOffsets(byte data[])
+ throws FOStoreDatabaseException, IOException {
+
+ FOStoreInput in =
+ new FOStoreInput(data, 0, data.length);
+ FOStoreOutput out = new FOStoreOutput();
+
+ if (null != oidOffsets) {
+ int numOIDOffsets = oidOffsets.length;
+ for (int i = 0; i < numOIDOffsets; i++) {
+ int offset = oidOffsets[i];
+ in.setPos(offset);
+ OID provOID = OID.read(in);
+ OID realOID = db.getRealOIDFromProvisional(provOID);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertFinisher.finish: i=" + i // NOI18N
+ + " offset="+ offset); // NOI18N
+ logger.debug("InsertFinisher.finish: prov" + provOID +
+ " " // NOI18N
+ + Tester.toHex(provOID.oid, 16));
+ logger.debug("InsertFinisher.finish: real" + realOID +
+ " " // NOI18N
+ + Tester.toHex(realOID.oid, 16));
+ }
+
+ // Write the real OID
+ // XXX PERF Best way to convert a long to byte array?
+ // XXX Conversion should be done by OID itself, since only
+ // it really knows it's representation is a long.
+ realOID.write(out);
+ System.arraycopy(out.getBuf(), 0, data, offset, 8);
+ out.setPos(0); // Set for next time through.
+ }
+ }
+ }
+
+ /**
+ * Replace all provisional CLIDs in the data with real CLIDs.
+ * Byte array data is the datablock containing provisional CLID's
+ * which need to be converted in-place.
+ */
+ private void finishCLIDOffsets(byte data[])
+ throws FOStoreDatabaseException, IOException {
+
+ FOStoreInput in =
+ new FOStoreInput(data, 0, data.length);
+ FOStoreOutput out = new FOStoreOutput();
+
+ if (null != clidOffsets) {
+ int numCLIDOffsets = clidOffsets.length;
+ for (int i = 0; i < numCLIDOffsets; i++) {
+ int offset = clidOffsets[i];
+ in.setPos(offset);
+ CLID provCLID = CLID.read(in);
+ CLID realCLID = db.getRealCLIDFromProvisional(provCLID);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertFinisher.finish: i=" + i // NOI18N
+ + " offset="+ offset); // NOI18N
+ logger.debug("InsertFinisher.finish: prov" + provCLID); // NOI18N
+ logger.debug("InsertFinisher.finish: real" + realCLID); // NOI18N
+ }
+
+ if (null == realCLID) {
+ throw new JDOFatalDataStoreException(
+ msg.msg("ERR_NullRealCLID", provCLID)); // NOI18N
+ }
+
+ // Write the real CLID
+ // XXX PERF Best way to convert an int to byte array?
+ // XXX Conversion should be done by CLID itself, since only
+ // it really knows its representation is an int.
+ realCLID.write(out);
+ System.arraycopy(out.getBuf(), 0, data, offset, 4);
+ out.setPos(0);
+ }
+ }
+ }
+
+ /**
+ * @see RequestFinisher#finish
+ */
+ public void finish() {
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertFinisher.finish: " + oid); // NOI18N
+ }
+
+ if (null != oidOffsets || null != clidOffsets) {
+ try {
+ Block block = (Block)db.get(oid);
+ byte data[] = block.getData();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertFinisher.finish: block length=" + // NOI18N
+ data.length);
+ }
+
+ // Replace each provisional OID with a datastore OID.
+ finishOIDOffsets(data);
+
+ // Replace each provisional CLID with a datastore CLID.
+ finishCLIDOffsets(data);
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("InsertFinisher: after finalizing"); // NOI18N
+ block.dump();
+ }
+
+ } catch (FOStoreDatabaseException ex) {
+ throw new FOStoreFatalInternalException(
+ this.getClass(), "finish", ex); // NOI18N
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "finish", ex); // NOI18N
+ }
+ }
+ }
+ }
+
+
+ /**
+ * @see RequestHandler#handleRequest
+ */
+ RequestFinisher handleRequest()
+ throws IOException, FOStoreDatabaseException {
+
+ RequestFinisher rc = null;
+ FOStoreInput in = con.getInputFromClient();
+ FOStoreDatabase db = con.getDatabase();
+ DBInfo dbInfo = db.getDBInfo();
+
+ OID oid = OID.read(in);
+ CLID clid = oid.getCLID();
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertHandler.hR/1: given" + oid // NOI18N
+ + " " + Tester.toHex(oid.oid, 16)); // NOI18N
+ }
+
+ if (clid.isProvisional()) {
+ clid = db.getRealCLIDFromProvisional(clid);
+ }
+
+ OID realOID;
+ if (oid.isProvisional()) {
+ realOID = db.getRealOIDFromProvisional(oid);
+ if (null == realOID) {
+ realOID = dbInfo.newInstanceOID(clid);
+ }
+ } else {
+ realOID = oid;
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertHandler.hR/2: real" + realOID + " " // NOI18N
+ + Tester.toHex(realOID.oid, 16));
+ }
+ Block block = readBlock(in);
+
+ rc = new InsertFinisher(db, realOID, in);
+
+ try {
+ updateDB(realOID, oid, block, db);
+
+ reply.writeOID(realOID);
+ reply.setStatus(Status.OK);
+
+ } catch (Exception ex) {
+ reply.writeOID(realOID);
+ reply.setStatus(Status.ERROR,
+ msg.msg("ERR_InsertException", realOID)); // NOI18N
+ }
+
+ return rc;
+ }
+
+ protected Block readBlock(FOStoreInput in) throws IOException {
+ int blockLength = in.readInt();
+ Block block = FOStoreDatabase.createBlock(in, blockLength);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertHandler.readBlock: blockLength="+ // NOI18N
+ blockLength);
+ if (logger.isTraceEnabled()) {
+ block.dump();
+ }
+ }
+ return block;
+ }
+
+ /**
+ * Add the block to the database, and to the database's extent.
+ * @param realOID OID to use as key in the database.
+ * @param givenOID by which object was inserted, possibly provisional.
+ * @param block Block to be inserted in database.
+ * @param db Database into which block is inserted.
+ */
+ protected void updateDB(OID realOID, OID givenOID, Block block,
+ FOStoreDatabase db)
+ throws IOException, FOStoreDatabaseException {
+
+ db.add(realOID, block);
+ if (givenOID.isProvisional()) {
+ db.mapProvisionalOIDToReal(givenOID, realOID);
+ }
+
+ // Add instance to its extent
+ DBInfo dbInfo = db.getDBInfo();
+ OID extentOID = dbInfo.getExtentOID(realOID.getCLID());
+ DBExtent dbExtent = (DBExtent)db.get(extentOID);
+ dbExtent.add(realOID);
+ con.addExtent(dbExtent);
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/InsertRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,537 @@
+/*
+ * 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.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.jdo.model.jdo.PersistenceModifier;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.sco.SCOCollection;
+import org.apache.jdo.sco.SCOMap;
+import org.apache.jdo.state.FieldManager;
+import org.apache.jdo.state.StateManagerInternal;
+
+/**
+ * Represents a request to write a new object to the datastore.
+ *
+ * @author Dave Bristor
+ * @version 1.0.1
+ */
+//
+// This is client-side code. It does not need to live in the server.
+//
+class InsertRequest extends AbstractFieldRequest {
+ // Provisional object id of object being inserted by this request.
+ private final OID oid;
+
+ // Metadata for this object.
+ private final FOStoreModel model;
+
+ private final Class cls;
+
+ // Set of CLID's of the object instances referenced by this object's
+ // fields (note that Strings are omitted). This is sent to the store
+ // along with the object values, as an appendix, so that when
+ // reconstituting the object, information about the referenced classes is
+ // available. Of course, metadata for the object is available (it was or
+ // will be sent to the store in an ActivateClassRequest), but that field
+ // information is about the type of referenced objects, not about their
+ // class. See storeObjectField().
+ private Set clids = null;
+
+ // Set of int arrays of object references in this object which are
+ // provisional, as offsets of OID's in the request buffer. See the end
+ // of doRequestBody, and storeObjectField(). Each field may add one
+ // entry to the ArrayList; each field may have any number of offsets
+ // within it. totNumOffsets is the total number of offsets, across all
+ // arrays in the ArrayList.
+ private ArrayList oidOffsets = new ArrayList();
+ private int numOidOffsets = 0;
+
+ private int clidOffsets[];
+ private int numClidOffsets;
+
+ InsertRequest(StateManagerInternal sm, Message m, FOStorePMF pmf) {
+ super(sm, m, pmf);
+ this.oid = (OID)sm.getInternalObjectId();
+ this.model = pmf.getModel();
+ this.cls = sm.getPCClass();
+ }
+
+ //
+ // Methods from AbstractRequest
+ //
+
+ /**
+ * Provides detail about data being inserted in an InsertRequest.
+ * The format of this request is (aside from the request header):
+ * <pre>
+ * oid: OID
+ * length of data block containing classname, field values, CLID info: int
+ * className: String (fully qualified name of class of object)
+ * fostoreSchemaUID for class
+ * length of the field values part of this block: int
+ * fieldValue: Object... (repeats numFields times)
+ * number of [CLID, classname] pairs for Object fields of this object
+ * [CLID, classname]...
+ * (the following are not in the above noted length bytes of this block)
+ * number of provisional OID's written in this request
+ * OID offset...
+ * number of the above written CLIDs that are provisional
+ * CLID offset...
+ * </pre>
+ *
+ * In the case of both the OID and CLID offsets, the offset is from
+ * the beginning of the block. In the case of the CLIDs and the OID
+ * and CLID offsets, the size of each set written may be zero but
+ * that size is always written.
+ * <p>
+ * Note that the number of CLID/classname pairs and the CLID/classname
+ * pairs themselves are part of the data block that is intended to be
+ * stored by the database server (and hence later returned upon
+ * fetch/getExtent). That is, the size written includes those pairs.
+ * The offsets, however, are not part of the datablock; they are used
+ * by the database server and discarded.
+ * @see AbstractRequest#doRequestBody
+ */
+ protected void doRequestBody() throws IOException {
+ oid.write(out);
+
+ // Write out the values of all the fields.
+ int startPos = writeBlock(jdoClass.getPersistentFieldNumbers(), false);
+
+ // Now write the oidOffsets, so that the store can turn provisional
+ // OID's into datastore OID's.
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertRequest.dRB: numoidOffsets=" + // NOI18N
+ numOidOffsets);
+ }
+ out.writeInt(numOidOffsets);
+ int size = oidOffsets.size();
+ for (int i = 0; i < size; i++) {
+ int fieldOffsets[] = (int[])(oidOffsets.get(i));
+ int numOffsets = fieldOffsets.length;
+ for (int j = 0; j < numOffsets; j++) {
+ // Write out offset relative to start of the data block.
+ out.writeInt(fieldOffsets[j] - startPos);
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "InsertRequest.dRB: " + oid // NOI18N
+ + " rawOffset=" + fieldOffsets[j] // NOI18N
+ + " offset=" + // NOI18N
+ (fieldOffsets[j] - startPos));
+ }
+ }
+ }
+
+ // Now write the offsets of the provisional CLID's
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertRequest.dRB: numClidOffsets=" + // NOI18N
+ numClidOffsets);
+ }
+ out.writeInt(numClidOffsets);
+ for (int i = 0; i < numClidOffsets; i++) {
+ out.writeInt(clidOffsets[i]);
+ }
+ }
+
+ //
+ // Methods from Request
+ //
+
+ /**
+ * Reads the oid, and notifies the persistence manager and state manager
+ * of the new oid.
+ * @see Request#handleReply
+ */
+ public void handleReply(Status status, DataInput in, int length)
+ throws IOException {
+
+ OID replyOid = OID.read(in);
+
+ // We don't have to update the cache, because we will when the
+ // instance was made persistent, we did a CreateOIDRequest, and it's
+ // reply updated the cache.
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertRequest.hR: " + status + ", " + // NOI18N
+ oid + " " + // NOI18N
+ Tester.toHex(oid.oid, 16) +
+ " -> " + replyOid + " " + // NOI18N
+ Tester.toHex(replyOid.oid, 16));
+ }
+ }
+
+ //
+ // Methods from FieldManager
+ //
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeBooleanField(int fieldNum,
+ * boolean value)
+ */
+ public void storeBooleanField(int fieldNum, boolean value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeBoolean(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeBooleanField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeCharField(int fieldNum,
+ * char value)
+ */
+ public void storeCharField(int fieldNum, char value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeChar(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeCharField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeByteField(int fieldNum,
+ * byte value)
+ */
+ public void storeByteField(int fieldNum, byte value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeByte(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeByteField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeShortField(int fieldNum,
+ * short value)
+ */
+ public void storeShortField(int fieldNum, short value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeShort(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeShortField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeIntField(int fieldNum, int value)
+ */
+ public void storeIntField(int fieldNum, int value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeInt(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeIntField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeLongField(int fieldNum,
+ * long value)
+ */
+ public void storeLongField(int fieldNum, long value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeLong(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeLongField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeFloatField(int fieldNum,
+ * float value)
+ */
+ public void storeFloatField(int fieldNum, float value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeFloat(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeFloatField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeDoubleField(int fieldNum,
+ * double value)
+ */
+ public void storeDoubleField(int fieldNum, double value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ t.storeDouble(value, out);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeDoubleField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeStringField(int fieldNum,
+ * String value)
+ */
+ public void storeStringField(int fieldNum, String value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ // Though it is a String, we need to preserve pm value
+ // in the ObjectTranscriber in case this is request
+ // to fetch a PC (embedded or because its field is accessed.
+ PersistenceManagerInternal pm =
+ (PersistenceManagerInternal)sm.getPersistenceManager();
+ t.storeObject(value, out, pm);
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeStringField", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.state.FieldManager#storeObjectField(int fieldNum,
+ * Object value)
+ */
+ public void storeObjectField(int fieldNum, Object value) {
+ FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+ try {
+ PersistenceManagerInternal pm =
+ (PersistenceManagerInternal)sm.getPersistenceManager();
+ int fieldOffsets[] = t.storeObject(value, out, pm);
+
+ // Add the field's object's CLID.
+ addCLID(value);
+
+ // If value is Collection, Map, or array then need to add the
+ // Class's of its elements.
+ if (null != value) {
+ if (value instanceof Collection) {
+ addCollectionCLIDs((Collection)value);
+ } else if (value instanceof Map) {
+ addMapCLIDs((Map)value);
+ } else {
+ Class cls = value.getClass().getComponentType();
+ if (null != cls) {
+ // We have an array. We have to add the CLIDs for all
+ // its elements, not just for the component type,
+ // because the class of the elements could be a
+ // subclass or implementation of the component type.
+ addArrayCLIDs(value);
+ }
+ }
+ }
+
+ // Check for and store offsets.
+ if (null != fieldOffsets) {
+ oidOffsets.add(fieldOffsets);
+ numOidOffsets += fieldOffsets.length;
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "InsertRequest.sOF: fieldNum=" + fieldNum // NOI18N
+ + " numOffsets=" + fieldOffsets.length); // NOI18N
+ }
+ }
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "storeObjectField", ex); // NOI18N
+ }
+ }
+
+ //
+ // Implementation detail
+ //
+
+ protected OID getOID() {
+ return oid;
+ }
+
+ /**
+ * Writes a data block, which consists of the values of the specified
+ * fields, plus the CLID's and corresponding class names of referenced
+ * objects.
+ * @param fields Field numbers of the fields to be written
+ * @param identifying If true, write before/flushed image fields,
+ * otherwise write current fields.
+ * @return Position in output stream at which data block starts
+ */
+ protected int writeBlock(int fields[], boolean identifying) throws IOException {
+ // Save and overwrite the position where we later write the length of
+ // the data.
+ int dataLengthPos = out.getPos();
+ out.writeInt(LENGTH_COOKIE);
+
+ // Save start of data block
+ int startPos = out.getPos();
+
+ // Initialize list of CLIDs used by this instance
+ clids = new HashSet();
+
+ // Fully qualified class name and FOStoreSchemaUID
+ if (logger.isDebugEnabled()) {
+ logger.debug("IR: className=" + jdoClass.getName() + // NOI18N
+ ", fsuid=" + fsuid); // NOI18N
+ }
+ out.writeUTF(jdoClass.getName());
+ fsuid.write(out);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertRequest.writeBlock: classname=" + // NOI18N
+ jdoClass.getName());
+ }
+
+ insertFields(fields, identifying);
+
+ // Write the CLID's and classnames. Some might be provisional, so as
+ // with the OID's we must write their offsets so they can be turned
+ // into real CLID's in the store. Here we save the offsets, to write
+ // them later, after the data block.
+ int size = clids.size();
+ clidOffsets = new int[size]; // Max num of possible provisionals
+ numClidOffsets = 0;
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "InsertRequest.writeBlock: numCLID's=" + // NOI18N
+ size);
+ }
+ out.writeInt(size);
+ for (Iterator i = clids.iterator(); i.hasNext();) {
+ CLID c = (CLID)i.next();
+ if (c.isProvisional()) {
+ clidOffsets[numClidOffsets++] = out.getPos() - startPos;
+ }
+ c.write(out);
+ Class clz = CLID.getKnownType(c);
+ if (null == clz) {
+ clz = model.getClass(c);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertRequest.writeBlock: " + c); // NOI18N
+ }
+ String className = clz.getName();
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "InsertRequest.writeBlock: field type " + // NOI18N
+ className);
+ }
+ out.writeUTF(className);
+ FOStoreSchemaUID fldUID = FOStoreSchemaUID.lookup(clz, model);
+ fldUID.write(out);
+ }
+
+ // Write the length of the block (data + CLID's)
+ int currentPos = out.getPos();
+ int length = currentPos - startPos;
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertRequest.dRB: length=" + length); // NOI18N
+ }
+ out.setPos(dataLengthPos);
+ out.writeInt(length);
+ out.setPos(currentPos);
+
+ return startPos;
+ }
+
+ /**
+ * Writes values of the specified fields. If identifying is true, writes
+ * identifying fields, otherwise writes current fields.
+ */
+ private void insertFields(int[] fields, boolean identifying)
+ throws IOException {
+
+ int fieldLengthPos = out.getPos();
+ out.writeInt(LENGTH_COOKIE);
+ int fieldPos = out.getPos();
+
+ sm.provideFields(fields, this, identifying);
+
+ // Write the length of the field values part of the block.
+ int currentPos = out.getPos();
+ int length = currentPos - fieldPos;
+ out.setPos(fieldLengthPos);
+ out.writeInt(length);
+ out.setPos(currentPos);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("InsertRequest.dRB: field values length=" + length); // NOI18N
+ }
+ }
+
+ private void addCollectionCLIDs(Collection c) {
+ Iterator i;
+ if (c instanceof SCOCollection) {
+ SCOCollection sco = (SCOCollection)c;
+ i = sco.eitherIterator();
+ } else {
+ i = c.iterator();
+ }
+ while(i.hasNext()) {
+ addCLID(i.next());
+ }
+ }
+
+ private void addMapCLIDs(Map m) {
+ Iterator i = null;
+ if (m instanceof SCOMap) {
+ i = ((SCOMap)m).eitherIterator();
+ } else {
+ i = m.entrySet().iterator();
+ }
+ while (i.hasNext()) {
+ Map.Entry entry = (Map.Entry)i.next();
+ addCLID(entry.getKey());
+ addCLID(entry.getValue());
+ }
+ }
+
+ private void addArrayCLIDs(Object arr) {
+ try {
+ int length = Array.getLength(arr);
+ for (int i = 0; i < length; i++) {
+ Object o = Array.get(arr, i);
+ addCLID(o);
+ }
+ } catch (RuntimeException ex) {
+ throw new FOStoreFatalInternalException(
+ this.getClass(), "addArrayCLIDs", ex); // NOI18N
+ }
+ }
+
+ private void addCLID(Object o) {
+ if (null != o) {
+ Class cls = o.getClass();
+ if (! CLID.isKnown(cls)) {
+ clids.add(model.getCLID(cls));
+ }
+ }
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/IntTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/IntTranscriber.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/IntTranscriber.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/IntTranscriber.java Sun May 22 11:40:13 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 int values.
+*
+* @author Dave Bristor
+*/
+class IntTranscriber extends FOStoreTranscriber {
+ private static IntTranscriber instance = new IntTranscriber();
+
+ private IntTranscriber() {}
+
+ static IntTranscriber getInstance() {
+ return instance;
+ }
+
+ void storeInt(int value, DataOutput out) throws IOException {
+ out.writeInt(value);
+ }
+
+ int fetchInt(DataInput in) throws IOException {
+ return in.readInt();
+ }
+
+ void skip(DataInput in) throws IOException {
+ in.readInt();
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginHandler.java Sun May 22 11:40:13 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.
+ */
+
+/*
+ * Handler for LoginRequests.
+ *
+ * LoginHandler.java
+ *
+ * Created on June 7, 2001, 4:16 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.IOException;
+import java.io.DataInput;
+import java.io.DataOutput;
+
+import javax.jdo.JDODataStoreException;
+import javax.jdo.JDOFatalDataStoreException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * Handler for LoginRequests.
+ * @author Craig Russell
+ * @version 1.0
+ */
+class LoginHandler extends RequestHandler {
+ /** the database name
+ */
+ String dbname;
+
+ /** the user of the database
+ */
+ String user;
+
+ /** a pseudo random number
+ */
+ long timestamp;
+
+ /** a message digest which is a shared secret
+ */
+ byte[] secret;
+
+ /** a flag to tell whether to create the database
+ */
+ boolean create;
+
+ /** Construct an instance of the LoginHandler to service this request.
+ * @param reply the reply for the request
+ * @param length the length of the request
+ * @param con the FOStoreServerConnection with the request
+ */
+ private LoginHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+
+ super(reply, length, con);
+ }
+
+ /** the factory used to create the handler for this request
+ */
+ public static final HandlerFactory factory =
+ new HandlerFactory() {
+ public RequestHandler getHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ return new LoginHandler(reply, length, con);
+ }};
+
+ /** Process the request by analyzing the database and user login information
+ * from the request buffer. This will create the database if needed, open
+ * it, and verify the user and password.
+ *
+ * @throws IOException if any problems
+ * @return null; there is no need for a finisher.
+ */
+ RequestFinisher handleRequest()
+ throws IOException, FOStoreDatabaseException {
+ DataInput in = con.getInputFromClient();
+ // read the utf encoded user and password for verification.
+ dbname = in.readUTF();
+ user = in.readUTF();
+ timestamp = in.readLong();
+ int secretSize = in.readInt();
+ secret = new byte[secretSize];
+ in.readFully(secret);
+ create = in.readBoolean();
+ try {
+ con.openDatabase(dbname, user, timestamp, secret, create);
+ } catch (Exception e) {
+ throw new FOStoreLoginException(dbname, user, e);
+ }
+ reply.setStatus(Status.OK);
+ return null;
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LoginRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+/*
+ * Request to login to a database.
+ *
+ * LoginRequest.java
+ *
+ * Created on June 7, 2001, 3:28 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.IOException;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.jdo.JDODataStoreException;
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * Request to login to a database.
+ * @author Craig Russell
+ * @version 1.0
+ */
+class LoginRequest extends AbstractRequest {
+ /** The database name from the PMF URL property.
+ */
+ String dbname;
+
+ /** The user from the PMF user property.
+ */
+ String user;
+
+ /** The password from the PMF password property.
+ */
+ String password;
+
+ /** This is the Date.getTime() of the time the request
+ * was created. It is used to construct the shared secret
+ * to verify the password at the server side, without
+ * transmitting the password in clear.
+ */
+ long timestamp;
+
+ /** The secret constructed from the user, timestamp, and password.
+ */
+ byte[] secret;
+
+ /** A flag telling whether to create the database
+ */
+ boolean create;
+
+ /** Creates new LoginRequest
+ * @param m the Message
+ * @param pmf the PersistenceManagerFactory
+ * @param user the user
+ * @param password the password
+ */
+ public LoginRequest(Message m, FOStorePMF pmf, String dbname, String user, String password, boolean create) {
+ super (m, pmf);
+ this.dbname = dbname;
+ this.user = user;
+ this.password = password;
+ this.create = create;
+ timestamp = new Date().getTime();
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("MD5"); // NOI18N
+ md.update (dbname.getBytes("UTF-8")); // NOI18N
+ md.update (user.getBytes("UTF-8")); // NOI18N
+ md.update ((Long.toString(timestamp)).getBytes("UTF-8")); // NOI18N
+// md.update (password.getBytes("UTF-8")); // XXX add back when database can look up password
+ this.secret = md.digest();
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new JDOFatalInternalException (
+ msg.msg("ERR_NoSuchAlgorithmException", dbname, user), // NOI18N
+ new Exception[]{nsae});
+ } catch (UnsupportedEncodingException uee) {
+ throw new JDOFatalInternalException (
+ msg.msg("ERR_UnsupportedEncodingException", dbname), // NOI18N
+ new Exception[]{uee});
+ }
+ }
+
+ /**
+ * Subclasses must implement in this method the actual writing of their
+ * Request type-specific data.
+ * @throws IOException if any errors constructing the stream
+ */
+ protected void doRequestBody() throws IOException {
+ //
+ // The format of this request is (aside from the request header):
+ //
+ // dbname: the database name property (part of the URL) of the PMF
+ // user: the user property of the PMF
+ // timestamp: the current Date in milliseconds
+ // XXX change the following to be a shared secret based on the password
+ // password: the password property of the PMF
+ // secret.length: the length of the secret
+ // secret: the secret as a byte array
+
+ if (logger.isDebugEnabled()) logger.debug("LoginRequest.dRB"); // NOI18N
+ out.writeUTF (dbname);
+ out.writeUTF (user);
+ out.writeLong (timestamp);
+ out.writeInt (secret.length);
+ out.write (secret);
+ out.writeBoolean (create);
+ }
+
+ /**
+ * Processes the results of the effect of the request in the store. To be
+ * invoked after the store has processed the request, and has returned
+ * information about that request, such as its status and any accompanying
+ * data.
+ * @param in
+ * @param length
+ * @param status Indication as to the success, failure, etc. of the
+ * request as handled by the store.
+ * @throws IOException
+ */
+ public void handleReply(Status status, DataInput in, int length) throws IOException {
+ if (logger.isDebugEnabled()) logger.debug("LoginRequest.hR"); // NOI18N
+
+ if (!status.equals (Status.OK)) {
+ throw new JDODataStoreException (msg.msg("EXC_CannotLogin")); // NOI18N
+ }
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LongTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LongTranscriber.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LongTranscriber.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/LongTranscriber.java Sun May 22 11:40:13 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 long values.
+*
+* @author Dave Bristor
+*/
+class LongTranscriber extends FOStoreTranscriber {
+ private static LongTranscriber instance = new LongTranscriber();
+
+ private LongTranscriber() {}
+
+ static LongTranscriber getInstance() {
+ return instance;
+ }
+
+ void storeLong(long value, DataOutput out) throws IOException {
+ out.writeLong(value);
+ }
+
+ long fetchLong(DataInput in) throws IOException {
+ return in.readLong();
+ }
+
+ void skip(DataInput in) throws IOException {
+ in.readLong();
+ }
+}