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
public class StartupQueue extends LinkedList<CdmInstance> {
27

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

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

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

    
34
    private int parallelStartUps = 1;
35

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

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

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

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

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

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

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

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

    
90
    }
91

    
92
    class InstanceListener implements Listener {
93

    
94
        private CdmInstance instance;
95

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

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

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

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

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

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

    
135
    class StartupThread extends Thread{
136

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

    
139
        private CdmInstance instance;
140

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

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

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