1 4 package com.tc.object.applicator; 5 6 import com.tc.exception.TCRuntimeException; 7 import com.tc.object.ClientObjectManager; 8 import com.tc.object.ObjectID; 9 import com.tc.object.TCObject; 10 import com.tc.object.TraversedReferences; 11 import com.tc.object.bytecode.ByteCodeUtil; 12 import com.tc.object.bytecode.Manageable; 13 import com.tc.object.dna.api.DNA; 14 import com.tc.object.dna.api.DNACursor; 15 import com.tc.object.dna.api.DNAWriter; 16 import com.tc.object.dna.api.LiteralAction; 17 import com.tc.object.dna.api.LogicalAction; 18 import com.tc.object.dna.api.PhysicalAction; 19 import com.tc.object.dna.impl.DNAEncoding; 20 import com.tc.object.tx.optimistic.OptimisticTransactionManager; 21 import com.tc.object.tx.optimistic.TCObjectClone; 22 import com.tc.util.Assert; 23 import com.tc.util.FieldUtils; 24 25 import java.io.IOException ; 26 import java.lang.reflect.Array ; 27 import java.lang.reflect.Field ; 28 import java.lang.reflect.InvocationTargetException ; 29 import java.lang.reflect.Method ; 30 import java.util.IdentityHashMap ; 31 import java.util.Iterator ; 32 import java.util.Map ; 33 import java.util.Map.Entry; 34 import java.util.concurrent.ConcurrentHashMap ; 35 36 39 public class ConcurrentHashMapApplicator extends HashMapApplicator { 40 private static final String CONCURRENT_HASH_MAP_FIELD_NAME_PREFIX = ConcurrentHashMap .class.getName() + "."; 41 private static final String SEGMENT_MASK_FIELD_NAME = "segmentMask"; 42 private static final String SEGMENT_SHIFT_FIELD_NAME = "segmentShift"; 43 private static final String SEGMENT_FIELD_NAME = "segments"; 44 private static final String TC_PUT_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX + "put"; 45 46 private static final Field SEGMENT_MASK_FIELD; 47 private static final Field SEGMENT_SHIFT_FIELD; 48 private static final Field SEGMENT_FIELD; 49 private static final Method TC_PUT_METHOD; 50 51 static { 52 try { 53 SEGMENT_MASK_FIELD = ConcurrentHashMap .class.getDeclaredField(SEGMENT_MASK_FIELD_NAME); 54 SEGMENT_MASK_FIELD.setAccessible(true); 55 56 SEGMENT_SHIFT_FIELD = ConcurrentHashMap .class.getDeclaredField(SEGMENT_SHIFT_FIELD_NAME); 57 SEGMENT_SHIFT_FIELD.setAccessible(true); 58 59 SEGMENT_FIELD = ConcurrentHashMap .class.getDeclaredField(SEGMENT_FIELD_NAME); 60 SEGMENT_FIELD.setAccessible(true); 61 62 TC_PUT_METHOD = ConcurrentHashMap .class.getDeclaredMethod(TC_PUT_METHOD_NAME, new Class [] { Object .class, 63 Object .class }); 64 TC_PUT_METHOD.setAccessible(true); 65 } catch (Exception e) { 66 throw new RuntimeException (e); 67 } 68 } 69 70 public ConcurrentHashMapApplicator(DNAEncoding encoding) { 71 super(encoding); 72 } 73 74 public TraversedReferences getPortableObjects(Object pojo, TraversedReferences addTo) { 75 super.getPortableObjects(pojo, addTo); 76 getPhysicalPortableObjects(pojo, addTo); 77 return addTo; 78 } 79 80 public void getPhysicalPortableObjects(Object pojo, TraversedReferences addTo) { 81 try { 82 filterPortableObject(SEGMENT_MASK_FIELD.get(pojo), addTo); 83 filterPortableObject(SEGMENT_SHIFT_FIELD.get(pojo), addTo); 84 Object [] segments = (Object [])SEGMENT_FIELD.get(pojo); 85 for (int i=0; i<segments.length; i++) { 86 filterPortableObject(segments[i], addTo); 87 } 88 } catch (IllegalAccessException e) { 89 throw new TCRuntimeException(e); 90 } 91 } 92 93 private void filterPortableObject(Object value, TraversedReferences addTo) { 94 if (value != null && isPortableReference(value.getClass())) { 95 addTo.addAnonymousReference(value); 96 } 97 } 98 99 public void hydrate(ClientObjectManager objectManager, TCObject tcObject, DNA dna, Object po) throws IOException , 100 ClassNotFoundException { 101 int segmentLength = -1; 102 Object segment = null; 103 Object [] segments = null; 104 int segmentIndex = 0; 105 DNACursor cursor = dna.getCursor(); 106 107 while (cursor.next(encoding)) { 108 Object action = cursor.getAction(); 109 if (action instanceof LogicalAction) { 110 if (segmentLength != -1) { 111 setSegmentField(segments, po, segmentLength, segmentIndex); 112 segmentLength = -1; 113 } 114 115 LogicalAction logicalAction = cursor.getLogicalAction(); 116 int method = logicalAction.getMethod(); 117 Object [] params = logicalAction.getParameters(); 118 apply(objectManager, po, method, params); 119 } else if (action instanceof LiteralAction) { 120 LiteralAction literalAction = (LiteralAction) action; 121 segmentLength = ((Integer ) literalAction.getObject()).intValue(); 122 } else if (action instanceof PhysicalAction) { 123 Assert.assertFalse(dna.isDelta()); 126 PhysicalAction physicalAction = cursor.getPhysicalAction(); 127 128 Assert.eval(physicalAction.isTruePhysical()); 129 String fieldName = physicalAction.getFieldName(); 130 Object value = physicalAction.getObject(); 131 try { 132 if (fieldName.equals(CONCURRENT_HASH_MAP_FIELD_NAME_PREFIX + SEGMENT_MASK_FIELD_NAME)) { 133 FieldUtils.tcSet(po, value, SEGMENT_MASK_FIELD); 134 } else if (fieldName.equals(CONCURRENT_HASH_MAP_FIELD_NAME_PREFIX + SEGMENT_SHIFT_FIELD_NAME)) { 135 FieldUtils.tcSet(po, value, SEGMENT_SHIFT_FIELD); 136 } else if (fieldName.equals(CONCURRENT_HASH_MAP_FIELD_NAME_PREFIX + SEGMENT_FIELD_NAME + segmentIndex)) { 137 segment = objectManager.lookupObject((ObjectID) value); 138 if (segments == null) { 139 segments = (Object []) Array.newInstance(segment.getClass(), segmentLength); 140 } 141 segments[segmentIndex] = segment; 142 segmentIndex++; 143 } 144 } catch (IllegalAccessException e) { 145 throw new TCRuntimeException(e); 146 } 147 } 148 } 149 setSegmentField(segments, po, segmentLength, segmentIndex); 150 } 151 152 private void setSegmentField(Object [] segments, Object po, int segmentLength, int segmentIndex) { 153 if (segmentLength != -1) { 154 Assert.assertEquals(segmentLength, segmentIndex); 155 try { 156 FieldUtils.tcSet(po, segments, SEGMENT_FIELD); 157 } catch (IllegalAccessException e) { 158 throw new TCRuntimeException(e); 159 } 160 } 161 } 162 163 public void dehydrate(ClientObjectManager objectManager, TCObject tcObject, DNAWriter writer, Object pojo) { 164 dehydrateFields(objectManager, tcObject, writer, pojo); 165 super.dehydrate(objectManager, tcObject, writer, pojo); 166 } 167 168 private void dehydrateFields(ClientObjectManager objectManager, TCObject tcObject, DNAWriter writer, Object pojo) { 169 try { 170 Object segmentMask = SEGMENT_MASK_FIELD.get(pojo); 171 segmentMask = getDehydratableObject(segmentMask, objectManager); 172 writer.addPhysicalAction(CONCURRENT_HASH_MAP_FIELD_NAME_PREFIX + SEGMENT_MASK_FIELD_NAME, segmentMask); 173 174 Object segmentShift = SEGMENT_SHIFT_FIELD.get(pojo); 175 segmentShift = getDehydratableObject(segmentShift, objectManager); 176 writer.addPhysicalAction(CONCURRENT_HASH_MAP_FIELD_NAME_PREFIX + SEGMENT_SHIFT_FIELD_NAME, segmentShift); 177 178 Object [] segments = (Object []) SEGMENT_FIELD.get(pojo); 179 writer.addLiteralValue(new Integer (segments.length)); 180 for (int i = 0; i < segments.length; i++) { 181 Object segment = segments[i]; 182 segment = getDehydratableObject(segment, objectManager); 183 writer.addPhysicalAction(CONCURRENT_HASH_MAP_FIELD_NAME_PREFIX + SEGMENT_FIELD_NAME + i, segment); 184 } 185 } catch (IllegalAccessException e) { 186 throw new TCRuntimeException(e); 187 } 188 } 189 190 public Map connectedCopy(Object source, Object dest, Map visited, ClientObjectManager objectManager, 191 OptimisticTransactionManager txManager) { 192 Map cloned = new IdentityHashMap (); 193 194 Manageable sourceManageable = (Manageable) source; 195 Manageable destManaged = (Manageable) dest; 196 197 Map sourceMap = (Map ) source; 198 Map destMap = (Map ) dest; 199 200 for (Iterator i = sourceMap.entrySet().iterator(); i.hasNext();) { 201 Entry e = (Entry) i.next(); 202 203 Object copyKey = createCopyIfNecessary(objectManager, visited, cloned, e.getKey()); 204 Object copyValue = createCopyIfNecessary(objectManager, visited, cloned, e.getValue()); 205 try { 206 TC_PUT_METHOD.invoke(destMap, new Object [] { copyKey, copyValue }); 207 } catch (IllegalArgumentException e1) { 208 throw new TCRuntimeException(e1); 209 } catch (IllegalAccessException e1) { 210 throw new TCRuntimeException(e1); 211 } catch (InvocationTargetException e1) { 212 throw new TCRuntimeException(e1); 213 } 214 } 215 216 destManaged.__tc_managed(new TCObjectClone(sourceManageable.__tc_managed(), txManager)); 217 return cloned; 218 } 219 } 220 | Popular Tags |