Project

General

Profile

Download (5.36 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2015 EDIT
3
 * European Distributed Institute of Taxonomy
4
 * http://www.e-taxonomy.eu
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9
package eu.etaxonomy.cdm.server.instance;
10

    
11
import java.util.HashSet;
12
import java.util.LinkedList;
13
import java.util.Set;
14

    
15
import org.apache.log4j.Logger;
16
import org.eclipse.jetty.util.component.LifeCycle;
17
import org.eclipse.jetty.util.component.LifeCycle.Listener;
18
import org.slf4j.MDC;
19

    
20
import eu.etaxonomy.cdm.server.logging.InstanceLogWrapper;
21

    
22
/**
23
 * @author a.kohlbecker
24
 * @date Jul 29, 2015
25
 *
26
 */
27
public class StartupQueue extends LinkedList<CdmInstance> {
28

    
29
    private static final long serialVersionUID = -8173521573512154767L;
30

    
31
    private final Logger logger = Logger.getLogger(InstanceManager.class);
32

    
33
    Set<CdmInstance> instancesStartingUp = new HashSet<>();
34

    
35
    private int parallelStartUps = 1;
36

    
37
    public int getParallelStartUps() {
38
        return parallelStartUps;
39
    }
40
    public void setParallelStartUps(int parallelStartUps) {
41
        this.parallelStartUps = parallelStartUps;
42
    }
43

    
44
    @Override
45
    public boolean add(CdmInstance e) {
46
        boolean result = super.add(e);
47
        registerAt(e);
48
        return result;
49
    }
50

    
51
    @Override
52
    public void addFirst(CdmInstance e) {
53
        super.addFirst(e);
54
        registerAt(e);
55
    }
56

    
57
    @Override
58
    public void addLast(CdmInstance e) {
59
        super.addLast(e);
60
        registerAt(e);
61
    }
62

    
63
    protected void notifyInstanceStartedUp(CdmInstance instance) {
64
        logger.debug("received message that instance " + instance.getName() + " has started up.");
65
        instancesStartingUp.remove(instance);
66
        startNextInstances();
67
    }
68

    
69
    protected void notifyInstanceFailed(CdmInstance instance) {
70
        logger.debug("received message that instance " + instance.getName() + " has failed.");
71
        instancesStartingUp.remove(instance);
72
        startNextInstances();
73
    }
74

    
75
    private void startNextInstances() {
76
        logger.debug("startNextInstances()");
77
        while(instancesStartingUp.size() < parallelStartUps && !isEmpty()) {
78
            CdmInstance nextInstance = pop();
79
            instancesStartingUp.add(nextInstance);
80
            logger.debug("Starting instance " + nextInstance.getName() + " in new thread.");
81
            Thread t = new StartupThread(nextInstance);
82
            t.start();
83
        }
84
    }
85

    
86
    @SuppressWarnings("unused")
87
    private void registerAt(CdmInstance e) {
88
        new InstanceListener(e);
89
        startNextInstances();
90

    
91
    }
92

    
93
    class InstanceListener implements Listener {
94

    
95
        private CdmInstance instance;
96

    
97
        InstanceListener(CdmInstance instance) {
98
            this.instance = instance;
99
            instance.getWebAppContext().addLifeCycleListener(this);
100
        }
101

    
102
        @Override
103
        public void lifeCycleStarting(LifeCycle event) {
104
            // IGNORE
105
        }
106

    
107
        @Override
108
        public void lifeCycleStarted(LifeCycle event) {
109
            notifyInstanceStartedUp(instance);
110
            // release reference to the instance so
111
            // that the thread can be garbage collected
112
            instance.getWebAppContext().removeLifeCycleListener(this);
113
            instance = null;
114
        }
115

    
116
        @Override
117
        public void lifeCycleFailure(LifeCycle event, Throwable cause) {
118
            notifyInstanceFailed(instance);
119
            // release reference to the instance so
120
            // that the thread can be garbage collected
121
            instance.getWebAppContext().removeLifeCycleListener(this);
122
            instance = null;
123
        }
124

    
125
        @Override
126
        public void lifeCycleStopping(LifeCycle event) {
127
            // IGNORE
128
        }
129

    
130
        @Override
131
        public void lifeCycleStopped(LifeCycle event) {
132
            // IGNORE
133
        }
134
    }
135

    
136
    class StartupThread extends Thread{
137

    
138
        private final Logger logger = Logger.getLogger(InstanceManager.class);
139

    
140
        private CdmInstance instance;
141

    
142
        StartupThread(CdmInstance instance){
143
            this.instance = instance;
144
        }
145

    
146
        @Override
147
        public void run() {
148
            try {
149
                MDC.put(InstanceLogWrapper.CDM_INSTANCE, instance.getName());
150

    
151
                instance.getWebAppContext().setThrowUnavailableOnStartupException(true);
152
                instance.getWebAppContext().start();
153
                // release reference to the instance so
154
                // that the thread can be garbage collected
155
                instance = null;
156
            } catch(InterruptedException e) {
157
                try {
158
                    instance.getWebAppContext().stop();
159
                } catch (Exception e1) {
160
                    logger.error("Error on stopping instance", e1);
161
                    notifyInstanceFailed(instance);
162
                }
163
            } catch (Throwable e) {
164
                logger.error("Could not start " + instance.getWebAppContext().getContextPath(), e);
165
                instance.getProblems().add(e.getMessage());
166
                instance.setStatus(Status.error);
167
                notifyInstanceFailed(instance);
168
                try {
169
                    // try to stop
170
                    instance.getWebAppContext().stop();
171
                } catch (Exception e1) {
172
                    /* IGNORE */
173
                }
174
            } finally {
175
                MDC.clear();
176
            }
177
        }
178
    }
179
}
(6-6/7)