001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Nuxeo - initial API and implementation
011 */
012
013package org.nuxeo.ecm.core.management.statuses;
014
015import static org.nuxeo.ecm.core.management.api.AdministrativeStatus.ACTIVE;
016import static org.nuxeo.ecm.core.management.api.AdministrativeStatus.PASSIVE;
017
018import java.util.Calendar;
019import java.util.List;
020import java.util.concurrent.Executors;
021import java.util.concurrent.ScheduledExecutorService;
022import java.util.concurrent.ThreadFactory;
023import java.util.concurrent.TimeUnit;
024
025import org.nuxeo.ecm.core.management.CoreManagementService;
026import org.nuxeo.ecm.core.management.api.AdministrativeStatus;
027import org.nuxeo.ecm.core.management.api.AdministrativeStatusManager;
028import org.nuxeo.ecm.core.management.api.GlobalAdministrativeStatusManager;
029import org.nuxeo.ecm.core.management.storage.AdministrativeStatusPersister;
030import org.nuxeo.runtime.transaction.TransactionHelper;
031
032/**
033 * Implementation class for the {@link AdministrativeStatusManager} service. For each Nuxeo Instance in the cluster one
034 * instance of this class is created.
035 *
036 * @author tiry
037 */
038public class AdministrativeStatusManagerImpl implements AdministrativeStatusManager, CoreManagementService {
039
040    protected final AdministrativeStatusPersister persister;
041
042    protected final GlobalAdministrativeStatusManager globalManager;
043
044    protected final String serverInstanceName;
045
046    protected final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new ThreadFactory() {
047        @Override
048        public Thread newThread(Runnable r) {
049            return new Thread(r, "Nuxeo-Administrative-Statuses-Notify-Scheduler");
050        }
051    });
052
053    protected final Notifier[] notifiers = { new CoreEventNotifier(), new RuntimeEventNotifier() };
054
055    public AdministrativeStatusManagerImpl(GlobalAdministrativeStatusManager globalManager,
056            AdministrativeStatusPersister persister) {
057        this.globalManager = globalManager;
058        this.persister = persister;
059        serverInstanceName = NuxeoInstanceIdentifierHelper.getServerInstanceName();
060    }
061
062    public AdministrativeStatusManagerImpl(GlobalAdministrativeStatusManager globalManager,
063            AdministrativeStatusPersister persister, String instanceIdentifier) {
064        this.globalManager = globalManager;
065        this.persister = persister;
066        serverInstanceName = instanceIdentifier;
067    }
068
069    protected String getServerInstanceName() {
070        return serverInstanceName;
071    }
072
073    protected void notifyEvent(String eventName, String instanceIdentifier, String serviceIdentifier) {
074        for (Notifier notifier : notifiers) {
075            notifier.notifyEvent(eventName, instanceIdentifier, serviceIdentifier);
076        }
077    }
078
079    public void onNuxeoServerStartup() {
080
081        List<AdministrativeStatus> savedStatuses = persister.getAllStatuses(serverInstanceName);
082
083        // iterate throw declared services and init them if needed
084        List<AdministrableServiceDescriptor> descs = globalManager.listRegistredServices();
085
086        for (AdministrableServiceDescriptor desc : descs) {
087            boolean serviceExist = false;
088            for (AdministrativeStatus status : savedStatuses) {
089                if (desc.getId().equals(status.getServiceIdentifier())) {
090                    serviceExist = true;
091                    break;
092                }
093            }
094            if (!serviceExist) {
095                AdministrativeStatus newStatus = new AdministrativeStatus(desc.getInitialState(), "",
096                        Calendar.getInstance(), "system", serverInstanceName, desc.getId());
097                persister.saveStatus(newStatus);
098            }
099        }
100
101        doNotifyAllStatuses();
102
103        scheduler.scheduleAtFixedRate(new NotifyStatusesHandler(), 5, 5, TimeUnit.MINUTES);
104    }
105
106    protected void doNotifyAllStatuses() {
107        for (AdministrativeStatus status : persister.getAllStatuses(serverInstanceName)) {
108            notifyOnStatus(status);
109        }
110    }
111
112    public class NotifyStatusesHandler implements Runnable {
113        @Override
114        public void run() {
115            TransactionHelper.startTransaction();
116            boolean notified = false;
117            try {
118                doNotifyAllStatuses();
119                notified = true;
120            } finally {
121                if (!notified) {
122                    TransactionHelper.setTransactionRollbackOnly();
123                }
124                TransactionHelper.commitOrRollbackTransaction();
125            }
126        }
127    }
128
129    public void onNuxeoServerShutdown() {
130        scheduler.shutdown();
131    }
132
133    protected void notifyOnStatus(AdministrativeStatus status) {
134        if (status.isActive()) {
135            notifyEvent(ACTIVATED_EVENT, status.getInstanceIdentifier(), status.getServiceIdentifier());
136        } else if (status.isPassive()) {
137            notifyEvent(PASSIVATED_EVENT, status.getInstanceIdentifier(), status.getServiceIdentifier());
138        }
139    }
140
141    @Override
142    public AdministrativeStatus activateNuxeoInstance(String message, String login) {
143        return activate(GLOBAL_INSTANCE_AVAILABILITY, message, login);
144    }
145
146    @Override
147    public AdministrativeStatus deactivateNuxeoInstance(String message, String login) {
148        return deactivate(GLOBAL_INSTANCE_AVAILABILITY, message, login);
149    }
150
151    @Override
152    public AdministrativeStatus getNuxeoInstanceStatus() {
153        return getStatus(GLOBAL_INSTANCE_AVAILABILITY);
154    }
155
156    @Override
157    public AdministrativeStatus setNuxeoInstanceStatus(String state, String message, String login) {
158        return setStatus(GLOBAL_INSTANCE_AVAILABILITY, state, message, login);
159    }
160
161    @Override
162    public AdministrativeStatus activate(String serviceIdentifier, String message, String login) {
163        return setStatus(serviceIdentifier, ACTIVE, message, login);
164    }
165
166    @Override
167    public AdministrativeStatus deactivate(String serviceIdentifier, String message, String login) {
168        return setStatus(serviceIdentifier, PASSIVE, message, login);
169    }
170
171    @Override
172    public AdministrativeStatus setStatus(String serviceIdentifier, String state, String message, String login) {
173        AdministrativeStatus status = new AdministrativeStatus(state, message, Calendar.getInstance(), login,
174                serverInstanceName, serviceIdentifier);
175        status = persister.saveStatus(status);
176        notifyOnStatus(status);
177        return addLabelAndDescription(status);
178    }
179
180    @Override
181    public List<AdministrativeStatus> getAllStatuses() {
182        List<AdministrativeStatus> statuses = persister.getAllStatuses(serverInstanceName);
183        for (AdministrativeStatus status : statuses) {
184            addLabelAndDescription(status);
185        }
186        return statuses;
187    }
188
189    protected AdministrativeStatus addLabelAndDescription(AdministrativeStatus status) {
190        if (status == null) {
191            return null;
192        }
193        String id = status.getServiceIdentifier();
194        AdministrableServiceDescriptor desc = globalManager.getServiceDescriptor(id);
195        if (desc != null) {
196            status.setLabelAndDescription(desc.getLabel(), desc.getDescription());
197        }
198        return status;
199    }
200
201    @Override
202    public AdministrativeStatus getStatus(String serviceIdentifier) {
203        AdministrativeStatus status = persister.getStatus(serverInstanceName, serviceIdentifier);
204        addLabelAndDescription(status);
205        return status;
206    }
207
208}