28 import java.io.ByteArrayOutputStream; |
28 import java.io.ByteArrayOutputStream; |
29 import java.io.File; |
29 import java.io.File; |
30 import java.io.FileOutputStream; |
30 import java.io.FileOutputStream; |
31 import java.io.IOException; |
31 import java.io.IOException; |
32 import java.io.InputStream; |
32 import java.io.InputStream; |
|
33 import java.io.ObjectInputStream; |
33 import java.io.OutputStream; |
34 import java.io.OutputStream; |
34 import java.io.PrintStream; |
35 import java.io.PrintStream; |
35 import java.io.PrintWriter; |
36 import java.io.PrintWriter; |
36 import java.io.Serializable; |
37 import java.io.Serializable; |
37 import java.lang.Process; |
38 import java.lang.Process; |
96 import java.util.Map; |
97 import java.util.Map; |
97 import java.util.MissingResourceException; |
98 import java.util.MissingResourceException; |
98 import java.util.Properties; |
99 import java.util.Properties; |
99 import java.util.ResourceBundle; |
100 import java.util.ResourceBundle; |
100 import java.util.Set; |
101 import java.util.Set; |
|
102 import java.util.concurrent.ConcurrentHashMap; |
101 import sun.rmi.log.LogHandler; |
103 import sun.rmi.log.LogHandler; |
102 import sun.rmi.log.ReliableLog; |
104 import sun.rmi.log.ReliableLog; |
103 import sun.rmi.registry.RegistryImpl; |
105 import sun.rmi.registry.RegistryImpl; |
104 import sun.rmi.runtime.NewThreadAction; |
106 import sun.rmi.runtime.NewThreadAction; |
105 import sun.rmi.server.UnicastServerRef; |
107 import sun.rmi.server.UnicastServerRef; |
145 private static Method execPolicyMethod; |
147 private static Method execPolicyMethod; |
146 private static boolean debugExec; |
148 private static boolean debugExec; |
147 |
149 |
148 /** maps activation id to its respective group id */ |
150 /** maps activation id to its respective group id */ |
149 private Map<ActivationID,ActivationGroupID> idTable = |
151 private Map<ActivationID,ActivationGroupID> idTable = |
150 new HashMap<ActivationID,ActivationGroupID>(); |
152 new ConcurrentHashMap<>(); |
151 /** maps group id to its GroupEntry groups */ |
153 /** maps group id to its GroupEntry groups */ |
152 private Map<ActivationGroupID,GroupEntry> groupTable = |
154 private Map<ActivationGroupID,GroupEntry> groupTable = |
153 new HashMap<ActivationGroupID,GroupEntry>(); |
155 new ConcurrentHashMap<>(); |
154 |
156 |
155 private byte majorVersion = MAJOR_VERSION; |
157 private byte majorVersion = MAJOR_VERSION; |
156 private byte minorVersion = MINOR_VERSION; |
158 private byte minorVersion = MINOR_VERSION; |
157 |
159 |
158 /** number of simultaneous group exec's */ |
160 /** number of simultaneous group exec's */ |
234 numUpdates = 0; |
236 numUpdates = 0; |
235 shutdownHook = new ShutdownHook(); |
237 shutdownHook = new ShutdownHook(); |
236 groupSemaphore = getInt("sun.rmi.activation.groupThrottle", 3); |
238 groupSemaphore = getInt("sun.rmi.activation.groupThrottle", 3); |
237 groupCounter = 0; |
239 groupCounter = 0; |
238 Runtime.getRuntime().addShutdownHook(shutdownHook); |
240 Runtime.getRuntime().addShutdownHook(shutdownHook); |
|
241 |
|
242 // Use array size of 0, since the value from calling size() |
|
243 // may be out of date by the time toArray() is called. |
239 ActivationGroupID[] gids = |
244 ActivationGroupID[] gids = |
240 groupTable.keySet().toArray( |
245 groupTable.keySet().toArray(new ActivationGroupID[0]); |
241 new ActivationGroupID[groupTable.size()]); |
|
242 |
246 |
243 synchronized (startupLock = new Object()) { |
247 synchronized (startupLock = new Object()) { |
244 // all the remote methods briefly synchronize on startupLock |
248 // all the remote methods briefly synchronize on startupLock |
245 // (via checkShutdown) to make sure they don't happen in the |
249 // (via checkShutdown) to make sure they don't happen in the |
246 // middle of this block. This block must not cause any such |
250 // middle of this block. This block must not cause any such |
272 e.printStackTrace(); |
276 e.printStackTrace(); |
273 } |
277 } |
274 } |
278 } |
275 } |
279 } |
276 |
280 |
|
281 /** |
|
282 * Previous versions used HashMap instead of ConcurrentHashMap. |
|
283 * Replace any HashMaps found during deserialization with |
|
284 * ConcurrentHashMaps. |
|
285 */ |
|
286 private void readObject(ObjectInputStream ois) |
|
287 throws IOException, ClassNotFoundException |
|
288 { |
|
289 ois.defaultReadObject(); |
|
290 if (! (groupTable instanceof ConcurrentHashMap)) { |
|
291 groupTable = new ConcurrentHashMap<>(groupTable); |
|
292 } |
|
293 if (! (idTable instanceof ConcurrentHashMap)) { |
|
294 idTable = new ConcurrentHashMap<>(idTable); |
|
295 } |
|
296 } |
|
297 |
277 private static class SystemRegistryImpl extends RegistryImpl { |
298 private static class SystemRegistryImpl extends RegistryImpl { |
278 |
299 |
279 private static final String NAME = ActivationSystem.class.getName(); |
300 private static final String NAME = ActivationSystem.class.getName(); |
280 private final ActivationSystem systemStub; |
301 private final ActivationSystem systemStub; |
281 |
302 |
486 checkArgs(desc, null); |
507 checkArgs(desc, null); |
487 |
508 |
488 ActivationGroupID id = new ActivationGroupID(systemStub); |
509 ActivationGroupID id = new ActivationGroupID(systemStub); |
489 GroupEntry entry = new GroupEntry(id, desc); |
510 GroupEntry entry = new GroupEntry(id, desc); |
490 // table insertion must take place before log update |
511 // table insertion must take place before log update |
491 synchronized (groupTable) { |
512 groupTable.put(id, entry); |
492 groupTable.put(id, entry); |
|
493 } |
|
494 addLogRecord(new LogRegisterGroup(id, desc)); |
513 addLogRecord(new LogRegisterGroup(id, desc)); |
495 return id; |
514 return id; |
496 } |
515 } |
497 |
516 |
498 public ActivationMonitor activeGroup(ActivationGroupID id, |
517 public ActivationMonitor activeGroup(ActivationGroupID id, |
513 checkShutdown(); |
532 checkShutdown(); |
514 RegistryImpl.checkAccess("ActivationSystem.unregisterGroup"); |
533 RegistryImpl.checkAccess("ActivationSystem.unregisterGroup"); |
515 |
534 |
516 // remove entry before unregister so state is updated before |
535 // remove entry before unregister so state is updated before |
517 // logged |
536 // logged |
518 synchronized (groupTable) { |
537 removeGroupEntry(id).unregisterGroup(true); |
519 GroupEntry entry = getGroupEntry(id); |
|
520 groupTable.remove(id); |
|
521 entry.unregisterGroup(true); |
|
522 } |
|
523 } |
538 } |
524 |
539 |
525 public ActivationDesc setActivationDesc(ActivationID id, |
540 public ActivationDesc setActivationDesc(ActivationID id, |
526 ActivationDesc desc) |
541 ActivationDesc desc) |
527 throws ActivationException, UnknownObjectException, RemoteException |
542 throws ActivationException, UnknownObjectException, RemoteException |
635 */ |
650 */ |
636 unexport(activator); |
651 unexport(activator); |
637 unexport(system); |
652 unexport(system); |
638 |
653 |
639 // destroy all child processes (groups) |
654 // destroy all child processes (groups) |
640 GroupEntry[] groupEntries; |
655 for (GroupEntry groupEntry : groupTable.values()) { |
641 synchronized (groupTable) { |
|
642 groupEntries = groupTable.values(). |
|
643 toArray(new GroupEntry[groupTable.size()]); |
|
644 } |
|
645 for (GroupEntry groupEntry : groupEntries) { |
|
646 groupEntry.shutdown(); |
656 groupEntry.shutdown(); |
647 } |
657 } |
648 |
658 |
649 Runtime.getRuntime().removeShutdownHook(shutdownHook); |
659 Runtime.getRuntime().removeShutdownHook(shutdownHook); |
650 |
660 |
706 * Throws UnknownObjectException if the object is not registered. |
714 * Throws UnknownObjectException if the object is not registered. |
707 */ |
715 */ |
708 private ActivationGroupID getGroupID(ActivationID id) |
716 private ActivationGroupID getGroupID(ActivationID id) |
709 throws UnknownObjectException |
717 throws UnknownObjectException |
710 { |
718 { |
711 synchronized (idTable) { |
719 ActivationGroupID groupID = idTable.get(id); |
712 ActivationGroupID groupID = idTable.get(id); |
720 if (groupID != null) { |
713 if (groupID != null) { |
721 return groupID; |
714 return groupID; |
|
715 } |
|
716 } |
722 } |
717 throw new UnknownObjectException("unknown object: " + id); |
723 throw new UnknownObjectException("unknown object: " + id); |
|
724 } |
|
725 |
|
726 /** |
|
727 * Returns the group entry for the group id, optionally removing it. |
|
728 * Throws UnknownGroupException if the group is not registered. |
|
729 */ |
|
730 private GroupEntry getGroupEntry(ActivationGroupID id, boolean rm) |
|
731 throws UnknownGroupException |
|
732 { |
|
733 if (id.getClass() == ActivationGroupID.class) { |
|
734 GroupEntry entry; |
|
735 if (rm) { |
|
736 entry = groupTable.remove(id); |
|
737 } else { |
|
738 entry = groupTable.get(id); |
|
739 } |
|
740 if (entry != null && !entry.removed) { |
|
741 return entry; |
|
742 } |
|
743 } |
|
744 throw new UnknownGroupException("group unknown"); |
718 } |
745 } |
719 |
746 |
720 /** |
747 /** |
721 * Returns the group entry for the group id. Throws |
748 * Returns the group entry for the group id. Throws |
722 * UnknownGroupException if the group is not registered. |
749 * UnknownGroupException if the group is not registered. |
723 */ |
750 */ |
724 private GroupEntry getGroupEntry(ActivationGroupID id) |
751 private GroupEntry getGroupEntry(ActivationGroupID id) |
725 throws UnknownGroupException |
752 throws UnknownGroupException |
726 { |
753 { |
727 if (id.getClass() == ActivationGroupID.class) { |
754 return getGroupEntry(id, false); |
728 synchronized (groupTable) { |
755 } |
729 GroupEntry entry = groupTable.get(id); |
756 |
730 if (entry != null && !entry.removed) { |
757 /** |
731 return entry; |
758 * Removes and returns the group entry for the group id. Throws |
732 } |
759 * UnknownGroupException if the group is not registered. |
733 } |
760 */ |
734 } |
761 private GroupEntry removeGroupEntry(ActivationGroupID id) |
735 throw new UnknownGroupException("group unknown"); |
762 throws UnknownGroupException |
|
763 { |
|
764 return getGroupEntry(id, true); |
736 } |
765 } |
737 |
766 |
738 /** |
767 /** |
739 * Returns the group entry for the object's id. Throws |
768 * Returns the group entry for the object's id. Throws |
740 * UnknownObjectException if the object is not registered or the |
769 * UnknownObjectException if the object is not registered or the |
742 */ |
771 */ |
743 private GroupEntry getGroupEntry(ActivationID id) |
772 private GroupEntry getGroupEntry(ActivationID id) |
744 throws UnknownObjectException |
773 throws UnknownObjectException |
745 { |
774 { |
746 ActivationGroupID gid = getGroupID(id); |
775 ActivationGroupID gid = getGroupID(id); |
747 synchronized (groupTable) { |
776 GroupEntry entry = groupTable.get(gid); |
748 GroupEntry entry = groupTable.get(gid); |
777 if (entry != null && !entry.removed) { |
749 if (entry != null) { |
778 return entry; |
750 return entry; |
|
751 } |
|
752 } |
779 } |
753 throw new UnknownObjectException("object's group removed"); |
780 throw new UnknownObjectException("object's group removed"); |
754 } |
781 } |
755 |
782 |
756 /** |
783 /** |
880 if (desc.getRestartMode() == true) { |
907 if (desc.getRestartMode() == true) { |
881 restartSet.add(id); |
908 restartSet.add(id); |
882 } |
909 } |
883 |
910 |
884 // table insertion must take place before log update |
911 // table insertion must take place before log update |
885 synchronized (idTable) { |
912 idTable.put(id, groupID); |
886 idTable.put(id, groupID); |
|
887 } |
|
888 |
913 |
889 if (addRecord) { |
914 if (addRecord) { |
890 addLogRecord(new LogRegisterObject(id, desc)); |
915 addLogRecord(new LogRegisterObject(id, desc)); |
891 } |
916 } |
892 } |
917 } |