001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.objectserver.managedobject;
006:
007: import com.tc.object.ObjectID;
008: import com.tc.object.SerializationUtil;
009: import com.tc.object.dna.api.DNACursor;
010: import com.tc.object.dna.api.DNAWriter;
011: import com.tc.object.dna.api.LiteralAction;
012: import com.tc.object.dna.api.LogicalAction;
013: import com.tc.object.dna.api.PhysicalAction;
014:
015: import java.io.IOException;
016: import java.io.ObjectInput;
017: import java.io.ObjectOutput;
018: import java.util.Arrays;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.Map;
022: import java.util.Set;
023: import java.util.Map.Entry;
024:
025: /**
026: * state for maps
027: */
028: public class ConcurrentHashMapManagedObjectState extends
029: MapManagedObjectState {
030: private static final String SEGMENT_MASK_FIELD_NAME = "java.util.concurrent.ConcurrentHashMap.segmentMask";
031: private static final String SEGMENT_SHIFT_FIELD_NAME = "java.util.concurrent.ConcurrentHashMap.segmentShift";
032: private static final String SEGMENT_FIELD_NAME = "java.util.concurrent.ConcurrentHashMap.segments";
033:
034: private Object segmentMask;
035: private Object segmentShift;
036: private ObjectID[] segments = null;
037:
038: protected ConcurrentHashMapManagedObjectState(long classID) {
039: super (classID, new HashMap());
040: }
041:
042: protected ConcurrentHashMapManagedObjectState(ObjectInput in)
043: throws IOException {
044: super (in);
045: }
046:
047: protected ConcurrentHashMapManagedObjectState(long classID, Map map) {
048: super (classID, map);
049: }
050:
051: public void apply(ObjectID objectID, DNACursor cursor,
052: BackReferences includeIDs) throws IOException {
053: int segmentIndex = 0;
054: while (cursor.next()) {
055: Object action = cursor.getAction();
056: if (action instanceof LogicalAction) {
057: LogicalAction logicalAction = (LogicalAction) action;
058: int method = logicalAction.getMethod();
059: Object[] params = logicalAction.getParameters();
060: applyMethod(objectID, includeIDs, method, params);
061: } else if (action instanceof LiteralAction) {
062: LiteralAction literalAction = (LiteralAction) action;
063: segments = new ObjectID[((Integer) literalAction
064: .getObject()).intValue()];
065: } else if (action instanceof PhysicalAction) {
066: PhysicalAction physicalAction = (PhysicalAction) action;
067: boolean updateSegment = updateReference(objectID,
068: physicalAction.getFieldName(), physicalAction
069: .getObject(), segmentIndex, includeIDs);
070: if (updateSegment) {
071: segmentIndex++;
072: }
073: }
074: }
075: }
076:
077: private boolean updateReference(ObjectID objectID,
078: String fieldName, Object value, int segmentIndex,
079: BackReferences includeIDs) {
080: if (SEGMENT_MASK_FIELD_NAME.equals(fieldName)) {
081: segmentMask = value;
082: return false;
083: } else if (SEGMENT_SHIFT_FIELD_NAME.equals(fieldName)) {
084: segmentShift = value;
085: return false;
086: } else if ((SEGMENT_FIELD_NAME + segmentIndex)
087: .equals(fieldName)) {
088: segments[segmentIndex] = (ObjectID) value;
089: getListener().changed(objectID, null,
090: segments[segmentIndex]);
091: includeIDs.addBackReference(segments[segmentIndex],
092: objectID);
093: return true;
094: } else {
095: return false;
096: }
097: }
098:
099: protected void addAllObjectReferencesTo(Set refs) {
100: super .addAllObjectReferencesTo(refs);
101: if (segments != null) {
102: for (int i = 0; i < segments.length; i++) {
103: refs.add(segments[i]);
104: }
105: }
106: }
107:
108: public void dehydrate(ObjectID objectID, DNAWriter writer) {
109: dehydrateFields(objectID, writer);
110: dehydrateMapKeyValuesPair(objectID, writer);
111: }
112:
113: private void dehydrateMapKeyValuesPair(ObjectID objectID,
114: DNAWriter writer) {
115: for (Iterator i = references.entrySet().iterator(); i.hasNext();) {
116: Entry entry = (Entry) i.next();
117: Object key = entry.getKey();
118: Object value = entry.getValue();
119: writer.addLogicalAction(SerializationUtil.PUT,
120: new Object[] { key, value });
121: }
122: }
123:
124: private void dehydrateFields(ObjectID objectID, DNAWriter writer) {
125: writer.addPhysicalAction(SEGMENT_MASK_FIELD_NAME, segmentMask);
126: writer
127: .addPhysicalAction(SEGMENT_SHIFT_FIELD_NAME,
128: segmentShift);
129:
130: writer.addLiteralValue(new Integer(segments.length));
131: for (int i = 0; i < segments.length; i++) {
132: ObjectID segment = segments[i];
133: writer.addPhysicalAction(SEGMENT_FIELD_NAME + i, segment);
134: }
135: }
136:
137: private void writeField(ObjectOutput out, String fieldName,
138: Object fieldValue) throws IOException {
139: out.writeUTF(fieldName);
140: if (fieldValue == null) {
141: out.writeBoolean(false);
142: } else {
143: out.writeBoolean(true);
144: if (fieldValue instanceof ObjectID) {
145: out.writeLong(((ObjectID) fieldValue).toLong());
146: } else {
147: out.writeObject(fieldValue);
148: }
149: }
150: }
151:
152: protected void basicWriteTo(ObjectOutput out) throws IOException {
153: writeField(out, SEGMENT_MASK_FIELD_NAME, segmentMask);
154: writeField(out, SEGMENT_SHIFT_FIELD_NAME, segmentShift);
155: if (segments == null) {
156: out.writeBoolean(false);
157: } else {
158: out.writeBoolean(true);
159: out.writeInt(segments.length);
160: for (int i = 0; i < segments.length; i++) {
161: writeField(out, SEGMENT_FIELD_NAME + i, segments[i]);
162: }
163: }
164: out.writeInt(references.size());
165: for (Iterator i = references.entrySet().iterator(); i.hasNext();) {
166: Entry entry = (Entry) i.next();
167: out.writeObject(entry.getKey());
168: out.writeObject(entry.getValue());
169: }
170: }
171:
172: private static void readField(ObjectInput in,
173: ConcurrentHashMapManagedObjectState mo, int index)
174: throws ClassNotFoundException, IOException {
175: String fieldName = in.readUTF();
176: boolean fieldExist = in.readBoolean();
177: if (fieldExist) {
178: if (fieldName.equals(SEGMENT_MASK_FIELD_NAME)) {
179: mo.segmentMask = in.readObject();
180: } else if (fieldName.equals(SEGMENT_SHIFT_FIELD_NAME)) {
181: mo.segmentShift = in.readObject();
182: } else if (fieldName.equals((SEGMENT_FIELD_NAME + index))) {
183: mo.segments[index] = new ObjectID(in.readLong());
184: } else {
185: throw new AssertionError(
186: "Field not recognized in ConcurrentHashMapManagedObjectState.readFrom().");
187: }
188: }
189: }
190:
191: static MapManagedObjectState readFrom(ObjectInput in)
192: throws IOException, ClassNotFoundException {
193: ConcurrentHashMapManagedObjectState mo = new ConcurrentHashMapManagedObjectState(
194: in);
195: readField(in, mo, -1);
196: readField(in, mo, -1);
197:
198: boolean segmentExist = in.readBoolean();
199: if (segmentExist) {
200: int segmentLength = in.readInt();
201: mo.segments = new ObjectID[segmentLength];
202: for (int i = 0; i < segmentLength; i++) {
203: readField(in, mo, i);
204: }
205: }
206:
207: int size = in.readInt();
208: Map map = new HashMap(size);
209: for (int i = 0; i < size; i++) {
210: map.put(in.readObject(), in.readObject());
211: }
212: mo.references = map;
213: return mo;
214: }
215:
216: public byte getType() {
217: return CONCURRENT_HASHMAP_TYPE;
218: }
219:
220: protected boolean basicEquals(LogicalManagedObjectState o) {
221: ConcurrentHashMapManagedObjectState mo = (ConcurrentHashMapManagedObjectState) o;
222:
223: return ((segmentMask == mo.segmentMask) || (segmentMask != null && segmentMask
224: .equals(mo.segmentMask)))
225: && ((segmentShift == mo.segmentShift) || (segmentShift != null && segmentShift
226: .equals(mo.segmentShift)))
227: && ((segments == mo.segments) || (segments != null && Arrays
228: .equals(segments, mo.segments)))
229: && references.equals(mo.references);
230: }
231: }
|