001/* 002 * This file is part of the Kompics component model runtime. 003 * <p> 004 * Copyright (C) 2009 Swedish Institute of Computer Science (SICS) 005 * Copyright (C) 2009 Royal Institute of Technology (KTH) 006 * <p> 007 * Kompics is free software; you can redistribute it and/or modify it under the 008 * terms of the GNU General Public License as published by the Free Software 009 * Foundation; either version 2 of the License, or (at your option) any later 010 * version. 011 * <p> 012 * This program is distributed in the hope that it will be useful, but WITHOUT 013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 014 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 015 * details. 016 * <p> 017 * You should have received a copy of the GNU General Public License along with 018 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 019 * Place - Suite 330, Boston, MA 02111-1307, USA. 020 */ 021package se.sics.kompics; 022 023import java.util.Optional; 024import java.lang.reflect.Constructor; 025import java.lang.reflect.InvocationTargetException; 026import java.util.HashMap; 027import java.util.HashSet; 028import java.util.Map; 029import java.util.Objects; 030import java.util.Set; 031import org.slf4j.Logger; 032import org.slf4j.MDC; 033import se.sics.kompics.Fault.ResolveAction; 034import se.sics.kompics.HandlerStore.HandlerList; 035import se.sics.kompics.HandlerStore.MatchedHandlerList; 036import se.sics.kompics.config.Config; 037import se.sics.kompics.config.ConfigUpdate; 038import se.sics.kompics.config.ValueMerger; 039 040/** 041 * The <code>ComponentCore</code> class. 042 * <p> 043 * 044 * @author Cosmin Arad {@literal <[email protected]>} 045 * @author Jim Dowling {@literal <[email protected]>} 046 * @author Lars Kroll {@literal <[email protected]>} 047 * @version $Id$ 048 */ 049@SuppressWarnings("serial") 050public class JavaComponent extends ComponentCore { 051 052 private final int executeNEvents; 053 /* 054 * outside ports 055 */ 056 private HashMap<Class<? extends PortType>, JavaPort<? extends PortType>> positivePorts; 057 private HashMap<Class<? extends PortType>, JavaPort<? extends PortType>> negativePorts; 058 private JavaPort<ControlPort> positiveControl, negativeControl; 059 ComponentDefinition component; 060 061 /** 062 * Instantiates a new component core. 063 * <p> 064 * 065 * @param componentDefinition 066 * the component definition 067 */ 068 public JavaComponent(ComponentDefinition componentDefinition) { 069 this.positivePorts = new HashMap<Class<? extends PortType>, JavaPort<? extends PortType>>(); 070 this.negativePorts = new HashMap<Class<? extends PortType>, JavaPort<? extends PortType>>(); 071 this.parent = parentThreadLocal.get(); 072 if (this.parent != null) { 073 this.conf = parent.conf.copy(componentDefinition.separateConfigId()); 074 } else { 075 this.conf = Kompics.getConfig().copy(componentDefinition.separateConfigId()); 076 } 077 078 if (childUpdate.get().isPresent()) { 079 Config.Impl ci = (Config.Impl) this.conf; 080 ci.apply(childUpdate.get().get(), ValueMerger.NONE); 081 Optional<ConfigUpdate> resetUpdate = Optional.empty(); 082 childUpdate.set(resetUpdate); 083 } 084 this.component = componentDefinition; 085 parentThreadLocal.set(null); 086 executeNEvents = Kompics.maxNumOfExecutedEvents.get(); 087 } 088 089 // public JavaComponent(JavaComponent other) { 090 // this.positivePorts = other.positivePorts; 091 // this.negativePorts = other.negativePorts; 092 // this.parent = other.parent; 093 // this.conf = other.conf; 094 // this.component = other.component; 095 // parentThreadLocal.set(null); 096 // } 097 @Override 098 protected Logger logger() { 099 return this.component.logger; 100 } 101 102 /* 103 * (non-Javadoc) 104 * 105 * @see se.sics.kompics.Component#getControl() 106 */ 107 @Override 108 public Positive<ControlPort> getControl() { 109 return positiveControl; 110 } 111 112 @Override 113 public Positive<ControlPort> control() { 114 return positiveControl; 115 } 116 117 Map<Class<? extends PortType>, JavaPort<? extends PortType>> getNegativePorts() { 118 return negativePorts; 119 } 120 121 /* 122 * (non-Javadoc) 123 * 124 * @see se.sics.kompics.Component#getNegative(java.lang.Class) 125 */ 126 @SuppressWarnings("unchecked") 127 @Override 128 public <P extends PortType> Negative<P> getNegative(Class<P> portType) { 129 Negative<P> port = (Negative<P>) negativePorts.get(portType); 130 if (port == null) { 131 throw new RuntimeException(component + " has no negative " + portType.getCanonicalName()); 132 } 133 return port; 134 } 135 136 @Override 137 public <P extends PortType> Negative<P> required(Class<P> portType) { 138 return getNegative(portType); 139 } 140 141 Map<Class<? extends PortType>, JavaPort<? extends PortType>> getPositivePorts() { 142 return positivePorts; 143 } 144 145 /* 146 * (non-Javadoc) 147 * 148 * @see se.sics.kompics.Component#getPositive(java.lang.Class) 149 */ 150 @SuppressWarnings("unchecked") 151 @Override 152 public <P extends PortType> Positive<P> getPositive(Class<P> portType) { 153 Positive<P> port = (Positive<P>) positivePorts.get(portType); 154 if (port == null) { 155 throw new RuntimeException(component + " has no positive " + portType.getCanonicalName()); 156 } 157 return port; 158 } 159 160 @Override 161 public <P extends PortType> Positive<P> provided(Class<P> portType) { 162 return getPositive(portType); 163 } 164 165 @Override 166 public <P extends PortType> Negative<P> createNegativePort(Class<P> portType) { 167 JavaPort<P> negativePort = new JavaPort<P>(false, PortType.getPortType(portType), this); 168 JavaPort<P> positivePort = new JavaPort<P>(true, PortType.getPortType(portType), parent); 169 170 negativePort.setPair(positivePort); 171 positivePort.setPair(negativePort); 172 173 Positive<?> existing = positivePorts.put(portType, positivePort); 174 if (existing != null) { 175 throw new RuntimeException("Cannot create multiple negative " + portType.getCanonicalName()); 176 } 177 return negativePort; 178 } 179 180 @Override 181 public <P extends PortType> Positive<P> createPositivePort(Class<P> portType) { 182 JavaPort<P> negativePort = new JavaPort<P>(false, PortType.getPortType(portType), parent); 183 JavaPort<P> positivePort = new JavaPort<P>(true, PortType.getPortType(portType), this); 184 185 negativePort.setPair(positivePort); 186 positivePort.setPair(negativePort); 187 188 Negative<?> existing = negativePorts.put(portType, negativePort); 189 if (existing != null) { 190 throw new RuntimeException("Cannot create multiple positive " + portType.getCanonicalName()); 191 } 192 return positivePort; 193 } 194 195 @Override 196 public Negative<ControlPort> createControlPort() { 197 negativeControl = new JavaPort<ControlPort>(false, PortType.getPortType(ControlPort.class), this); 198 positiveControl = new JavaPort<ControlPort>(true, PortType.getPortType(ControlPort.class), parent); 199 200 positiveControl.setPair(negativeControl); 201 negativeControl.setPair(positiveControl); 202 203 negativeControl.doSubscribe(handleStart); 204 negativeControl.doSubscribe(handleStop); 205 negativeControl.doSubscribe(handleKill); 206 207 negativeControl.doSubscribe(handleStarted); 208 negativeControl.doSubscribe(handleStopped); 209 negativeControl.doSubscribe(handleKilled); 210 211 negativeControl.doInternalSubscribe(handleFault); 212 213 negativeControl.doInternalSubscribe(configHandler); 214 215 return negativeControl; 216 } 217 218 @Override 219 protected void cleanPorts() { 220 for (JavaPort<? extends PortType> port : negativePorts.values()) { 221 port.cleanChannels(); 222 } 223 for (JavaPort<? extends PortType> port : positivePorts.values()) { 224 port.cleanChannels(); 225 } 226 } 227 228 @Override 229 public <T extends ComponentDefinition> Component doCreate(Class<T> definition, Optional<Init<T>> initEvent) { 230 Optional<ConfigUpdate> update = Optional.empty(); 231 return doCreate(definition, initEvent, update); 232 } 233 234 @Override 235 public <T extends ComponentDefinition> Component doCreate(Class<T> definition, Optional<Init<T>> initEvent, 236 Optional<ConfigUpdate> update) { 237 // create an instance of the implementing component type 238 ComponentDefinition component; 239 childrenLock.writeLock().lock(); 240 try { 241 parentThreadLocal.set(this); 242 childUpdate.set(update); 243 component = createInstance(definition, initEvent); 244 ComponentCore child = component.getComponentCore(); 245 246 // child.workCount.incrementAndGet(); 247 child.setScheduler(scheduler); 248 249 children.add(child); 250 251 return child; 252 } catch (InstantiationException e) { 253 throw new RuntimeException("Cannot create component " + definition.getCanonicalName(), e); 254 } catch (IllegalAccessException e) { 255 throw new RuntimeException("Cannot create component " + definition.getCanonicalName(), e); 256 } catch (NoSuchMethodException e) { 257 throw new RuntimeException("Cannot create component " + definition.getCanonicalName(), e); 258 } catch (InvocationTargetException e) { 259 throw new RuntimeException("Cannot create component " + definition.getCanonicalName(), e); 260 } finally { 261 childrenLock.writeLock().unlock(); 262 } 263 } 264 265 private <T extends ComponentDefinition> T createInstance(Class<T> definition, Optional<Init<T>> initEvent) 266 throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { 267 if (!initEvent.isPresent()) { 268 return definition.newInstance(); 269 } 270 Init<T> init = initEvent.get(); 271 if (init instanceof Init.None) { 272 return definition.newInstance(); 273 } 274 // look for a constructor that takes a single parameter 275 // and is assigment compatible with the given init event 276 Constructor<T> constr = definition.getConstructor(init.getClass()); 277 return constr.newInstance(init); 278 } 279 280 @Override 281 public void execute(int wid) { 282 State previousState = state; 283 if ((state == State.DESTROYED) || (state == State.FAULTY)) { 284 return; // don't schedule these components 285 } 286 this.wid = wid; 287 // System.err.println("Executing " + wid); 288 289 // New scheduling code: Run n and move to end of schedule 290 // 291 int count = 0; 292 int wc = workCount.get(); 293 294 this.component.setMDC(); 295 MDC.put(ComponentDefinition.MDC_KEY_CSTATE, state.name()); 296 try { 297 298 while ((count < executeNEvents) && wc > 0) { 299 if (previousState != state) { // state might have changed between iterations 300 if (state == State.FAULTY) { 301 return; 302 } 303 previousState = state; 304 MDC.put(ComponentDefinition.MDC_KEY_CSTATE, state.name()); 305 } 306 307 KompicsEvent event; 308 JavaPort<?> nextPort; 309 if ((state == State.PASSIVE) || (state == State.STARTING)) { 310 // System.err.println("non-active state " + wid); 311 312 event = negativeControl.pickFirstEvent(); 313 nextPort = negativeControl; 314 315 if (event == null) { 316 logger().debug("Not scheduling component."); 317 // try again 318 if (wc > 0) { 319 schedule(wid); 320 } 321 return; // Don't run anything else 322 } 323 readyPorts.remove(nextPort); 324 } else { 325 // System.err.println("active state " + wid); 326 nextPort = (JavaPort<?>) readyPorts.poll(); 327 if (nextPort == null) { 328 wc = workCount.decrementAndGet(); 329 count++; 330 continue; 331 } 332 event = nextPort.pickFirstEvent(); 333 } 334 335 if (event == null) { 336 logger().debug("Couldn't find event to schedule: wc={}", wc); 337 wc = workCount.decrementAndGet(); 338 count++; 339 continue; 340 } 341 342 HandlerList handlers = nextPort.getSubscribedHandlers(event); 343 344 if ((handlers != null) && (handlers.length > 0)) { 345 for (int i = 0; i < handlers.length; i++) { 346 if (executeEvent(event, handlers.subscriptions[i])) { 347 break; // state changed don't handle the rest of the event 348 } 349 } 350 } 351 if (event instanceof PatternExtractor) { 352 PatternExtractor<?, ?> pe = (PatternExtractor<?, ?>) event; 353 MatchedHandlerList mhandlers = nextPort.getSubscribedMatchers(pe); 354 if ((mhandlers != null) && (mhandlers.length > 0)) { 355 for (int i = 0; i < mhandlers.length; i++) { 356 if (executeEvent(pe, mhandlers.subscriptions[i])) { 357 break; // state changed don't handle the rest of the event 358 } 359 } 360 } 361 } 362 wc = workCount.decrementAndGet(); 363 count++; 364 } 365 366 } finally { 367 MDC.clear(); 368 } 369 370 if (wc > 0) { 371 schedule(wid); 372 } 373 } 374 375 @SuppressWarnings("unchecked") 376 private boolean executeEvent(KompicsEvent event, Handler<?> handler) { 377 try { 378 ((Handler<KompicsEvent>) handler).handle(event); 379 return false; // no state change 380 } catch (Throwable throwable) { 381 logger().error("Handling an event caused a fault! Might be handled later...", throwable); 382 markSubtreeAs(State.FAULTY); 383 escalateFault(new Fault(throwable, this, event)); 384 return true; // state changed 385 } 386 } 387 388 @SuppressWarnings("unchecked") 389 private boolean executeEvent(PatternExtractor<?, ?> event, MatchedHandler<?, ?, ?> handler) { 390 try { 391 PatternExtractor<?, Object> pe = (PatternExtractor<?, Object>) event; 392 MatchedHandler<?, Object, PatternExtractor<?, Object>> h = (MatchedHandler<?, Object, PatternExtractor<?, Object>>) handler; 393 h.handle(pe.extractValue(), pe); 394 return false; // no state change 395 } catch (Throwable throwable) { 396 logger().error("Handling an event caused a fault! Might be handled later...", throwable); 397 markSubtreeAs(State.FAULTY); 398 escalateFault(new Fault(throwable, this, event)); 399 return true; // state changed 400 } 401 } 402 403 @Override 404 public void escalateFault(Fault fault) { 405 if (parent != null) { 406 parent.control().doTrigger(fault, wid, this); 407 } else { 408 // StackTraceElement[] stackTrace = throwable.getStackTrace(); 409 // System.err.println("Kompics isolated fault: " 410 // + throwable.getMessage()); 411 // do { 412 // for (int i = 0; i < stackTrace.length; i++) { 413 // System.err.println(" " + stackTrace[i]); 414 // } 415 // throwable = throwable.getCause(); 416 // if (throwable != null) { 417 // stackTrace = throwable.getStackTrace(); 418 // System.err.println("Caused by: " + throwable + ": " 419 // + throwable.getMessage()); 420 // } 421 // } while (throwable != null); 422 logger().error("A fault was escalated to the root component: \n{} \n\n", fault); 423 Kompics.handleFault(fault); 424 // System.exit(1); 425 } 426 } 427 428 Handler<Fault> handleFault = new Handler<Fault>() { 429 430 @Override 431 public void handle(Fault event) { 432 433 ResolveAction ra = component.handleFault(event); 434 switch (ra) { 435 case RESOLVED: 436 logger().info("Fault {} was resolved by user.", event); 437 break; 438 case IGNORE: 439 logger().info("Fault {} was declared to be ignored by user. Resuming component...", event); 440 markSubtreeAtAs(event.source, State.PASSIVE); 441 event.source.control().doTrigger(Start.event, wid, JavaComponent.this); 442 break; 443 case DESTROY: 444 logger().info("User declared that Fault {} should destroy component tree...", event); 445 destroyTreeAtParentOf(event.source); 446 logger().info("finished destroying the subtree."); 447 break; 448 default: 449 escalateFault(event); 450 } 451 } 452 }; 453 Handler<Update> configHandler = new Handler<Update>() { 454 455 @Override 456 public void handle(Update event) { 457 UpdateAction action = JavaComponent.this.component.handleUpdate(event.update); 458 switch (action.selfStrategy) { 459 case ORIGINAL: 460 ((Config.Impl) conf).apply(event.update, action.merger); 461 break; 462 case MAP: 463 ((Config.Impl) conf).apply(action.selfMapper.map(event.update, event.update.modify(id())), 464 action.merger); 465 break; 466 case SWALLOW: 467 break; 468 } 469 if ((parent != null) && (event.forwarder == parent.id())) { // downwards 470 switch (action.downStrategy) { 471 case ORIGINAL: { 472 Update forwardedEvent = new Update(event.update, id()); 473 for (Component child : children) { 474 ((PortCore<ControlPort>) child.getControl()).doTrigger(forwardedEvent, wid, 475 component.getComponentCore()); 476 } 477 } 478 break; 479 case MAP: { 480 ConfigUpdate mappedUpdate = action.downMapper.map(event.update, event.update.modify(id())); 481 Update forwardedEvent = new Update(mappedUpdate, id()); 482 for (Component child : children) { 483 ((PortCore<ControlPort>) child.getControl()).doTrigger(forwardedEvent, wid, 484 component.getComponentCore()); 485 } 486 } 487 break; 488 case SWALLOW: 489 break; 490 } 491 } else { // upwards and to other children 492 switch (action.downStrategy) { 493 case ORIGINAL: { 494 Update forwardedEvent = new Update(event.update, id()); 495 for (Component child : children) { 496 if (child.id() != event.forwarder) { 497 ((PortCore<ControlPort>) child.getControl()).doTrigger(forwardedEvent, wid, 498 component.getComponentCore()); 499 } 500 } 501 } 502 break; 503 case MAP: { 504 ConfigUpdate mappedUpdate = action.downMapper.map(event.update, event.update.modify(id())); 505 Update forwardedEvent = new Update(mappedUpdate, id()); 506 for (Component child : children) { 507 if (child.id() != event.forwarder) { 508 ((PortCore<ControlPort>) child.getControl()).doTrigger(forwardedEvent, wid, 509 component.getComponentCore()); 510 } 511 } 512 } 513 break; 514 case SWALLOW: 515 break; 516 } 517 if (parent != null) { 518 switch (action.upStrategy) { 519 case ORIGINAL: { 520 Update forwardedEvent = new Update(event.update, id()); 521 ((PortCore<ControlPort>) parent.getControl()).doTrigger(forwardedEvent, wid, 522 component.getComponentCore()); 523 } 524 break; 525 526 case MAP: { 527 ConfigUpdate mappedUpdate = action.upMapper.map(event.update, event.update.modify(id())); 528 Update forwardedEvent = new Update(mappedUpdate, id()); 529 ((PortCore<ControlPort>) parent.getControl()).doTrigger(forwardedEvent, wid, 530 component.getComponentCore()); 531 } 532 break; 533 case SWALLOW: 534 break; 535 } 536 } 537 } 538 component.postUpdate(); 539 } 540 }; 541 542 @Override 543 public ComponentDefinition getComponent() { 544 return component; 545 } 546 547 @Override 548 void doConfigUpdate(ConfigUpdate update) { 549 Config.Impl impl = (Config.Impl) conf; 550 impl.apply(update, ValueMerger.NONE); 551 Update forwardedEvent = new Update(update, id()); 552 // forward down 553 for (Component child : children) { 554 ((PortCore<ControlPort>) child.getControl()).doTrigger(forwardedEvent, wid, this); 555 } 556 // forward up 557 if (parent != null) { 558 ((PortCore<ControlPort>) parent.getControl()).doTrigger(forwardedEvent, wid, this); 559 } 560 component.postUpdate(); 561 } 562 563 @Override 564 public boolean equals(Object o) { 565 if (o instanceof JavaComponent) { 566 JavaComponent that = (JavaComponent) o; 567 return this.id().equals(that.id()); 568 } 569 return false; 570 } 571 572 @Override 573 public int hashCode() { 574 int hash = 7; 575 hash = 11 * hash + Objects.hashCode(this.id()); 576 return hash; 577 } 578 /* 579 * === LIFECYCLE === 580 */ 581 582 @Override 583 protected void setInactive(Component child) { 584 activeSet.remove(child); 585 } 586 587 private Set<Component> activeSet = new HashSet<Component>(); 588 Handler<Start> handleStart = new Handler<Start>() { 589 @Override 590 public void handle(Start event) { 591 if (state != Component.State.PASSIVE) { 592 throw new KompicsException(JavaComponent.this + " received a Start event while in " + state + " state. " 593 + "Duplicate Start events are not allowed!"); 594 } 595 try { 596 childrenLock.readLock().lock(); 597 if (!children.isEmpty()) { 598 logger().debug("Starting..."); 599 state = Component.State.STARTING; 600 for (ComponentCore child : children) { 601 logger().debug("Sending Start to child: {}", child); 602 // start child 603 ((PortCore<ControlPort>) child.getControl()).doTrigger(Start.event, wid, 604 component.getComponentCore()); 605 } 606 } else { 607 logger().debug("Started!"); 608 state = Component.State.ACTIVE; 609 if (parent != null) { 610 ((PortCore<ControlPort>) parent.getControl()).doTrigger( 611 new Started(component.getComponentCore()), wid, component.getComponentCore()); 612 } 613 } 614 } finally { 615 childrenLock.readLock().unlock(); 616 } 617 } 618 619 @Override 620 public java.lang.Class<Start> getEventType() { 621 return Start.class; 622 }; 623 }; 624 625 Handler<Stop> handleStop = new Handler<Stop>() { 626 @Override 627 public void handle(Stop event) { 628 if (state != Component.State.ACTIVE) { 629 throw new KompicsException(JavaComponent.this + " received a Stop event while in " + state + " state. " 630 + "Duplicate Stop events are not allowed!"); 631 } 632 try { 633 childrenLock.readLock().lock(); 634 if (!children.isEmpty()) { 635 logger().debug("Stopping..."); 636 state = Component.State.STOPPING; 637 for (ComponentCore child : children) { 638 if (child.state() != Component.State.ACTIVE) { 639 continue; // don't send stop events to already stopping components 640 } 641 logger().debug("Sending Stop to child: {}", child); 642 // stop child 643 ((PortCore<ControlPort>) child.getControl()).doTrigger(Stop.event, wid, 644 component.getComponentCore()); 645 } 646 } else { 647 logger().debug("Stopped!"); 648 state = Component.State.PASSIVE; 649 component.tearDown(); 650 if (parent != null) { 651 ((PortCore<ControlPort>) parent.getControl()).doTrigger( 652 new Stopped(component.getComponentCore()), wid, component.getComponentCore()); 653 } else { 654 synchronized (component.getComponentCore()) { 655 component.getComponentCore().notifyAll(); 656 } 657 } 658 } 659 } finally { 660 childrenLock.readLock().unlock(); 661 } 662 } 663 664 @Override 665 public java.lang.Class<Stop> getEventType() { 666 return Stop.class; 667 }; 668 }; 669 670 Handler<Kill> handleKill = new Handler<Kill>() { 671 672 @Override 673 public void handle(Kill event) { 674 if (state != Component.State.ACTIVE) { 675 throw new KompicsException(JavaComponent.this + " received a Kill event while in " + state + " state. " 676 + "Duplicate Kill events are not allowed!"); 677 } 678 try { 679 childrenLock.readLock().lock(); 680 if (!children.isEmpty()) { 681 logger().debug("Slowly dying..."); 682 state = Component.State.STOPPING; 683 ((PortCore<ControlPort>) getControl().getPair()).cleanEvents(); // if multiple kills are queued up 684 // just ignore everything 685 for (ComponentCore child : children) { 686 if (child.state() != Component.State.ACTIVE) { 687 continue; // don't send stop events to already stopping components 688 } 689 logger().debug("Sending Kill to child: {}", child); 690 // stop child 691 ((PortCore<ControlPort>) child.getControl()).doTrigger(Kill.event, wid, 692 component.getComponentCore()); 693 } 694 } else { 695 logger().debug("dying..."); 696 state = Component.State.PASSIVE; 697 ((PortCore<ControlPort>) getControl().getPair()).cleanEvents(); // if multiple kills are queued up 698 // just ignore everything 699 component.tearDown(); 700 if (parent != null) { 701 ((PortCore<ControlPort>) parent.getControl()) 702 .doTrigger(new Killed(component.getComponentCore()), wid, component.getComponentCore()); 703 } else { 704 synchronized (component.getComponentCore()) { 705 component.getComponentCore().notifyAll(); 706 } 707 } 708 } 709 } finally { 710 childrenLock.readLock().unlock(); 711 } 712 } 713 714 @Override 715 public java.lang.Class<Kill> getEventType() { 716 return Kill.class; 717 } 718 719 }; 720 721 Handler<Killed> handleKilled = new Handler<Killed>() { 722 723 @Override 724 public void handle(Killed event) { 725 logger().debug("Got Killed event from {}", event.component); 726 727 activeSet.remove(event.component); 728 doDestroy(event.component); 729 logger().debug("Active set has {} members", activeSet.size()); 730 if (activeSet.isEmpty() && (state == Component.State.STOPPING)) { 731 logger().debug("Stopped!"); 732 state = Component.State.PASSIVE; 733 component.tearDown(); 734 if (parent != null) { 735 ((PortCore<ControlPort>) parent.getControl()).doTrigger(new Killed(component.getComponentCore()), 736 wid, component.getComponentCore()); 737 } else { 738 synchronized (component.getComponentCore()) { 739 component.getComponentCore().notifyAll(); 740 } 741 } 742 } 743 } 744 745 @Override 746 public java.lang.Class<Killed> getEventType() { 747 return Killed.class; 748 } 749 }; 750 751 Handler<Started> handleStarted = new Handler<Started>() { 752 @Override 753 public void handle(Started event) { 754 logger().debug("Got Started event from {}", event.component); 755 activeSet.add(event.component); 756 logger().debug("Active set has {} members", activeSet.size()); 757 try { 758 childrenLock.readLock().lock(); 759 if ((activeSet.size() == children.size()) && (state == Component.State.STARTING)) { 760 logger().debug("Started!"); 761 state = Component.State.ACTIVE; 762 if (parent != null) { 763 ((PortCore<ControlPort>) parent.getControl()).doTrigger( 764 new Started(component.getComponentCore()), wid, component.getComponentCore()); 765 } 766 } 767 } finally { 768 childrenLock.readLock().unlock(); 769 } 770 771 } 772 773 @Override 774 public java.lang.Class<Started> getEventType() { 775 return Started.class; 776 }; 777 }; 778 779 Handler<Stopped> handleStopped = new Handler<Stopped>() { 780 @Override 781 public void handle(Stopped event) { 782 logger().debug("Got Stopped event from {}", event.component); 783 784 activeSet.remove(event.component); 785 logger().debug("Active set has {} members", activeSet.size()); 786 if (activeSet.isEmpty() && (state == Component.State.STOPPING)) { 787 logger().debug("Stopped!"); 788 state = Component.State.PASSIVE; 789 component.tearDown(); 790 if (parent != null) { 791 ((PortCore<ControlPort>) parent.getControl()).doTrigger(new Stopped(component.getComponentCore()), 792 wid, component.getComponentCore()); 793 } else { 794 synchronized (component.getComponentCore()) { 795 component.getComponentCore().notifyAll(); 796 } 797 } 798 } 799 800 } 801 802 @Override 803 public java.lang.Class<Stopped> getEventType() { 804 return Stopped.class; 805 }; 806 807 }; 808 809}