Package com.sun.sgs.impl.service.data

Source Code of com.sun.sgs.impl.service.data.ReferenceTable

/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* --
*/

package com.sun.sgs.impl.service.data;

import com.sun.sgs.app.ManagedObject;
import com.sun.sgs.app.TransactionNotActiveException;
import com.sun.sgs.impl.util.WeakIdentityMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

/**
* Stores information about managed references within a particular transaction.
* This class is logically part of the ManagedReferenceImpl class.
*/
final class ReferenceTable {

    /**
     * A map whose keys are stale managed objects, if tracking stale objects.
     */
    private static final WeakIdentityMap<Object, Boolean>
  staleObjects = new WeakIdentityMap<Object, Boolean>();

    /** Maps object IDs to managed references. */
    private final SortedMap<Long, ManagedReferenceImpl<?>> oids =
  new TreeMap<Long, ManagedReferenceImpl<?>>();

    /**
     * Maps managed objects to managed references.  The objects are compared by
     * identity, not the equals method.
     */
    private final Map<ManagedObject, ManagedReferenceImpl<?>> objects =
  new IdentityHashMap<ManagedObject, ManagedReferenceImpl<?>>();

    /** Whether to track stale objects. */
    private final boolean trackStaleObjects;

    /**
     * Creates an instance of this class.
     *
     * @param  trackStaleObjects whether to track stale objects
     */
    ReferenceTable(boolean trackStaleObjects) {
  this.trackStaleObjects = trackStaleObjects;
    }

    /**
     * Finds the managed reference associated with a managed object, returning
     * null if no reference is found.
     */
    ManagedReferenceImpl<?> find(ManagedObject object) {
  assert object != null : "Object is null";
        ManagedReferenceImpl<?> result = objects.get(object);
  if (result == null &&
      trackStaleObjects &&
      staleObjects.containsKey(object))
  {
      throw new TransactionNotActiveException(
    "Attempt to access an object of type " +
    DataServiceImpl.typeName(object) +
    " whose transaction is no longer active");
  }
  return result;
    }

    /**
     * Finds the managed reference associated with an object ID, returning null
     * if no reference is found.
     */
    ManagedReferenceImpl<?> find(long oid) {
  assert oid >= 0 : "Object ID is negative";
  return oids.get(oid);
    }

    /** Adds a new managed reference to this table. */
    void add(ManagedReferenceImpl<?> ref) {
  assert !oids.containsKey(ref.oid)
      : "Found existing reference for oid:" + ref.oid;
  oids.put(ref.oid, ref);
  ManagedObject object = ref.getObject();
  if (object != null) {
      assert !objects.containsKey(object)
    : "Found existing reference for object with oid:" + ref.oid;
      objects.put(object, ref);
  }
    }

    /**
     * Updates this table for a reference that has been newly associated with
     * an object.
     */
    void registerObject(ManagedReferenceImpl<?> ref) {
  assert oids.get(ref.oid) == ref
      : "Found duplicate references for oid: " + ref.oid;
  assert ref.getObject() != null : "Object is null for oid:" + ref.oid;
  assert !objects.containsKey(ref.getObject())
      : "Found existing reference for object with oid: " + ref.oid;
  objects.put(ref.getObject(), ref);
    }

    /**
     * Updates this table for a reference that is no longer associated with an
     * object.
     */
    void unregisterObject(ManagedObject object) {
  assert objects.containsKey(object) : "Object was not found";
  objects.remove(object);
  if (trackStaleObjects) {
      staleObjects.put(object, Boolean.TRUE);
  }
    }

    /** Removes a managed reference from this table. */
    void remove(ManagedReferenceImpl<?> ref) {
  Object existing = oids.remove(ref.oid);
  assert existing == ref
      : "Found duplicate reference for oid:" + ref.oid;
  ManagedObject object = ref.getObject();
  if (object != null) {
      existing = objects.remove(object);
      assert existing == ref
    : "Found duplicate reference for oid:" + ref.oid;
  }
    }

    /**
     * Returns the next object ID in the reference table of a newly created
     * object, or -1 if none is found.  Does not return IDs for removed
     * objects.  Specifying -1 requests the first ID.
     */
    long nextNewObjectId(long oid) {
  for (Entry<Long, ManagedReferenceImpl<?>> entry :
     oids.tailMap(oid).entrySet())
  {
      long key = entry.getKey();
      if (key > oid && entry.getValue().isNew()) {
    return key;
      }
  }
  return -1;
    }

    /**
     * Flushes all references.  Returns information about any objects found to
     * be modified, or null if none were modified.
     */
    FlushInfo flushModifiedObjects() {
  FlushInfo flushInfo = null;
  for (ManagedReferenceImpl<?> ref : oids.values()) {
      byte[] data = ref.flush();
      if (data != null) {
    if (flushInfo == null) {
        flushInfo = new FlushInfo();
    }
    flushInfo.add(ref.oid, data);
      }
  }
  return flushInfo;
    }

    /**
     * Checks the consistency of this table, throwing an assertion error if a
     * problem is found.
     */
    void checkAllState() {
  int objectCount = 0;
  for (Entry<Long, ManagedReferenceImpl<?>> entry : oids.entrySet()) {
      long oid = entry.getKey();
      ManagedReferenceImpl<?> ref = entry.getValue();
      ref.checkState();
      if (oid != ref.oid) {
    throw new AssertionError(
        "Wrong oids entry: oid = " + oid + ", ref.oid = " +
        ref.oid);
      }
      Object object = ref.getObject();
      if (object != null) {
    ManagedReferenceImpl<?> objectsRef = objects.get(object);
    if (objectsRef == null) {
        throw new AssertionError(
      "Missing objects entry for oid = " + ref.oid);
    } else if (!ref.equals(objectsRef)) {
        throw new AssertionError(
      "Wrong objects entry for oid = " + ref.oid);
    }
    objectCount++;
      }
  }
  if (objectCount != objects.size()) {
      throw new AssertionError(
    "Objects table has wrong size: was " + objects.size() +
    ", expected " + objectCount);
  }
    }
}
TOP

Related Classes of com.sun.sgs.impl.service.data.ReferenceTable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.