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