1 4 package com.tc.objectserver.managedobject; 5 6 import com.tc.io.TCByteBufferOutputStream; 7 import com.tc.object.ObjectID; 8 import com.tc.object.dna.api.DNA; 9 import com.tc.object.dna.api.DNACursor; 10 import com.tc.object.dna.api.DNAException; 11 import com.tc.object.dna.impl.DNAEncoding; 12 import com.tc.object.dna.impl.DNAWriterImpl; 13 import com.tc.object.dna.impl.ObjectDNAWriterImpl; 14 import com.tc.object.dna.impl.ObjectStringSerializer; 15 import com.tc.object.tx.TransactionID; 16 import com.tc.objectserver.api.ObjectInstanceMonitor; 17 import com.tc.objectserver.core.api.ManagedObject; 18 import com.tc.objectserver.core.api.ManagedObjectState; 19 import com.tc.objectserver.impl.ManagedObjectReference; 20 import com.tc.objectserver.managedobject.bytecode.ClassNotCompatableException; 21 import com.tc.objectserver.mgmt.ManagedObjectFacade; 22 import com.tc.text.PrettyPrintable; 23 import com.tc.text.PrettyPrinter; 24 import com.tc.util.Assert; 25 import com.tc.util.Conversion; 26 27 import gnu.trove.TLinkable; 28 29 import java.io.IOException ; 30 import java.io.ObjectInputStream ; 31 import java.io.ObjectOutputStream ; 32 import java.io.PrintWriter ; 33 import java.io.Serializable ; 34 import java.io.StringWriter ; 35 import java.util.Set ; 36 37 44 public class ManagedObjectImpl implements ManagedObject, ManagedObjectReference, Serializable , PrettyPrintable { 45 private static final DNAEncoding DNA_STORAGE_ENCODING = new DNAEncoding(DNAEncoding.STORAGE); 46 47 private final static byte IS_NEW_OFFSET = 1; 48 private final static byte IS_DIRTY_OFFSET = 2; 49 private final static byte REFERENCED_OFFSET = 4; 50 private final static byte REMOVE_ON_RELEASE_OFFSET = 8; 51 private final static byte PINNED_OFFSET = 16; 52 private final static byte PROCESS_PENDING_OFFSET = 32; 53 54 private final static byte INITIAL_FLAG_VALUE = IS_DIRTY_OFFSET | IS_NEW_OFFSET; 55 56 final ObjectID id; 57 58 long version; 59 transient ManagedObjectState state; 60 61 private volatile transient byte flags = INITIAL_FLAG_VALUE; 63 64 private transient TLinkable previous; 66 private transient TLinkable next; 67 68 private int accessed; 69 70 public ManagedObjectImpl(ObjectID id) { 71 Assert.assertNotNull(id); 72 this.id = id; 73 } 74 75 78 public boolean isEqual(ManagedObject moi) { 79 if (this == moi) return true; 80 if (moi instanceof ManagedObjectImpl) { 81 ManagedObjectImpl mo = (ManagedObjectImpl) moi; 82 boolean rv = true; 83 rv &= id.equals(mo.id); 84 rv &= version == mo.version; 85 rv &= state.equals(mo.state); 86 return rv; 87 } else return false; 88 } 89 90 void setBasicIsNew(boolean b) { 91 setFlag(IS_NEW_OFFSET, b); 92 } 93 94 private void setBasicIsDirty(boolean b) { 95 setFlag(IS_DIRTY_OFFSET, b); 96 } 97 98 private synchronized void setFlag(int offset, boolean value) { 99 flags = Conversion.setFlag(flags, offset, value); 100 } 101 102 private synchronized boolean getFlag(int offset) { 103 return (flags & offset) == offset; 104 } 105 106 private boolean basicIsNew() { 107 return getFlag(IS_NEW_OFFSET); 108 } 109 110 private boolean basicIsDirty() { 111 return getFlag(IS_DIRTY_OFFSET); 112 } 113 114 public boolean isNew() { 115 return basicIsNew(); 116 } 117 118 public boolean isDirty() { 119 return basicIsDirty(); 120 } 121 122 public void setIsDirty(boolean isDirty) { 123 setBasicIsDirty(isDirty); 124 } 125 126 public ObjectID getID() { 127 return id; 128 } 129 130 public Set getObjectReferences() { 131 return state.getObjectReferences(); 132 } 133 134 public void addObjectReferencesTo(ManagedObjectTraverser traverser) { 135 state.addObjectReferencesTo(traverser); 136 } 137 138 public void apply(DNA dna, TransactionID txnID, BackReferences includeIDs, ObjectInstanceMonitor instanceMonitor) { 139 boolean isNew = isNew(); 140 String typeName = dna.getTypeName(); 141 if (dna.isDelta() && isNew) { 142 throw new AssertionError ("Newly created Object is applied with a delta DNA ! ManagedObjectImpl = " 144 + this.toString() + " DNA = " + dna + " TransactionID = " + txnID); 145 } 146 if (isNew) { 147 instanceMonitor.instanceCreated(typeName); 148 } 149 this.version = dna.getVersion(); 150 DNACursor cursor = dna.getCursor(); 151 152 initializeStateIfNecessary(dna.getParentObjectID(), typeName, dna.getDefiningLoaderDescription(), cursor); 153 if (state == null) { throw new AssertionError ( 154 "Attempt to apply a transaction to a managed object with null state: " 155 + this); } 156 try { 157 try { 158 state.apply(id, cursor, includeIDs); 159 } catch (ClassNotCompatableException cnce) { 160 reinitializeState(dna.getParentObjectID(), dna.getTypeName(), dna.getDefiningLoaderDescription(), cursor, state); 162 state.apply(id, cursor, includeIDs); 163 } 164 } catch (IOException e) { 165 throw new DNAException(e); 166 } 167 setIsDirty(true); 168 setBasicIsNew(false); 169 } 170 171 private void reinitializeState(ObjectID pid, String className, String loaderDesc, DNACursor cursor, 172 ManagedObjectState oldState) { 173 state = getStateFactory().recreateState(id, pid, className, loaderDesc, cursor, oldState); 174 } 175 176 private void initializeStateIfNecessary(ObjectID pid, String className, String loaderDesc, DNACursor cursor) { 177 if (state == null) { 178 state = getStateFactory().createState(id, pid, className, loaderDesc, cursor); 179 } 180 } 181 182 private ManagedObjectStateFactory getStateFactory() { 183 return ManagedObjectStateFactory.getInstance(); 184 } 185 186 private void writeObject(ObjectOutputStream out) throws IOException { 187 if (state == null) { throw new AssertionError ("Null state:" + this); } 188 out.defaultWriteObject(); 189 out.writeByte(state.getType()); 190 state.writeTo(out); 191 } 192 193 private void readObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 194 in.defaultReadObject(); 195 byte type = in.readByte(); 196 this.state = getStateFactory().readManagedObjectStateFrom(in, type); 197 this.setBasicIsNew(false); 198 this.setBasicIsDirty(false); 199 } 200 201 public ManagedObjectState getManagedObjectState() { 202 return state; 203 } 204 205 208 public void toDNA(TCByteBufferOutputStream out, ObjectStringSerializer serializer) { 209 DNAWriterImpl writer = new ObjectDNAWriterImpl(out, id, getClassname(), serializer, DNA_STORAGE_ENCODING, 210 getLoaderDescription(), version); 211 state.dehydrate(id, writer); 212 writer.finalizeDNA(); 213 } 214 215 public String toString() { 216 StringWriter writer = new StringWriter (); 218 PrintWriter pWriter = new PrintWriter (writer); 219 new PrettyPrinter(pWriter).visit(this); 220 return writer.getBuffer().toString(); 221 } 222 223 public PrettyPrinter prettyPrint(PrettyPrinter out) { 224 PrettyPrinter rv = out; 225 out = out.print("ManagedObjectImpl").duplicateAndIndent().println(); 226 out.indent().print("identityHashCode: " + System.identityHashCode(this)).println(); 227 out.indent().print("id: " + id).println(); 228 out.indent().print("className: " + getClassname()).println(); 229 out.indent().print("version:" + version).println(); 230 out.indent().print("state: ").visit(state).println(); 231 out.indent().print("isDirty:" + this.basicIsDirty()); 232 out.indent().print("isNew:" + this.basicIsNew()); 233 out.indent().print("isReferenced:" + this.isReferenced()).println(); 234 out.indent().print("next: " + (this.getNext() != null) + " prev: " + (this.getPrevious() != null)); 235 return rv; 236 } 237 238 public ManagedObjectFacade createFacade(int limit) { 239 return state.createFacade(id, getClassname(), limit); 240 } 241 242 245 public String getClassname() { 246 return state == null ? "UNKNOWN" : state.getClassName(); 247 } 248 249 public String getLoaderDescription() { 250 return state == null ? "UNKNOWN" : state.getLoaderDescription(); 251 } 252 253 public ManagedObjectReference getReference() { 254 return this; 255 } 256 257 260 public ManagedObject getObject() { 261 return this; 262 } 263 264 public boolean getProcessPendingOnRelease() { 265 return getFlag(PROCESS_PENDING_OFFSET); 266 } 267 268 public void setProcessPendingOnRelease(boolean b) { 269 setFlag(PROCESS_PENDING_OFFSET, b); 270 } 271 272 public boolean isRemoveOnRelease() { 273 return getFlag(REMOVE_ON_RELEASE_OFFSET); 274 } 275 276 public void markReference() { 277 setFlag(REFERENCED_OFFSET, true); 278 } 279 280 public void unmarkReference() { 281 setFlag(REFERENCED_OFFSET, false); 282 } 283 284 public boolean isReferenced() { 285 return getFlag(REFERENCED_OFFSET); 286 } 287 288 291 public void pin() { 292 setFlag(PINNED_OFFSET, true); 293 } 294 295 public void unpin() { 296 setFlag(PINNED_OFFSET, false); 297 } 298 299 303 public boolean isPinned() { 304 return getFlag(PINNED_OFFSET); 305 } 306 307 312 313 public void setRemoveOnRelease(boolean removeOnRelease) { 314 setFlag(REMOVE_ON_RELEASE_OFFSET, removeOnRelease); 315 } 316 317 public void markAccessed() { 318 accessed++; 319 } 320 321 public void clearAccessed() { 322 accessed = 0; 323 } 324 325 public boolean recentlyAccessed() { 326 return accessed > 0; 327 } 328 329 public int accessCount(int factor) { 330 accessed = accessed / factor; 331 return accessed; 332 } 333 334 public ObjectID getObjectID() { 335 return getID(); 336 } 337 338 public TLinkable getNext() { 339 return next; 340 } 341 342 public TLinkable getPrevious() { 343 return previous; 344 } 345 346 public void setNext(TLinkable next) { 347 this.next = next; 348 } 349 350 public void setPrevious(TLinkable previous) { 351 this.previous = previous; 352 } 353 354 public synchronized boolean canEvict() { 355 return !(isPinned() || isReferenced() || isNew()); 356 } 357 358 } 359 | Popular Tags |