Coverage Report - com.thindeck.Routine
 
Classes in this File Line Coverage Branch Coverage Complexity
Routine
0%
0/46
0%
0/12
2.444
Routine$1
0%
0/2
N/A
2.444
Routine$2
0%
0/9
0%
0/2
2.444
Routine$2$AjcClosure1
0%
0/1
N/A
2.444
Routine$3
0%
0/3
N/A
2.444
Routine$AjcClosure1
0%
0/1
N/A
2.444
 
 1  0
 /**
 2  
  * Copyright (c) 2014-2015, Thindeck.com
 3  
  * All rights reserved.
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions
 7  
  * are met: 1) Redistributions of source code must retain the above
 8  
  * copyright notice, this list of conditions and the following
 9  
  * disclaimer. 2) Redistributions in binary form must reproduce the above
 10  
  * copyright notice, this list of conditions and the following
 11  
  * disclaimer in the documentation and/or other materials provided
 12  
  * with the distribution. 3) Neither the name of the thindeck.com nor
 13  
  * the names of its contributors may be used to endorse or promote
 14  
  * products derived from this software without specific prior written
 15  
  * permission.
 16  
  *
 17  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 19  
  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 20  
  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 21  
  * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 22  
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23  
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 24  
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 25  
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 26  
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 27  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 28  
  * OF THE POSSIBILITY OF SUCH DAMAGE.
 29  
  */
 30  
 package com.thindeck;
 31  
 
 32  
 import com.jcabi.aspects.Immutable;
 33  
 import com.jcabi.aspects.LogExceptions;
 34  
 import com.jcabi.aspects.Loggable;
 35  
 import com.jcabi.aspects.ScheduleWithFixedDelay;
 36  
 import com.jcabi.immutable.Array;
 37  
 import com.jcabi.log.Logger;
 38  
 import com.thindeck.agents.BuildImage;
 39  
 import com.thindeck.agents.BuryContainers;
 40  
 import com.thindeck.agents.CheckState;
 41  
 import com.thindeck.agents.DetectPorts;
 42  
 import com.thindeck.agents.FindTanks;
 43  
 import com.thindeck.agents.PingContainers;
 44  
 import com.thindeck.agents.PingImages;
 45  
 import com.thindeck.agents.RemoveImages;
 46  
 import com.thindeck.agents.StartDocker;
 47  
 import com.thindeck.agents.StopDocker;
 48  
 import com.thindeck.agents.Swap;
 49  
 import com.thindeck.agents.TerminateDocker;
 50  
 import com.thindeck.agents.UpdateNginx;
 51  
 import com.thindeck.agents.WasteContainers;
 52  
 import com.thindeck.agents.WasteImages;
 53  
 import com.thindeck.agents.WipeRepo;
 54  
 import com.thindeck.api.Agent;
 55  
 import com.thindeck.api.Base;
 56  
 import com.thindeck.api.Boss;
 57  
 import com.thindeck.api.Deck;
 58  
 import com.thindeck.bosses.CleanNginx;
 59  
 import com.thindeck.bosses.SetupNginx;
 60  
 import com.thindeck.bosses.UploadKeys;
 61  
 import java.io.IOException;
 62  
 import java.util.Arrays;
 63  
 import java.util.Collection;
 64  
 import java.util.LinkedList;
 65  
 import java.util.concurrent.Callable;
 66  
 import java.util.concurrent.ExecutionException;
 67  
 import java.util.concurrent.ExecutorService;
 68  
 import java.util.concurrent.Executors;
 69  
 import java.util.concurrent.Future;
 70  
 import java.util.concurrent.ThreadFactory;
 71  
 import java.util.concurrent.TimeUnit;
 72  
 import java.util.concurrent.atomic.AtomicInteger;
 73  
 import lombok.EqualsAndHashCode;
 74  
 import lombok.ToString;
 75  
 import org.apache.commons.lang3.exception.ExceptionUtils;
 76  
 
 77  
 /**
 78  
  * Agents.
 79  
  *
 80  
  * @author Yegor Bugayenko (yegor@teamed.io)
 81  
  * @version $Id$
 82  
  * @since 0.1
 83  
  * @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
 84  
  * @checkstyle ClassFanOutComplexityCheck (500 lines)
 85  
  */
 86  
 @Immutable
 87  0
 @ToString
 88  0
 @EqualsAndHashCode
 89  
 @ScheduleWithFixedDelay(delay = 1, unit = TimeUnit.MINUTES)
 90  
 @Loggable(Loggable.INFO)
 91  
 @SuppressWarnings({ "PMD.DoNotUseThreads", "PMD.ExcessiveImports" })
 92  0
 final class Routine implements Runnable {
 93  
 
 94  
     /**
 95  
      * Start.
 96  
      */
 97  
     private final transient long start;
 98  
 
 99  
     /**
 100  
      * Base.
 101  
      */
 102  
     private final transient Base base;
 103  
 
 104  
     /**
 105  
      * Agents.
 106  
      */
 107  
     private final transient Array<Agent> agents;
 108  
 
 109  
     /**
 110  
      * Bosses.
 111  
      */
 112  
     private final transient Array<Boss> bosses;
 113  
 
 114  
     /**
 115  
      * Execute them all.
 116  
      * @param bse Base
 117  
      * @throws IOException If fails
 118  
      */
 119  0
     Routine(final Base bse) throws IOException {
 120  0
         this.start = System.currentTimeMillis();
 121  0
         this.base = bse;
 122  0
         this.agents = new Array<>(Routine.allAgents());
 123  0
         this.bosses = new Array<>(Routine.allBosses());
 124  0
     }
 125  
 
 126  
     @Override
 127  
     @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
 128  
     public void run() {
 129  0
         final AtomicInteger grp = new AtomicInteger();
 130  0
         final ExecutorService exec = Executors.newCachedThreadPool(
 131  0
             new ThreadFactory() {
 132  
                 @Override
 133  
                 public Thread newThread(final Runnable runnable) {
 134  0
                     return new Thread(
 135  
                         new ThreadGroup(
 136  
                             Integer.toString(grp.getAndIncrement())
 137  
                         ),
 138  
                         runnable
 139  
                     );
 140  
                 }
 141  
             }
 142  
         );
 143  0
         final Iterable<Deck> decks = this.decks();
 144  0
         final Collection<Future<Integer>> futures = new LinkedList<>();
 145  0
         futures.add(
 146  
             exec.submit(
 147  0
                 new Callable<Integer>() {
 148  
                     @Override
 149  
                     @LogExceptions
 150  
                     public Integer call() throws Exception {
 151  0
                         int total = 0;
 152  0
                         for (final Boss boss : Routine.this.bosses) {
 153  0
                             boss.exec(decks);
 154  0
                             ++total;
 155  0
                         }
 156  0
                         Logger.info(this, "%d bosses succeeded", total);
 157  0
                         return total;
 158  
                     }
 159  
                 }
 160  
             )
 161  
         );
 162  0
         for (final Deck deck : decks) {
 163  0
             futures.add(
 164  
                 exec.submit(
 165  0
                     new Callable<Integer>() {
 166  
                         @Override
 167  
                         public Integer call() throws Exception {
 168  0
                             Routine.this.exec(deck);
 169  0
                             return 1;
 170  
                         }
 171  
                     }
 172  
                 )
 173  
             );
 174  0
         }
 175  0
         for (final Future<?> future : futures) {
 176  
             try {
 177  0
                 future.get();
 178  0
             } catch (final InterruptedException ex) {
 179  0
                 Thread.currentThread().interrupt();
 180  0
                 throw new IllegalStateException(ex);
 181  0
             } catch (final ExecutionException ex) {
 182  0
                 throw new IllegalStateException(ex);
 183  0
             }
 184  0
         }
 185  0
         Logger.info(
 186  
             this, "decks done, alive for %[ms]s",
 187  
             System.currentTimeMillis() - this.start
 188  
         );
 189  0
     }
 190  
 
 191  
     /**
 192  
      * Get all decks.
 193  
      * @return Decks
 194  
      */
 195  
     private Iterable<Deck> decks() {
 196  
         try {
 197  0
             return this.base.active();
 198  0
         } catch (final IOException ex) {
 199  0
             throw new IllegalStateException(ex);
 200  
         }
 201  
     }
 202  
 
 203  
     /**
 204  
      * Process one deck.
 205  
      * @param deck Deck
 206  
      * @throws IOException If fails
 207  
      */
 208  
     @SuppressWarnings("PMD.AvoidCatchingThrowable")
 209  
     private void exec(final Deck deck) throws IOException {
 210  0
         final Collection<String> failure = new LinkedList<>();
 211  0
         for (final Agent agent : this.agents) {
 212  
             try {
 213  0
                 deck.exec(agent);
 214  
                 // @checkstyle IllegalCatchCheck (1 line)
 215  0
             } catch (final Throwable ex) {
 216  0
                 Logger.error(this, "%s", ExceptionUtils.getStackTrace(ex));
 217  0
                 failure.add(agent.getClass().getSimpleName());
 218  0
             }
 219  0
         }
 220  0
         if (failure.isEmpty()) {
 221  0
             deck.events().create("success");
 222  
         } else {
 223  0
             deck.events().create(String.format("failed: %s", failure));
 224  
         }
 225  0
     }
 226  
 
 227  
     /**
 228  
      * Create a list of agents.
 229  
      * @return List of agents
 230  
      * @throws IOException If fails
 231  
      */
 232  
     private static Iterable<Agent> allAgents() throws IOException {
 233  0
         return Arrays.asList(
 234  
             new WipeRepo(),
 235  
             new DetectPorts(),
 236  
             new TerminateDocker(),
 237  
             new PingContainers(),
 238  
             new PingImages(),
 239  
             new BuryContainers(),
 240  
             new WasteContainers(),
 241  
             new WasteImages(),
 242  
             new StopDocker(),
 243  
             new RemoveImages(),
 244  
             new BuildImage(),
 245  
             new FindTanks(),
 246  
             new CheckState(),
 247  
             new Swap(),
 248  
             new StartDocker(),
 249  
             new UpdateNginx()
 250  
         );
 251  
     }
 252  
 
 253  
     /**
 254  
      * Create a list of bosses.
 255  
      * @return List of bosses
 256  
      * @throws IOException If fails
 257  
      */
 258  
     private static Iterable<Boss> allBosses() throws IOException {
 259  0
         return Arrays.asList(
 260  
             new UploadKeys(),
 261  
             new SetupNginx(),
 262  
             new CleanNginx()
 263  
         );
 264  
     }
 265  
 
 266  
 }