javax.management.Notification Java Examples
The following examples show how to use
javax.management.Notification.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: GarbageCollectorImpl.java From jdk8u-jdk with GNU General Public License v2.0 | 6 votes |
void createGCNotification(long timestamp, String gcName, String gcAction, String gcCause, GcInfo gcInfo) { if (!hasListeners()) { return; } Notification notif = new Notification(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION, getObjectName(), getNextSeqNumber(), timestamp, gcName); GarbageCollectionNotificationInfo info = new GarbageCollectionNotificationInfo(gcName, gcAction, gcCause, gcInfo); CompositeData cd = GarbageCollectionNotifInfoCompositeData.toCompositeData(info); notif.setUserData(cd); sendNotification(notif); }
Example #2
Source File: Basic.java From openjdk-jdk8u with GNU General Public License v2.0 | 6 votes |
public MBeanNotificationInfo[] getNotificationInfo() { if (notifDescriptorAtt == null) { initNotifDescriptorAtt(); } return new MBeanNotificationInfo[]{ new MBeanNotificationInfo(new String[]{ NOTIF_TYPE_0 }, javax.management.Notification.class.getName(), "Standard JMX Notification", notifDescriptorAtt), new MBeanNotificationInfo(new String[]{ NOTIF_TYPE_1 }, SqeNotification.class.getName(), "SQE Notification", notifDescriptorAtt) }; }
Example #3
Source File: LegacyExample.java From cacheonix-core with GNU Lesser General Public License v2.1 | 6 votes |
public static void main(String[] args) throws Exception { // Create the service LegacyService legacyService = new LegacyService(); // Create the JMX MBeanServer and register the service wrapper MBeanServer server = MBeanServerFactory.newMBeanServer(); ObjectName serviceName = new ObjectName("examples", "mbean", "legacy"); DynamicLegacyService dynamicService = new DynamicLegacyService(legacyService); server.registerMBean(dynamicService, serviceName); // Now register a listener: we want to be able to know when the service starts and stops server.addNotificationListener(serviceName, new NotificationListener() { public void handleNotification(Notification notification, Object handback) { System.out.println(notification); } }, null, null); // Now start the service, using the new method name: 'start' instead of 'execute' server.invoke(serviceName, "start", null, null); }
Example #4
Source File: SimpleListener.java From dragonwell8_jdk with GNU General Public License v2.0 | 6 votes |
public synchronized void handleNotification(Notification notification, Object handback) { Utils.debug(Utils.DEBUG_STANDARD, "SimpleListener::handleNotification :" + notification); try { received = true; type = notification.getType(); this.handback = handback; handbacks.add(handback); nbrec++; notify(); } catch(Exception e) { System.out.println("(ERROR) SimpleListener::handleNotification :" + " Caught exception " + e) ; } }
Example #5
Source File: DirectoryScanner.java From jdk8u-dev-jdk with GNU General Public License v2.0 | 6 votes |
private boolean notifyMatch(File file) { try { final Notification n = new Notification(FILE_MATCHES_NOTIFICATION,this, getNextSeqNumber(), file.getAbsolutePath()); // This method *is not* called from any synchronized block, so // we can happily call broadcaster.sendNotification() here. // Note that verifying whether a method is called from within // a synchronized block demends a thoroughful code reading, // examining each of the 'parent' methods in turn. // broadcaster.sendNotification(n); return true; } catch (Exception x) { LOG.fine("Failed to notify: "+file.getAbsolutePath()); } return false; }
Example #6
Source File: ResultLogManager.java From jdk8u-jdk with GNU General Public License v2.0 | 6 votes |
/** * This MBean emits three kind of notifications: * <pre> * <i>com.sun.jmx.examples.scandir.log.file.switched</i> * <i>com.sun.jmx.examples.scandir.log.memory.full</i> * <i>com.sun.jmx.examples.scandir.log.memory.cleared</i> * </pre> **/ public MBeanNotificationInfo[] getNotificationInfo() { return new MBeanNotificationInfo[] { new MBeanNotificationInfo(new String[] { LOG_FILE_CHANGED}, Notification.class.getName(), "Emitted when the log file is switched") , new MBeanNotificationInfo(new String[] { MEMORY_LOG_MAX_CAPACITY}, Notification.class.getName(), "Emitted when the memory log capacity is reached") , new MBeanNotificationInfo(new String[] { MEMORY_LOG_CLEARED}, Notification.class.getName(), "Emitted when the memory log is cleared") }; }
Example #7
Source File: FederatingManager.java From gemfirexd-oss with Apache License 2.0 | 6 votes |
private DistributedMember removeMemberArtifacts(DistributedMember member, boolean crashed) { Region<String, Object> proxyRegion = repo.getEntryFromMonitoringRegionMap(member); Region<NotificationKey, Notification> notifRegion = repo.getEntryFromNotifRegionMap(member); if (proxyRegion == null && notifRegion == null) { return member; } repo.romoveEntryFromMonitoringRegionMap(member); repo.removeEntryFromNotifRegionMap(member); // If cache is closed all the regions would have been // destroyed implicitly if (!cache.isClosed()) { proxyFactory.removeAllProxies(member, proxyRegion); proxyRegion.localDestroyRegion(); notifRegion.localDestroyRegion(); } if (!cache.getDistributedSystem().getDistributedMember().equals(member)) { service.memberDeparted((InternalDistributedMember) member, crashed); } return member; }
Example #8
Source File: DefaultMBeanServerInterceptor.java From TencentKona-8 with GNU General Public License v2.0 | 6 votes |
public void handleNotification(Notification notification, Object handback) { if (notification != null) { if (notification.getSource() == mbean) notification.setSource(name); } /* * Listeners are not supposed to throw exceptions. If * this one does, we could remove it from the MBean. It * might indicate that a connector has stopped working, * for instance, and there is no point in sending future * notifications over that connection. However, this * seems rather drastic, so instead we propagate the * exception and let the broadcaster handle it. */ listener.handleNotification(notification, handback); }
Example #9
Source File: NotificationAccessControllerTest.java From openjdk-8 with GNU General Public License v2.0 | 6 votes |
public void fetchNotification( String connectionId, ObjectName name, Notification notification, Subject subject) throws SecurityException { echo("fetchNotification:"); echo("\tconnectionId: " + connectionId); echo("\tname: " + name); echo("\tnotification: " + notification); echo("\tsubject: " + (subject == null ? null : subject.getPrincipals())); if (!throwException) if (name.getCanonicalName().equals("domain:name=2,type=NB") && subject.getPrincipals().contains(new JMXPrincipal("role"))) throw new SecurityException(); }
Example #10
Source File: StartTest.java From openjdk-jdk8u-backup with GNU General Public License v2.0 | 6 votes |
public void handleNotification(Notification n, Object hb) { if (!stopping) { received++; System.out.println( ">>> myListener-handleNotification: received " + n.getSequenceNumber()); } }
Example #11
Source File: DirectoryScanner.java From dragonwell8_jdk with GNU General Public License v2.0 | 6 votes |
private boolean notifyMatch(File file) { try { final Notification n = new Notification(FILE_MATCHES_NOTIFICATION,this, getNextSeqNumber(), file.getAbsolutePath()); // This method *is not* called from any synchronized block, so // we can happily call broadcaster.sendNotification() here. // Note that verifying whether a method is called from within // a synchronized block demends a thoroughful code reading, // examining each of the 'parent' methods in turn. // broadcaster.sendNotification(n); return true; } catch (Exception x) { LOG.fine("Failed to notify: "+file.getAbsolutePath()); } return false; }
Example #12
Source File: TestSlowQueryReport.java From Tomcat8-Source-Read with MIT License | 6 votes |
@Override public void handleNotification(Notification notification, Object handback) { notificationCount.incrementAndGet(); System.out.println("\nReceived notification:"); System.out.println("\tClassName: " + notification.getClass().getName()); System.out.println("\tSource: " + notification.getSource()); System.out.println("\tType: " + notification.getType()); System.out.println("\tMessage: " + notification.getMessage()); if (notification instanceof AttributeChangeNotification) { AttributeChangeNotification acn = (AttributeChangeNotification) notification; System.out.println("\tAttributeName: " + acn.getAttributeName()); System.out.println("\tAttributeType: " + acn.getAttributeType()); System.out.println("\tNewValue: " + acn.getNewValue()); System.out.println("\tOldValue: " + acn.getOldValue()); } }
Example #13
Source File: TestJPPFNodeForwardingMBean2.java From JPPF with Apache License 2.0 | 6 votes |
/** * Check that the received notifications are the epxected ones. * Here we expect that: * <ul> * <li>the number of tasks is a multiple of the total number of nodes</li> * <li>the tasks are evenly spread among the nodes</li> * </ul> * @param notifs the notifications that were received. * @param nbTasks the total number of takss that were executed. * @param expectedNodes the nodes from which notifications should have been received. * @throws Exception if any error occurs. */ private static void checkNotifs(final List<Notification> notifs, final int nbTasks, final String...expectedNodes) throws Exception { assertNotNull(expectedNodes); assertTrue(expectedNodes.length > 0); final Set<String> expectedNodesSet = CollectionUtils.set(expectedNodes); assertNotNull(notifs); final int nbNotifsPerNode = nbTasks / allNodes.size(); assertEquals(expectedNodes.length * nbNotifsPerNode, notifs.size()); final Map<String, AtomicInteger> notifCounts = new HashMap<>(); for (final String uuid: expectedNodes) notifCounts.put(uuid, new AtomicInteger(0)); for (final Notification notification: notifs) { assertTrue(notification instanceof JPPFNodeForwardingNotification); final JPPFNodeForwardingNotification outerNotif = (JPPFNodeForwardingNotification) notification; assertEquals(NodeTestMBean.MBEAN_NAME, outerNotif.getMBeanName()); final Notification notif = outerNotif.getNotification(); assertTrue(notif.getUserData() instanceof UserObject); final UserObject userObject = (UserObject) notif.getUserData(); assertNotNull(userObject.nodeUuid); assertTrue(expectedNodesSet.contains(userObject.nodeUuid)); assertEquals(outerNotif.getNodeUuid(), userObject.nodeUuid); notifCounts.get(userObject.nodeUuid).incrementAndGet(); } for (final Map.Entry<String, AtomicInteger> entry: notifCounts.entrySet()) { assertEquals(nbNotifsPerNode, entry.getValue().get()); } }
Example #14
Source File: ConnectionPool.java From Tomcat8-Source-Read with MIT License | 6 votes |
public static MBeanNotificationInfo[] getDefaultNotificationInfo() { String[] types = new String[] {NOTIFY_INIT, NOTIFY_CONNECT, NOTIFY_ABANDON, SLOW_QUERY_NOTIFICATION, FAILED_QUERY_NOTIFICATION, SUSPECT_ABANDONED_NOTIFICATION, POOL_EMPTY, SUSPECT_RETURNED_NOTIFICATION}; String name = Notification.class.getName(); String description = "A connection pool error condition was met."; MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description); return new MBeanNotificationInfo[] {info}; }
Example #15
Source File: ModelControllerMBeanTestCase.java From wildfly-core with GNU Lesser General Public License v2.1 | 6 votes |
private void doTestMBeanServerNotification_UNREGISTRATION_NOTIFICATION(MBeanServerConnection connection, boolean mustReceiveNotification) throws Exception { final ObjectName testObjectName = createObjectName(LEGACY_DOMAIN + ":subsystem=test"); final ObjectName childObjectName = createObjectName(LEGACY_DOMAIN + ":subsystem=test,single=only"); final CountDownLatch notificationEmitted = new CountDownLatch(1); final AtomicReference<Notification> notification = new AtomicReference<>(); NotificationListener listener = new MbeanServerNotificationListener(notification, notificationEmitted, LEGACY_DOMAIN); NotificationFilterSupport filter = new NotificationFilterSupport(); filter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION); connection.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, listener, filter, null); // add a management resource connection.invoke(testObjectName, "addSingleOnly", new Object[]{123}, new String[]{String.class.getName()}); // and remove it connection.invoke(childObjectName, "remove", new Object[0], new String[0]); if (mustReceiveNotification) { Assert.assertTrue("Did not receive expected notification", notificationEmitted.await(1, TimeUnit.SECONDS)); Notification notif = notification.get(); Assert.assertNotNull(notif); Assert.assertTrue(notif instanceof MBeanServerNotification); MBeanServerNotification mBeanServerNotification = (MBeanServerNotification) notif; Assert.assertEquals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION, mBeanServerNotification.getType()); Assert.assertEquals(childObjectName, mBeanServerNotification.getMBeanName()); } else { Assert.assertFalse("Did receive unexpected notification", notificationEmitted.await(500, TimeUnit.MILLISECONDS)); } connection.removeNotificationListener(MBeanServerDelegate.DELEGATE_NAME, listener, filter, null); }
Example #16
Source File: Basic.java From openjdk-jdk9 with GNU General Public License v2.0 | 6 votes |
public MBeanNotificationInfo[] getNotificationInfo() { if (notifDescriptorAtt == null) { initNotifDescriptorAtt(); } return new MBeanNotificationInfo[]{ new MBeanNotificationInfo(new String[]{ NOTIF_TYPE_0 }, javax.management.Notification.class.getName(), "Standard JMX Notification", notifDescriptorAtt), new MBeanNotificationInfo(new String[]{ NOTIF_TYPE_1 }, SqeNotification.class.getName(), "SQE Notification", notifDescriptorAtt) }; }
Example #17
Source File: ReflectionExceptionTest.java From dragonwell8_jdk with GNU General Public License v2.0 | 6 votes |
public void handleNotification(Notification notification, Object handback) { echo(">>> Received notification: " + notification); if (notification instanceof MonitorNotification) { String type = notification.getType(); if (type.equals(MonitorNotification.RUNTIME_ERROR)) { MonitorNotification mn = (MonitorNotification) notification; echo("\tType: " + mn.getType()); echo("\tTimeStamp: " + mn.getTimeStamp()); echo("\tObservedObject: " + mn.getObservedObject()); echo("\tObservedAttribute: " + mn.getObservedAttribute()); echo("\tDerivedGauge: " + mn.getDerivedGauge()); echo("\tTrigger: " + mn.getTrigger()); synchronized (this) { messageReceived = true; notifyAll(); } } } }
Example #18
Source File: ModelMBeanNotificationPublisherTests.java From java-technology-stack with MIT License | 5 votes |
public void testSendAttributeChangeNotificationWhereSourceIsNotTheManagedResource() throws Exception { StubSpringModelMBean mbean = new StubSpringModelMBean(); Notification notification = new AttributeChangeNotification(this, 1872, System.currentTimeMillis(), "Shall we break for some tea?", "agree", "java.lang.Boolean", Boolean.FALSE, Boolean.TRUE); ObjectName objectName = createObjectName(); NotificationPublisher publisher = new ModelMBeanNotificationPublisher(mbean, objectName, mbean); publisher.sendNotification(notification); assertNotNull(mbean.getActualNotification()); assertTrue(mbean.getActualNotification() instanceof AttributeChangeNotification); assertSame("The exact same Notification is not being passed through from the publisher to the mbean.", notification, mbean.getActualNotification()); assertSame("The 'source' property of the Notification is *wrongly* being set to the ObjectName of the associated MBean.", this, mbean.getActualNotification().getSource()); }
Example #19
Source File: NotificationBufferTest.java From openjdk-8 with GNU General Public License v2.0 | 5 votes |
private static NotificationBufferFilter makeFilter(final Integer id, final ObjectName pattern, final NotificationFilter filter) { return new NotificationBufferFilter() { public void apply(List<TargetedNotification> notifs, ObjectName source, Notification notif) { if (pattern.apply(source)) { if (filter == null || filter.isNotificationEnabled(notif)) notifs.add(new TargetedNotification(notif, id)); } } }; }
Example #20
Source File: RMIConnector.java From TencentKona-8 with GNU General Public License v2.0 | 5 votes |
protected void doStart() throws IOException { // Get RMIServer stub from directory or URL encoding if needed. RMIServer stub; try { stub = (rmiServer!=null)?rmiServer: findRMIServer(jmxServiceURL, env); } catch (NamingException ne) { throw new IOException("Failed to get a RMI stub: "+ne); } // Connect IIOP Stub if needed. stub = connectStub(stub,env); // Calling newClient on the RMIServer stub. Object credentials = env.get(CREDENTIALS); connection = stub.newClient(credentials); // notif issues final ClientListenerInfo[] old = rmiNotifClient.preReconnection(); reconnectNotificationListeners(old); connectionId = getConnectionId(); Notification reconnectedNotif = new JMXConnectionNotification(JMXConnectionNotification.OPENED, this, connectionId, clientNotifSeqNo++, "Reconnected to server", null); sendNotification(reconnectedNotif); }
Example #21
Source File: StatisticsExposingMBean.java From freehealth-connector with GNU Affero General Public License v3.0 | 5 votes |
protected MBeanInfo createMBeanInfoFromTagNames(Collection<String> tagNames) { MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[tagNames.size() * this.getStatsValueRetrievers().size()]; int i = 0; Iterator i$ = tagNames.iterator(); while(i$.hasNext()) { String tagName = (String)i$.next(); String statName; StatsValueRetriever statsValueRetriever; for(Iterator i$ = this.getStatsValueRetrievers().entrySet().iterator(); i$.hasNext(); attributes[i++] = new MBeanAttributeInfo(tagName + statName, statsValueRetriever.getValueClass().getName(), "Returns " + statName + " for tag " + tagName, true, false, false)) { Entry<String, StatsValueRetriever> statNameAndValueRetriever = (Entry)i$.next(); statName = (String)statNameAndValueRetriever.getKey(); statsValueRetriever = (StatsValueRetriever)statNameAndValueRetriever.getValue(); } } MBeanOperationInfo[] operations = new MBeanOperationInfo[]{new MBeanOperationInfo("exposeTag", "Allows the caller to add a monitored tag at runtime", new MBeanParameterInfo[]{new MBeanParameterInfo("tagName", String.class.getName(), "The name of the tag to expose")}, "void", 1), new MBeanOperationInfo("removeTag", "Allows the caller to remove a monitored tag at runtime", new MBeanParameterInfo[]{new MBeanParameterInfo("tagName", String.class.getName(), "The name of the tag to remove")}, "boolean", 1)}; MBeanNotificationInfo[] notificationInfos; if (this.acceptableRanges.isEmpty()) { notificationInfos = new MBeanNotificationInfo[0]; } else { notificationInfos = new MBeanNotificationInfo[]{new MBeanNotificationInfo(new String[]{"org.perf4j.threshold.exceeded"}, Notification.class.getName(), "Notification sent if any statistics move outside of the specified acceptable ranges")}; } return new MBeanInfo(this.getClass().getName(), "Timing Statistics", attributes, (MBeanConstructorInfo[])null, operations, notificationInfos); }
Example #22
Source File: ResultLogManager.java From openjdk-8 with GNU General Public License v2.0 | 5 votes |
/** * Check whether a new log file should be created. * If a new file needs to be created, creates it, renaming * previously existing file by appending '~' to its name. * Also reset the log count and file capacity. * Sends a notification indicating that the log file was changed. * Returns the new log stream; * Creation of a new file can be forced by passing force=true. **/ private OutputStream checkLogFile(String basename, long maxRecords, boolean force) throws IOException { final OutputStream newStream; synchronized(this) { if ((force==false) && (logCount < maxRecords)) return logStream; final OutputStream oldStream = logStream; // First close the stream. On some platforms you cannot rename // a file that has open streams... // if (oldStream != null) { oldStream.flush(); oldStream.close(); } final File newFile = (basename==null)?null:createNewLogFile(basename); newStream = (newFile==null)?null:new FileOutputStream(newFile,true); logStream = newStream; logFile = newFile; fileCapacity = maxRecords; logCount = 0; } sendNotification(new Notification(LOG_FILE_CHANGED,objectName, getNextSeqNumber(), basename)); return newStream; }
Example #23
Source File: UnexpectedNotifTest.java From jdk8u-dev-jdk with GNU General Public License v2.0 | 5 votes |
public void handleNotification(Notification notif, Object handback) { System.out.println("Received: " + notif + " (" + notif.getSequenceNumber() + ")"); synchronized(lock) { if(++receivedNotifs == nb) { lock.notifyAll(); } else if (receivedNotifs > nb) { System.out.println("The client expected to receive " + nb + " notifs, but got at least " + receivedNotifs); System.exit(1); } } }
Example #24
Source File: MissingClassTest.java From jdk8u-dev-jdk with GNU General Public License v2.0 | 5 votes |
public void handleNotification(Notification n, Object o) { if (n instanceof JMXConnectionNotification) { JMXConnectionNotification jn = (JMXConnectionNotification)n; if (JMXConnectionNotification.FAILED.equals(jn.getType())) { failed = true; } } }
Example #25
Source File: HeapMemoryMonitor.java From gemfirexd-oss with Apache License 2.0 | 5 votes |
@Override public void handleNotification(final Notification notification, final Object callback) { this.resourceManager.runWithNotifyExecutor(new Runnable() { @SuppressWarnings("synthetic-access") @Override public void run() { // Not using the information given by the notification in favor // of constructing fresh information ourselves. if (!testDisableMemoryUpdates) { updateStateAndSendEvent(); } } }); }
Example #26
Source File: UnexpectedNotifTest.java From TencentKona-8 with GNU General Public License v2.0 | 5 votes |
public void handleNotification(Notification notif, Object handback) { System.out.println("Received: " + notif + " (" + notif.getSequenceNumber() + ")"); synchronized(lock) { if(++receivedNotifs == nb) { lock.notifyAll(); } else if (receivedNotifs > nb) { System.out.println("The client expected to receive " + nb + " notifs, but got at least " + receivedNotifs); System.exit(1); } } }
Example #27
Source File: SystemMemberJmxImpl.java From gemfirexd-oss with Apache License 2.0 | 5 votes |
/** * Implementation handles creation of cache by extracting the details from the * given event object and sending the * {@link SystemMemberJmx#NOTIF_CACHE_CREATED} notification to the connected * JMX Clients. * * @param event * event object corresponding to the creation of the cache */ public void handleCacheCreate(SystemMemberCacheEvent event) { LogWriterI18n logWriterI18n = this.getDistributedSystem().getLogWriter().convertToLogWriterI18n(); Helper.sendNotification(logWriterI18n, this, new Notification(NOTIF_CACHE_CREATED, this.modelMBean, Helper.getNextNotificationSequenceNumber(), Helper.getCacheEventDetails(event))); }
Example #28
Source File: UnexpectedNotifTest.java From openjdk-8-source with GNU General Public License v2.0 | 5 votes |
public void handleNotification(Notification notif, Object handback) { System.out.println("Received: " + notif + " (" + notif.getSequenceNumber() + ")"); synchronized(lock) { if(++receivedNotifs == nb) { lock.notifyAll(); } else if (receivedNotifs > nb) { System.out.println("The client expected to receive " + nb + " notifs, but got at least " + receivedNotifs); System.exit(1); } } }
Example #29
Source File: CustomBean1.java From gemfirexd-oss with Apache License 2.0 | 5 votes |
public void sendNotificationToMe(String name) { long sequence = sequenceNumber++; Notification n = new AttributeChangeNotification(this, sequenceNumber, System.currentTimeMillis(), name, "A", "long", sequence, sequenceNumber); n.setSource(RemoteTestModule.getMyVmid()); sendNotification(n); }
Example #30
Source File: ServerNotifForwarder.java From TencentKona-8 with GNU General Public License v2.0 | 5 votes |
public void apply(List<TargetedNotification> targetedNotifs, ObjectName source, Notification notif) { // We proceed in two stages here, to avoid holding the listenerMap // lock while invoking the filters (which are user code). final IdAndFilter[] candidates; synchronized (listenerMap) { final Set<IdAndFilter> set = listenerMap.get(source); if (set == null) { logger.debug("bufferFilter", "no listeners for this name"); return; } candidates = new IdAndFilter[set.size()]; set.toArray(candidates); } // We don't synchronize on targetedNotifs, because it is a local // variable of our caller and no other thread can see it. for (IdAndFilter idaf : candidates) { final NotificationFilter nf = idaf.getFilter(); if (nf == null || nf.isNotificationEnabled(notif)) { logger.debug("bufferFilter", "filter matches"); final TargetedNotification tn = new TargetedNotification(notif, idaf.getId()); if (allowNotificationEmission(source, tn)) targetedNotifs.add(tn); } } }