001// 002// Name 003// $RCSfile: ManagedObject.java,v $ 004// 005// Copyright 006// Copyright 2007-2012 Cloud Software Group, Inc. ALL RIGHTS RESERVED. 007// Cloud Software Group, Inc. Confidential Information 008// 009// History 010// $Revision: 1.1.2.22 $ $Date: 2012/04/10 20:26:55 $ 011// 012 013package com.kabira.platform; 014 015import java.util.*; 016import com.kabira.platform.annotation.*; 017import java.util.concurrent.ConcurrentMap; 018 019/** 020 * Class to manipulate and find shared memory backed objects. 021 * To create a Java object that persists in shared memory, see the 022 * <code>@Managed</code> annotation. 023 * <p> 024 * Example: 025 *<pre>@Managed 026public class Account { 027 public Account(String userName) { 028 super(); 029 m_userName = userName; 030 } 031 032 public Account(String userName, Account referrer) { 033 this(userName); 034 allocateMailbox(); 035 addToFriendList(referrer); 036 } 037 038 public void addToFriendList(Account friendlyAccount) { 039 ... 040 } 041 042 private void allocateMailbox() { 043 ... 044 } 045 046 private String m_userName; 047 private Account[] m_friendList; 048}</pre> 049 * Some example usage of the above type: 050 <pre> 051 // 052 // create a new account in shared memory: 053 // 054 Account newCustomer = new Account("Fred Rogers", referrer); 055 System.out.println("Added " + newCustomer.toString()); 056 057 // 058 // delete all expired accounts from shared memory. 059 // Note extent access, and use of the delete() method 060 // to delete the shared memory instance. 061 // 062 for (Account acc : ManagedObject.extent(Account.class)) { 063 if (acc.expireDate < today) { 064 ManagedObject.delete(acc); 065 } 066 } 067 </pre> 068 * 069 * @see com.kabira.platform.annotation.Managed 070 * @see com.kabira.platform.Transaction 071 */ 072@Managed 073public abstract class ManagedObject 074{ 075 /** 076 * Returns all shared memory instances of a Managed type. 077 * <p> 078 * The <code>klass</code> parameter must be a <code>Managed</code> 079 * class, and is used to determine the extent to return. 080 * A Managed class is either annotated <code>@Managed</code>, or 081 * extends a class that is so annotated. 082 * <p> 083 * Consider the following example. It returns all instances of 084 * <code>MyType</code> (including instances of its subtypes) 085 * with no locks held on the objects: 086 <pre> 087 // 088 // Iterate instances of MyType.class, returning all objects in the extent 089 // 090 for (MyType instance : ManagedObject.extent(MyType.class)) { 091 assert ( Transaction.hasReadLock(instance) == false ); 092 assert ( Transaction.hasWriteLock(instance) == false ); 093 ... 094 }</pre> 095 * @param klass extent class - instances of this type, 096 * and any subtypes that extend from this type, will be returned in 097 * the extent. 098 * @exception ManagedClassError Thrown if <code>klass</code> 099 * is not Managed (or exactly ManagedObject). 100 * @return <code>Iterable</code> that will traverse all instances 101 * located in shared memory. 102 * @see com.kabira.platform.annotation.Managed 103 * @see com.kabira.platform.ManagedClassError 104 */ 105 public static <T> java.lang.Iterable<T> extent( 106 final java.lang.Class<T> klass) 107 throws ManagedClassError 108 { 109 return ManagedObject.extent(klass, LockMode.NOLOCK); 110 } 111 112 /** 113 * Returns all shared memory instances of a Managed type, 114 * with an explicit transaction lock taken on each instance 115 * as it is iterated. 116 *<p> 117 * The <code>klass</code> parameter must be a Managed class, 118 * and is used to determine the extent to return. 119 *<p> 120 * The <code>objectLock</code> parameter is used to specify the 121 * transaction lock to take on objects returned during extent 122 * iteration. The objects are locked as they are returned from the 123 * <code>java.util.Iterator<T></code>, not when this method 124 * returns. 125 * <p> 126 * Consider the following example. It returns all instances of 127 * <code>MyType</code> (including instances of its subtypes) 128 * with a READLOCK held on each instance: 129 <pre> 130 // 131 // Iterate the ManagedObjectSet taking read locks on the objects 132 // 133 for (MyType mt : ManagedObject.extent( MyType.class, LockMode.READLOCK)) { 134 assert ( Transaction.hasReadLock(mt) == true ); 135 ... 136 }</pre> 137 * @param klass extent class - instances of this type, 138 * and any subtypes that extend from this type, will be returned 139 * in the extent. 140 * @param objectLock object lock - all object instances 141 * returned during extent iteration will have this transaction lock. 142 * @exception ManagedClassError Thrown if <code>klass</code> 143 * is not marked Managed, or is exactly ManagedObject. 144 * @return <code>Iterable<klass></code> containing references to 145 * all instances located in shared memory. 146 * @see com.kabira.platform.annotation.Managed 147 */ 148 public static <T> java.lang.Iterable<T> extent( 149 final java.lang.Class<T> klass, 150 final LockMode objectLock) 151 throws ManagedClassError 152 { 153 checkManagedClass(klass, "extent"); 154 155 if (klass.equals(ManagedObject.class)) 156 { 157 throw new ManagedClassError( 158 "extent class cannot be " 159 + ManagedObject.class.getName() + "."); 160 } 161 162 return new Extent<T>(klass.getName(), objectLock); 163 } 164 165 /** Returns a hash code based on the 166 * underlying shared memory object. 167 */ 168 public static int hashCode(Object o) 169 { 170 return java.util.Arrays.hashCode( 171 ManagedObject.getObjectReference(o)); 172 } 173 174 /** Returns true if both references are proxies to the same 175 * shared memory object. 176 * 177 * @throws ManagedClassError if o1 or o2 is not Managed. 178 */ 179 public static boolean equals(Object o1, Object o2) 180 throws ManagedClassError 181 { 182 if (o1 == o2) 183 { 184 return true; 185 } 186 187 if ((o1 == null) || (o2 == null)) 188 { 189 return false; 190 } 191 192 checkManagedObject(o1, "equals"); 193 checkManagedObject(o2, "equals"); 194 195 // FIX THIS: can we reduce two JNI calls to one? 196 // FIX THIS: this is inefficient - getObjectReference is a 197 // JNI native, because $m_objectReference is added at class 198 // load time. This should be generated at class load time. 199 return java.util.Arrays.equals( 200 ManagedObject.getObjectReference(o1), 201 ManagedObject.getObjectReference(o2)); 202 } 203 204 /** Determines if the given object is an instance of a Managed class. 205 * Returns true only if the object, or a superclass, is marked 206 * @Managed. 207 */ 208 public static boolean isManaged(Object o) 209 { 210 return isManagedClass(o.getClass()); 211 } 212 213 /** Determines if the given class is Managed. 214 * Returns true only if the class, or a superclass, is marked 215 * @Managed. 216 */ 217 @SuppressWarnings("deprecation") 218 public static boolean isManagedClass(Class<?> klass) 219 { 220 return (klass.isAnnotationPresent(Managed.class) 221 || klass.isAnnotationPresent(Distributed.class)); 222 } 223 224 /** If the given object is not Managed, throw a new ManagedClassError. 225 */ 226 private static void checkManagedObject(Object o, String methodName) 227 throws ManagedClassError 228 { 229 checkManagedClass(o.getClass(), methodName); 230 } 231 232 /** If the given class is not Managed, throw a new ManagedClassError. 233 */ 234 private static void checkManagedClass(Class klass, String methodName) 235 throws ManagedClassError 236 { 237 if (isManagedClass(klass) == false) 238 { 239 throw new ManagedClassError("Method " 240 + methodName + "() can only be applied to " 241 + "Managed classes."); 242 } 243 } 244 245 /** Return the object reference as a byte array. Package-private. 246 * This may return a reference to the actual field, so the result 247 * should be treated as read-only. 248 * FIX THIS: inefficient to use a native for this. 249 */ 250 static native byte[] getObjectReference(Object o); 251 252 /** Deletes a Managed object. 253 * @throws ManagedClassError if operand is not Managed. 254 */ 255 public static void delete(Object operand) 256 throws ManagedClassError 257 { 258 checkManagedObject(operand, "delete"); 259 _deleteSM(operand); 260 } 261 262 /** Returns the number of instances of the given class. 263 *<br> 264 * This count does not require transaction locks on the 265 * extent or any of the individual objects in the extent. 266 *<br> 267 * This means the number returned by cardinality() may 268 * change even as observed within a single transaction. 269 * @throws ManagedClassError if klass is not Managed. 270 */ 271 public static int cardinality(Class<?> operand) 272 throws ManagedClassError 273 { 274 checkManagedClass(operand, "cardinality"); 275 return ManagedObject._cardinality(operand.getName()); 276 } 277 278 /** Determines if the backing shared memory object has been deleted. 279 * @throws ManagedClassError if the operand object is not of a Managed 280 * class. 281 * @return true if the operand has been deleted, false otherwise. 282 */ 283 public static boolean isEmpty(Object operand) 284 throws ManagedClassError 285 { 286 if (operand == null) 287 { 288 return true; 289 } 290 checkManagedObject(operand, "isEmpty"); 291 return _isEmpty(operand); 292 } 293 294 /** 295 * Commit and abort triggers must be enabled in each transaction. 296 * This method enables triggers for all methods in TransactionTriggers 297 * (currently abort and commit). 298 */ 299 static void enableTriggers(TransactionTriggers obj) 300 { 301 enableTriggers(ManagedObject.getObjectReference(obj)); 302 } 303 native static void enableTriggers(byte[] objectReference); 304 305 /** Determines if the passed in object reference is local 306 * or distributed. 307 * @returns true if the passed in reference is local 308 */ 309 private native static boolean isLocal(byte[] objectReference); 310 311 private native static boolean isLocalToJVM(byte[] objectReference); 312 313 private native static boolean _isEmpty(Object operand); 314 315 /** Creates the shared memory object. 316 * 317 * This method does not create shared memory for a JBA keyed type; 318 * the generated JBA constructor should do that instead. 319 * This method returns the object reference as a byte array. If the 320 * type was not created, a "refNULL" is returned - a byte array 321 * of the appropriate size, with contents zero'ed out. 322 */ 323 private static native byte[] createSMObject(String className); 324 325 /** 326 * Invoke post-create triggers. 327 * Does not create or update keys. 328 */ 329 private static native void postCreateTrigger(byte[] objRef); 330 331 /** 332 * Invoke all post-create work in the runtime. 333 */ 334 private static native void completeSMObject( 335 byte[] objRef, 336 boolean callTriggers); 337 338 /** 339 * An exception is being thrown from this constructor; 340 * destroy the (partially-created) shared memory object. 341 */ 342 private static native void cancelSMObject(byte[] objRef); 343 344 /** 345 * Set the context class loader for this thread to this classes class 346 * loader. 347 * NOTE this assumes the context class loader is not set. This should 348 * only be called when attaching a Thread via JNI AttachCurrentThread. 349 */ 350 private static void setContextClassLoader() 351 { 352 // 353 // FIX THIS: The IBM JVM asserts on this, commented out for now. 354 // 355 // assert(Thread.currentThread().getContextClassLoader() == null); 356 // 357 assert(ManagedObject.class.getClassLoader() != null); 358 359 Thread.currentThread().setContextClassLoader( 360 ManagedObject.class.getClassLoader()); 361 } 362 363 private static native void _deleteSM(Object operand); 364 365 private static native int _cardinality(String className); 366 367 // 368 // Dispatch operations 369 // 370 private native static Any sendTwoWay( 371 final Object object, 372 final int opDomainId, 373 final int opTypeId, 374 final AnyBuffer params); 375 private native static Any sendPinnedTwoWay( 376 final Object object, 377 final int opDomainId, 378 final int opTypeId, 379 final AnyBuffer params); 380 private native static void sendOneWay( 381 final Object object, 382 final int opDomainId, 383 final int opTypeId, 384 final AnyBuffer params); 385 386 // 387 // Method for Reflection support 388 // 389 static Object getObject(Object obj, String fieldName) 390 { 391 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 392 byte [] objRef = getObjectReference(obj); 393 394 int slotIndex = 0; 395 TypeDescriptor.FieldDescriptor slot = null; 396 397 for (TypeDescriptor.FieldDescriptor fd : td.m_fields) 398 { 399 if (fd.m_name.equals(fieldName)) 400 { 401 slot = fd; 402 break; 403 } 404 slotIndex++; 405 } 406 assert( slot != null ); 407 408 // 409 // We have to autobox the value based on the slot 410 // 411 switch (slot.m_typeId) 412 { 413 case TypeDescriptor.DSE_TYPEID_INT32: 414 return getIntegerRef(objRef, slotIndex); 415 case TypeDescriptor.DSE_TYPEID_INT64: 416 return getLongRef(objRef, slotIndex); 417 case TypeDescriptor.DSE_TYPEID_INT16: 418 return getShortRef(objRef, slotIndex); 419 case TypeDescriptor.DSE_TYPEID_WCHAR: 420 return getCharacterRef(objRef, slotIndex); 421 case TypeDescriptor.DSE_TYPEID_FLOAT: 422 return getFloatRef(objRef, slotIndex); 423 case TypeDescriptor.DSE_TYPEID_DOUBLE: 424 return getDoubleRef(objRef, slotIndex); 425 case TypeDescriptor.DSE_TYPEID_BOOLEAN: 426 return getBooleanRef(objRef, slotIndex); 427 case TypeDescriptor.DSE_TYPEID_CHAR: 428 case TypeDescriptor.DSE_TYPEID_OCTET: 429 return getByteRef(objRef, slotIndex); 430 } 431 432 // 433 // This handles String, Date and Managed objects 434 // 435 return getReference(objRef, slotIndex); 436 } 437 static void setObject(Object obj, String fieldName, Object v) 438 { 439 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 440 byte [] objRef = getObjectReference(obj); 441 int slotIndex = td.getSlotIndex(fieldName); 442 443 // 444 // We have to auto-unbox the instance and call the appropriate 445 // setter. 446 // 447 if (v instanceof Integer) 448 { 449 setInteger(((Integer)v).intValue(), objRef, slotIndex); 450 } 451 else if (v instanceof Long) 452 { 453 setLong(((Long)v).longValue(), objRef, slotIndex); 454 } 455 else if (v instanceof Short) 456 { 457 setShort(((Short)v).shortValue(), objRef, slotIndex); 458 } 459 else if (v instanceof Character) 460 { 461 setChar(((Character)v).charValue(), objRef, slotIndex); 462 } 463 else if (v instanceof Float) 464 { 465 setFloat(((Float)v).floatValue(), objRef, slotIndex); 466 } 467 else if (v instanceof Double) 468 { 469 setDouble(((Double)v).doubleValue(), objRef, slotIndex); 470 } 471 else if (v instanceof Boolean) 472 { 473 setBoolean(((Boolean)v).booleanValue(), objRef, slotIndex); 474 } 475 else if (v instanceof Byte) 476 { 477 setByte(((Byte)v).byteValue(), objRef, slotIndex); 478 } 479 else 480 { 481 // 482 // This handles String, Date and Managed objects 483 // 484 setReference(v, objRef, slotIndex); 485 } 486 } 487 static boolean getBoolean(Object obj, String fieldName) 488 { 489 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 490 Boolean b = getBooleanRef(getObjectReference(obj), 491 td.getSlotIndex(fieldName)); 492 return b.booleanValue(); 493 } 494 static void setBoolean(Object obj, String fieldName, boolean b) 495 { 496 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 497 setBoolean(b, getObjectReference(obj), td.getSlotIndex(fieldName)); 498 } 499 static byte getByte(Object obj, String fieldName) 500 { 501 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 502 Byte v = getByteRef(getObjectReference(obj), 503 td.getSlotIndex(fieldName)); 504 return v.byteValue(); 505 } 506 static void setByte(Object obj, String fieldName, byte b) 507 { 508 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 509 setByte(b, getObjectReference(obj), td.getSlotIndex(fieldName)); 510 } 511 static char getChar(Object obj, String fieldName) 512 { 513 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 514 Character v = getCharacterRef(getObjectReference(obj), 515 td.getSlotIndex(fieldName)); 516 return v.charValue(); 517 } 518 static void setChar(Object obj, String fieldName, char c) 519 { 520 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 521 setChar(c, getObjectReference(obj), td.getSlotIndex(fieldName)); 522 } 523 static double getDouble(Object obj, String fieldName) 524 { 525 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 526 return getDouble(getObjectReference(obj), td.getSlotIndex(fieldName)); 527 } 528 static void setDouble(Object obj, String fieldName, double d) 529 { 530 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 531 setDouble(d, getObjectReference(obj), td.getSlotIndex(fieldName)); 532 } 533 static float getFloat(Object obj, String fieldName) 534 { 535 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 536 return getFloat(getObjectReference(obj), td.getSlotIndex(fieldName)); 537 } 538 static void setFloat(Object obj, String fieldName, float f) 539 { 540 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 541 setFloat(f, getObjectReference(obj), td.getSlotIndex(fieldName)); 542 } 543 static int getInt(Object obj, String fieldName) 544 { 545 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 546 return getInteger(getObjectReference(obj), td.getSlotIndex(fieldName)); 547 } 548 static void setInt(Object obj, String fieldName, int i) 549 { 550 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 551 setInteger(i, getObjectReference(obj), td.getSlotIndex(fieldName)); 552 } 553 static long getLong(Object obj, String fieldName) 554 { 555 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 556 return getLong(getObjectReference(obj), td.getSlotIndex(fieldName)); 557 } 558 static void setLong(Object obj, String fieldName, long l) 559 { 560 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 561 setLong(l, getObjectReference(obj), td.getSlotIndex(fieldName)); 562 } 563 static short getShort(Object obj, String fieldName) 564 { 565 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 566 Short v = getShortRef(getObjectReference(obj), 567 td.getSlotIndex(fieldName)); 568 return v.shortValue(); 569 } 570 static void setShort(Object obj, String fieldName, short s) 571 { 572 TypeDescriptor td = TypeDescriptor.getDescriptor(obj); 573 setShort(s, getObjectReference(obj), td.getSlotIndex(fieldName)); 574 } 575 576 // 577 // field getters/setters: 578 // 579 private static native Boolean getBooleanRef( 580 byte[] objRef, 581 long slotNum); 582 private static native Byte getByteRef( 583 byte[] objRef, 584 long slotNum); 585 private static native Character getCharacterRef( 586 byte[] objRef, 587 long slotNum); 588 private static native Short getShortRef( 589 byte[] objRef, 590 long slotNum); 591 private static native int getInteger( 592 byte[] objRef, 593 long slotNum); 594 private static native Integer getIntegerRef( 595 byte[] objRef, 596 long slotNum); 597 private static native long getLong( 598 byte[] objRef, 599 long slotNum); 600 private static native Long getLongRef( 601 byte[] objRef, 602 long slotNum); 603 private static native float getFloat( 604 byte[] objRef, 605 long slotNum); 606 private static native Float getFloatRef( 607 byte[] objRef, 608 long slotNum); 609 private static native double getDouble( 610 byte[] objRef, 611 long slotNum); 612 private static native Double getDoubleRef( 613 byte[] objRef, 614 long slotNum); 615 private static native Object getReference( 616 byte[] objRef, 617 long slotNum); 618 private static Object getSerializable( 619 byte[] objRef, 620 long slotNum) 621 { 622 Any storedval = (Any)getReference(objRef, slotNum); 623 624 if (storedval == null) 625 { 626 return null; 627 } 628 629 return Any.deserializeAny(storedval); 630 } 631 632 private static native void setBoolean( 633 boolean val, 634 byte[] objRef, 635 long slotNum); 636 private static native void setBooleanRef( 637 Boolean val, 638 byte[] objRef, 639 long slotNum); 640 private static native void setByte( 641 byte val, 642 byte[] objRef, 643 long slotNum); 644 private static native void setByteRef( 645 Byte val, 646 byte[] objRef, 647 long slotNum); 648 private static native void setChar( 649 char val, 650 byte[] objRef, 651 long slotNum); 652 private static native void setCharacterRef( 653 Character val, 654 byte[] objRef, 655 long slotNum); 656 private static native void setShort( 657 short val, 658 byte[] objRef, 659 long slotNum); 660 private static native void setShortRef( 661 Short val, 662 byte[] objRef, 663 long slotNum); 664 private static native void setInteger( 665 int val, 666 byte[] objRef, 667 long slotNum); 668 private static native void setIntegerRef( 669 Integer val, 670 byte[] objRef, 671 long slotNum); 672 private static native void setLong( 673 long val, 674 byte[] objRef, 675 long slotNum); 676 private static native void setLongRef( 677 Long val, 678 byte[] objRef, 679 long slotNum); 680 private static native void setFloat( 681 float val, 682 byte[] objRef, 683 long slotNum); 684 private static native void setFloatRef( 685 Float val, 686 byte[] objRef, 687 long slotNum); 688 private static native void setDouble( 689 double val, 690 byte[] objRef, 691 long slotNum); 692 private static native void setDoubleRef( 693 Double val, 694 byte[] objRef, 695 long slotNum); 696 private static void setSerializable( 697 Object val, 698 byte[] objRef, 699 long slotNum) 700 { 701 if (val == null) 702 { 703 setReference(null, objRef, slotNum); 704 } 705 else 706 { 707 setReference(new Any(Any.serializeObject(val)), objRef, slotNum); 708 } 709 } 710 711 private static native void setReference( 712 Object val, 713 byte[] objRef, 714 long slotNum); 715 716 // 717 // array-length operator: 718 // 719 private static native int _getArrayLength( 720 byte[] objref, 721 long slotNum, 722 int[] coords); 723 724 // 725 // Basic-type array getters/setters: 726 // 727 private static native void _setByteArray( 728 byte[] objref, 729 long slotNum, 730 int[] coords, 731 int pos, 732 byte val); 733 private static native void _setCharArray( 734 byte[] objref, 735 long slotNum, 736 int[] coords, 737 int pos, 738 char val); 739 private static native void _setDoubleArray( 740 byte[] objref, 741 long slotNum, 742 int[] coords, 743 int pos, 744 double val); 745 private static native void _setFloatArray( 746 byte[] objref, 747 long slotNum, 748 int[] coords, 749 int pos, 750 float val); 751 private static native void _setIntArray( 752 byte[] objref, 753 long slotNum, 754 int[] coords, 755 int pos, 756 int val); 757 private static native void _setLongArray( 758 byte[] objref, 759 long slotNum, 760 int[] coords, 761 int pos, 762 long val); 763 private static native void _setShortArray( 764 byte[] objref, 765 long slotNum, 766 int[] coords, 767 int pos, 768 short val); 769 770 private static native byte _getByteArray( 771 byte[] objref, 772 long slotNum, 773 int[] coords, 774 int pos); 775 private static native char _getCharArray( 776 byte[] objref, 777 long slotNum, 778 int[] coords, 779 int pos); 780 private static native float _getFloatArray( 781 byte[] objref, 782 long slotNum, 783 int[] coords, 784 int pos); 785 private static native int _getIntArray( 786 byte[] objref, 787 long slotNum, 788 int[] coords, 789 int pos); 790 private static native long _getLongArray( 791 byte[] objref, 792 long slotNum, 793 int[] coords, 794 int pos); 795 private static native short _getShortArray( 796 byte[] objref, 797 long slotNum, 798 int[] coords, 799 int pos); 800 private static native double _getDoubleArray( 801 byte[] objref, 802 long slotNum, 803 int[] coords, 804 int pos); 805 806 private static java.lang.Object _getSerializableArray( 807 byte[] objref, 808 long slotNum, 809 int[] coords, 810 int pos) 811 { 812 Object obj = _getReferenceArray(objref, slotNum, coords, pos); 813 814 return Any.deserializeAny((Any)obj); 815 } 816 817 private static void _setSerializableArray( 818 byte[] objref, 819 long slotNum, 820 int[] coords, 821 int pos, 822 java.lang.Object val) 823 { 824 _setReferenceArray(objref, slotNum, coords, pos, new Any(Any.serializeObject(val))); 825 } 826 827 // 828 // Reference array getters/setters: 829 // 830 private static native java.lang.Object _getReferenceArray( 831 byte[] objref, 832 long slotNum, 833 int[] coords, 834 int pos); 835 private static native void _setReferenceArray( 836 byte[] objref, 837 long slotNum, 838 int[] coords, 839 int pos, 840 java.lang.Object val); 841 842 /** 843 * Used for field sets of @ByReference-annotated fields. This method 844 * is here in ManagedObject so we can keep it private - the classloader 845 * will modify the access flags. 846 */ 847 private static Object getByRefMap( 848 Object container, 849 ConcurrentMap<Object, Reference> map) 850 { 851 return Reference.getReference(map, container); 852 } 853 854 /** 855 * Used for field sets of @ByReference-annotated fields. This method 856 * is here in ManagedObject so we can keep it private - the classloader 857 * will modify the access flags. 858 */ 859 private static void setByRefMap( 860 Object container, 861 Object val, 862 ConcurrentMap<Object, Reference> map) 863 { 864 Reference.setReference(map, container, val); 865 } 866 867 /** 868 * Synthetic ByReference field maps are registered with the ReferenceManager 869 * so we can scan for orphaned Reference instances. 870 * This method is here so we can keep it marked private - the classloader 871 * will modify the access flags. 872 * Invoked by synthetic code added to static initializers. 873 */ 874 private static void registerFieldMap(ConcurrentMap<Object, Reference> fieldMap) 875 { 876 Reference.registerFieldMap(fieldMap); 877 } 878 879 /** Private class returned from extent() methods (needed to use the 880 * for-each loop). 881 */ 882 private static class Extent<T> 883 implements Iterable<T> 884 { 885 private String m_typeName; 886 private LockMode m_objectLockMode; 887 Extent(String typeName, LockMode objectLockMode) 888 { 889 m_typeName = typeName; 890 m_objectLockMode = objectLockMode; 891 } 892 893 public Iterator<T> iterator() 894 { 895 return new ExtentIterator<T>( 896 m_typeName, 897 m_objectLockMode); 898 } 899 } 900 901 /** Class wrapping readonly access to a Managed extent. 902 */ 903 private static class ExtentIterator<T extends Object> 904 implements java.util.Iterator<T> 905 { 906 private LockMode m_objectLockMode; 907 private long m_cHandle; 908 private T m_next; 909 910 ExtentIterator(String typeName, LockMode objectLock) 911 { 912 m_objectLockMode = objectLock; 913 m_cHandle = _new(typeName); 914 m_next = _next(m_cHandle); 915 } 916 917 protected void finalize() 918 { 919 if (m_cHandle != 0) 920 { 921 _delete(m_cHandle); 922 } 923 m_cHandle = 0; 924 } 925 926 public boolean hasNext() 927 { 928 return (m_next != null); 929 } 930 931 public T next() 932 { 933 T t = m_next; 934 935 m_next = _next(m_cHandle); 936 937 if (m_objectLockMode == LockMode.READLOCK) 938 { 939 Transaction.readLockObject(t); 940 } 941 else if (m_objectLockMode == LockMode.WRITELOCK) 942 { 943 Transaction.writeLockObject(t); 944 } 945 else 946 { 947 assert ( m_objectLockMode == LockMode.NOLOCK ); 948 } 949 950 return t; 951 } 952 953 public void remove() 954 { 955 throw new UnsupportedOperationException(); 956 } 957 958 native long _new(String typeName); 959 native T _next(long cHandle); 960 native void _delete(long cHandle); 961 } 962}