Java tutorial
package com.r1soft.backup.server.web; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import javax.imageio.ImageIO; import org.apache.commons.lang.builder.EqualsBuilder; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.WebApp; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventQueue; import org.zkoss.zk.ui.event.EventQueues; import org.zkoss.zk.ui.util.DesktopCleanup; import org.zkoss.zk.ui.util.DesktopInit; import org.zkoss.zk.ui.util.WebAppCleanup; import org.zkoss.zul.Image; import org.zkoss.zul.Space; import com.r1soft.backup.server.cache.CacheEntry; import com.r1soft.backup.server.cache.SigarDiskCache; import com.r1soft.backup.server.cache.SigarDiskCacheEntry; import com.r1soft.backup.server.cache.VolumeCache; import com.r1soft.backup.server.cache.VolumeCacheEntry; import com.r1soft.backup.server.disksafe.metadata.DiskSafeManager; import com.r1soft.backup.server.disksafe.metadata.MetaDataException; import com.r1soft.backup.server.disksafe.metadata.entity.DiskSafeMetaData; import com.r1soft.backup.server.disksafe.metadata.entity.RecoveryPoint; import com.r1soft.backup.server.event.AgentEvent; import com.r1soft.backup.server.event.ArchivePointActionEvent; import com.r1soft.backup.server.event.ArchivePointEvent; import com.r1soft.backup.server.event.DiskSafeCacheEvent; import com.r1soft.backup.server.event.EventListener; import com.r1soft.backup.server.event.GroupEvent; import com.r1soft.backup.server.event.LicensingEvent; import com.r1soft.backup.server.event.PolicyEvent; import com.r1soft.backup.server.event.RecoveryPointEvent; import com.r1soft.backup.server.event.StatsEvent; import com.r1soft.backup.server.event.TaskHistoryEvent; import com.r1soft.backup.server.event.UserEvent; import com.r1soft.backup.server.event.VolumeCacheEvent; import com.r1soft.backup.server.event.VolumeEvent; import com.r1soft.backup.server.facade.CDPServerFacade; import com.r1soft.backup.server.facade.LicenseFacade; import com.r1soft.backup.server.facade.RecoveryPointInfo; import com.r1soft.backup.server.facade.ServerProperties; import com.r1soft.backup.server.facade.TaskFacade; import com.r1soft.backup.server.facade.TaskSchedulerInfoSpec.TaskPoolType; import com.r1soft.backup.server.i18n.I18NStrings; import com.r1soft.backup.server.om.entity.EntityManagerFacade; import com.r1soft.backup.server.om.entity.TaskState; import com.r1soft.backup.server.om.pojo.DiskSafePointer; import com.r1soft.backup.server.om.pojo.MergedRecoveryPointID; import com.r1soft.backup.server.om.pojo.TaskExecutionContext; import com.r1soft.backup.server.om.pojo.Volume; import com.r1soft.backup.server.om.query.QueryComparisonOperator; import com.r1soft.backup.server.om.query.QueryParameter; import com.r1soft.backup.server.om.uuid.UUID; import com.r1soft.backup.server.task.BaseDiskSafeTask; import com.r1soft.backup.server.task.DataProtectionPolicyTask; import com.r1soft.backup.server.task.MergeRecoveryPointsTask; import com.r1soft.backup.server.web.agent.Controller.SelectableAgent; import com.r1soft.backup.server.web.charts.ChartUtil; import com.r1soft.backup.server.web.charts.DiskQuotaInfo; import com.r1soft.backup.server.web.charts.IZkossImageChart; import com.r1soft.backup.server.web.charts.TaskGauge; import com.r1soft.backup.server.web.charts.TransferRateChart; import com.r1soft.backup.server.web.component.RingChart; import com.r1soft.backup.server.web.disksafe.Controller.SelectableDiskSafeCacheEntry; import com.r1soft.backup.server.web.group.Controller.SelectableGroup; import com.r1soft.backup.server.web.policy.Controller.SelectableDPPInfo; import com.r1soft.backup.server.web.taskhistory.Controller.SelectableTaskExecutionContext; import com.r1soft.backup.server.web.user.Controller.SelectableUser; import com.r1soft.backup.server.web.volume.Controller.SelectableVolume; public class GlobalUpdater implements DesktopInit, DesktopCleanup, WebAppCleanup { protected static final mazz.i18n.Logger logger = mazz.i18n.LoggerFactory.getLogger(GlobalUpdater.class); protected static final org.apache.log4j.Logger debug = org.apache.log4j.Logger.getLogger(GlobalUpdater.class); private static GlobalUpdaterThread updaterThread = null; private static Map<String, EventQueue> applicationEventQueues = null; private static List<Desktop> activeDesktops = new ArrayList<Desktop>(); private static Map<String, DiskQuotaInfo> diskQuotaInfos = new ConcurrentHashMap<String, DiskQuotaInfo>(); private static TransferRateChart networkBandwidthChart = null; private static Map<TaskPoolType, TaskGauge> taskGauges = new HashMap<TaskPoolType, TaskGauge>(); private static final Map<String, RingChart> storageCharts = Collections .synchronizedMap(new HashMap<String, RingChart>()); private static final Map<UUID, RingChart> volumeCharts = Collections .synchronizedMap(new HashMap<UUID, RingChart>()); private static boolean shutdown = false; protected static final List<String> excludePaths = new ArrayList<String>(); static { excludePaths.add("login.zul"); ChartUtil.initLicense(); } public GlobalUpdater() { // default constructor } protected static boolean isExcluded(Desktop desktop) { for (String exclude : excludePaths) { if (desktop.getRequestPath().contains(exclude)) return true; } return false; } public static EventQueue lookupEventQueue(String eventQueue) { EventQueue queue = applicationEventQueues.get(eventQueue); if (queue != null) return queue; queue = EventQueues.lookup(eventQueue, EventQueues.APPLICATION, true); applicationEventQueues.put(eventQueue, queue); return queue; } public static void subscribeToEventQueue(String eventQueue, org.zkoss.zk.ui.event.EventListener eventListener) { lookupEventQueue(eventQueue).subscribe(eventListener); } public static void unsubscribeFromEventQueue(String eventQueue, org.zkoss.zk.ui.event.EventListener eventListener) { lookupEventQueue(eventQueue).unsubscribe(eventListener); } public static List<DiskQuotaInfo> getDiskQuotaInfos() { return new ArrayList<DiskQuotaInfo>(diskQuotaInfos.values()); } /** * * @return will return null if chart is not ready */ public static TransferRateChart getNetworkBandwidthChart() { return networkBandwidthChart; } public static Component getStorageChart(String mountPoint) { Component chart = null; if (storageCharts.containsKey(mountPoint)) { byte[] chartData = storageCharts.get(mountPoint).getContent().getByteData(); try { ByteArrayInputStream bais = new ByteArrayInputStream(chartData); Image chartImg = new Image(); chartImg.setContent(ImageIO.read(bais)); chart = chartImg; } catch (IOException ex) { logger.error(ex, I18NStrings.ERROR_LOADING_CHART_CONTENT_FOR_MOUNT_POINT_X, mountPoint); } } if (chart == null) { Space space = new Space(); space.setHeight("48"); space.setWidth("48"); chart = space; } return chart; } public static RingChart getVolumeChart(UUID volumeId) { return volumeCharts.get(volumeId); } /** * * @return will return null if chart is not ready */ public static Map<TaskPoolType, TaskGauge> getTaskGauges() { return taskGauges; } private static synchronized void initEventQueues() { if (applicationEventQueues != null) return; applicationEventQueues = Collections.synchronizedMap(new HashMap<String, EventQueue>()); applicationEventQueues.put(EventConstants.NATIVE_DISK_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.NATIVE_DISK_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.VOLUME_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.VOLUME_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.DISK_SAFE_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.DISK_SAFE_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.TASK_HISTORY_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.TASK_HISTORY_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.SERVER_INFO_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.SERVER_INFO_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.TASK_SCHEDULER_INFO_EVENT_QUEUE_NAME, EventQueues .lookup(EventConstants.TASK_SCHEDULER_INFO_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.RECOVERY_POINT_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.RECOVERY_POINT_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.AGENT_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.AGENT_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.ARCHIVE_POINT_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.ARCHIVE_POINT_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.ARCHIVE_POINT_ACTION_EVENT_QUEUE_NAME, EventQueues .lookup(EventConstants.ARCHIVE_POINT_ACTION_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.LICENSING_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.LICENSING_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.USER_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.USER_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.GROUP_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.GROUP_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.POLICY_EVENT_QUEUE_NAME, EventQueues.lookup(EventConstants.POLICY_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.ZKOSS_IMAGE_CHART_EVENT_QUEUE_NAME, EventQueues .lookup(EventConstants.ZKOSS_IMAGE_CHART_EVENT_QUEUE_NAME, EventQueues.APPLICATION, true)); applicationEventQueues.put(EventConstants.STATS_EVENT_QUEUE, EventQueues.lookup(EventConstants.STATS_EVENT_QUEUE, EventQueues.APPLICATION, true)); // TODO: Simplify this shit by just using one EventConstants interface com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.DISK_SAFE_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof DiskSafeCacheEvent)) return; if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.DISK_SAFE_CACHE_ENTRY_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.DISK_SAFE_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.DISK_SAFE_UPDATE_EVENT_NAME, null, new SelectableDiskSafeCacheEntry( ((DiskSafeCacheEvent) event).getDiskSafeCacheEntry()))); } else if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.DISK_SAFE_CACHE_ENTRY_REMOVE_EVENT)) { applicationEventQueues.get(EventConstants.DISK_SAFE_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.DISK_SAFE_DELETE_EVENT_NAME, null, new SelectableDiskSafeCacheEntry( ((DiskSafeCacheEvent) event).getDiskSafeCacheEntry()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.VOLUME_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof VolumeEvent)) return; if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.VOLUME_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.VOLUME_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.VOLUME_CREATE_EVENT_NAME, null, new SelectableVolume(((VolumeEvent) event).getVolume()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.VOLUME_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.VOLUME_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.VOLUME_UPDATE_EVENT_NAME, null, new SelectableVolume(((VolumeEvent) event).getVolume()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.VOLUME_DELETE_EVENT)) { applicationEventQueues.get(EventConstants.VOLUME_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.VOLUME_DELETE_EVENT_NAME, null, new SelectableVolume(((VolumeEvent) event).getVolume()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.VOLUME_REMOVE_EVENT)) { applicationEventQueues.get(EventConstants.VOLUME_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.VOLUME_DELETE_EVENT_NAME, null, new SelectableVolume(((VolumeEvent) event).getVolume()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.VOLUME_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof VolumeCacheEvent)) return; if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.VOLUME_CACHE_ENTRY_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.VOLUME_EVENT_QUEUE_NAME).publish(new Event( EventConstants.VOLUME_UPDATE_EVENT_NAME, null, new SelectableVolume(((VolumeCacheEvent) event).getVolumeCacheEntry()))); } else if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.VOLUME_CACHE_ENTRY_REMOVE_EVENT)) { applicationEventQueues.get(EventConstants.VOLUME_EVENT_QUEUE_NAME).publish(new Event( EventConstants.VOLUME_DELETE_EVENT_NAME, null, new SelectableVolume(((VolumeCacheEvent) event).getVolumeCacheEntry()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.RECOVERY_POINT_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof RecoveryPointEvent)) return; if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.RECOVERY_POINT_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.RECOVERY_POINT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.RECOVERY_POINT_CREATE_EVENT_NAME, null, ((RecoveryPointEvent) event).getRecoveryPointInfo())); } else if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.RECOVERY_POINT_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.RECOVERY_POINT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.RECOVERY_POINT_UPDATE_EVENT_NAME, null, ((RecoveryPointEvent) event).getRecoveryPointInfo())); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.AGENT_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof AgentEvent)) return; if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.AGENT_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.AGENT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.AGENT_CREATE_EVENT_NAME, null, new SelectableAgent(((AgentEvent) event).getAgent()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.AGENT_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.AGENT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.AGENT_UPDATE_EVENT_NAME, null, new SelectableAgent(((AgentEvent) event).getAgent()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.AGENT_DELETE_EVENT)) { applicationEventQueues.get(EventConstants.AGENT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.AGENT_DELETE_EVENT_NAME, null, new SelectableAgent(((AgentEvent) event).getAgent()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.ARCHIVE_POINT_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof ArchivePointEvent)) return; if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.ARCHIVE_POINT_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.ARCHIVE_POINT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.ARCHIVE_POINT_CREATE_EVENT_NAME, null, ((ArchivePointEvent) event).getArchivePointInfo())); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.ARCHIVE_POINT_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.ARCHIVE_POINT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.ARCHIVE_POINT_UPDATE_EVENT_NAME, null, ((ArchivePointEvent) event).getArchivePointInfo())); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.ARCHIVE_POINT_ACTION_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof ArchivePointActionEvent)) return; if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.ARCHIVE_POINT_ACTION_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.ARCHIVE_POINT_ACTION_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.ARCHIVE_POINT_ACTION_CREATE_EVENT_NAME, null, ((ArchivePointActionEvent) event).getArchivePointAction())); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.LICENSING_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof LicensingEvent)) return; if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.LICENSING_INFO_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.LICENSING_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.LICENSING_INFO_UPDATE_EVENT_NAME, null, ((LicensingEvent) event).getLicenseInfoSpec())); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.TASK_HISTORY_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof TaskHistoryEvent)) return; if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.TASK_HISTORY_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.TASK_HISTORY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.TASK_HISTORY_CREATE_EVENT_NAME, null, new SelectableTaskExecutionContext( ((TaskHistoryEvent) event).getTaskExecutionContext()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.TASK_HISTORY_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.TASK_HISTORY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.TASK_HISTORY_UPDATE_EVENT_NAME, null, new SelectableTaskExecutionContext( ((TaskHistoryEvent) event).getTaskExecutionContext()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.TASK_HISTORY_DELETE_EVENT)) { applicationEventQueues.get(EventConstants.TASK_HISTORY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.TASK_HISTORY_DELETE_EVENT_NAME, null, new SelectableTaskExecutionContext( ((TaskHistoryEvent) event).getTaskExecutionContext()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.USER_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof UserEvent)) return; if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.USER_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.USER_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.USER_CREATE_EVENT_NAME, null, new SelectableUser(((UserEvent) event).getUser()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.USER_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.USER_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.USER_UPDATE_EVENT_NAME, null, new SelectableUser(((UserEvent) event).getUser()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.USER_DELETE_EVENT)) { applicationEventQueues.get(EventConstants.USER_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.USER_DELETE_EVENT_NAME, null, new SelectableUser(((UserEvent) event).getUser()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.GROUP_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof GroupEvent)) return; if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.GROUP_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.GROUP_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.GROUP_CREATE_EVENT_NAME, null, new SelectableGroup(((GroupEvent) event).getGroup()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.GROUP_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.GROUP_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.GROUP_UPDATE_EVENT_NAME, null, new SelectableGroup(((GroupEvent) event).getGroup()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.GROUP_DELETE_EVENT)) { applicationEventQueues.get(EventConstants.GROUP_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.GROUP_DELETE_EVENT_NAME, null, new SelectableGroup(((GroupEvent) event).getGroup()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.POLICY_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown) return; if (!(event instanceof PolicyEvent)) return; if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.POLICY_CREATE_EVENT)) { applicationEventQueues.get(EventConstants.POLICY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.POLICY_CREATE_EVENT_NAME, null, new SelectableDPPInfo(((PolicyEvent) event).getDPPInfo()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.POLICY_UPDATE_EVENT)) { applicationEventQueues.get(EventConstants.POLICY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.POLICY_UPDATE_EVENT_NAME, null, new SelectableDPPInfo(((PolicyEvent) event).getDPPInfo()))); } else if (event.getName() .equals(com.r1soft.backup.server.event.EventConstants.POLICY_DELETE_EVENT)) { applicationEventQueues.get(EventConstants.POLICY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.POLICY_DELETE_EVENT_NAME, null, new SelectableDPPInfo(((PolicyEvent) event).getDPPInfo()))); } } }); com.r1soft.backup.server.event.EventQueues .lookup(com.r1soft.backup.server.event.EventConstants.STATS_EVENT_QUEUE, true) .subscribe(new EventListener() { @Override public void onEvent(com.r1soft.backup.server.event.Event event) { if (shutdown || !(event instanceof StatsEvent)) return; if (event.getName().equals( com.r1soft.backup.server.event.EventConstants.RESTORE_STATS_UPDATED_EVENT)) { lookupEventQueue(EventConstants.STATS_EVENT_QUEUE).publish( new Event(EventConstants.RESTORE_STATS_UPDATED_EVENT, null, event.getData())); } } }); } private static synchronized void createThreadSingleton() { if (updaterThread != null) return; updaterThread = new GlobalUpdaterThread(); updaterThread.start(); } private static void stopThreadSingleton() { if (updaterThread == null) return; updaterThread.shutdownUpdater(); } private static void start() { shutdown = false; initEventQueues(); createThreadSingleton(); } private static void shutdown() { shutdown = true; stopThreadSingleton(); applicationEventQueues = null; } @Override public void init(Desktop desktop, Object req) throws Exception { GlobalUpdater.start(); synchronized (activeDesktops) { if (!isExcluded(desktop)) { activeDesktops.add(desktop); } } } @Override public void cleanup(WebApp webapp) throws Exception { GlobalUpdater.shutdown(); } @Override public void cleanup(Desktop desktop) throws Exception { synchronized (activeDesktops) { activeDesktops.remove(desktop); } } protected static class GlobalUpdaterThread extends Thread { protected static final long SLEEP_MILLIS = 5000L; protected static Long lastExecutionCheck = System.currentTimeMillis(); protected static final QueryParameter<List<TaskState>> runningStatesParam; static { List<TaskState> runningStates = new ArrayList<TaskState>(); runningStates.add(TaskState.QUEUED); runningStates.add(TaskState.RUNNING); runningStatesParam = new QueryParameter<List<TaskState>>("state", "state", runningStates, QueryComparisonOperator.IN); } // FIXME this should just store a list of context IDs as storing the actial TECs can easily take 10 MB+ protected List<TaskExecutionContext> runningContexts = null; protected boolean shutdown = false; public GlobalUpdaterThread() { // default constructor } public void shutdownUpdater() { synchronized (this) { if (!shutdown) { shutdown = true; this.notify(); networkBandwidthChart.shutdownUpdater(); } } } @Override public void run() { this.setName(this.getClass().getSimpleName()); long start = System.currentTimeMillis(); // Keep looping for (;;) { List<String> activePaths = null; synchronized (this) { if (shutdown) break; } start = System.currentTimeMillis(); synchronized (activeDesktops) { if (!activeDesktops.isEmpty()) { activePaths = new ArrayList<String>(activeDesktops.size()); for (Desktop desktop : activeDesktops) { if (desktop.getRequestPath() != null) activePaths.add(desktop.getRequestPath()); } } } try { if (activePaths != null) doUpdates(activePaths); } catch (Throwable ex) { logger.error(ex, I18NStrings.GLOBAL_UPDATER_FAILED_TO_UPDATE); } synchronized (this) { if (shutdown) break; long sleep = SLEEP_MILLIS - (System.currentTimeMillis() - start); try { if (sleep > 0) this.wait(sleep); } catch (InterruptedException ex) { // do nothing } if (shutdown) break; } } } private void doUpdates(List<String> activePaths) { if (activePaths.isEmpty()) return; boolean updateServerInfo = false, updateTaskSchedulerInfo = false, updateDiskQuotas = false, updateVolumes = false, updateDiskSafes = false, updateTasks = false, updateRecoveryPoints = false, updateLicenceInfo = false, updateCharts = false; for (String reqPath : activePaths) { // Someone's on the dashboard if (reqPath.equals("/") || reqPath.equals("/index.zul") || reqPath.contains("/Dashboard")) { updateDiskQuotas = true; updateTasks = true; updateCharts = true; } // Someone's looking at agents else if (reqPath.contains("/Agent")) { updateTasks = true; } // Someone's looking at control panel user list else if (reqPath.contains("/CP")) { updateTasks = true; } // Someone's looking at disk safes else if (reqPath.contains("/DiskSafe")) { updateDiskSafes = true; updateTasks = true; } // Someone's looking at volumes else if (reqPath.contains("/Volume")) { updateVolumes = true; } // Someone's looking at task history else if (reqPath.contains("/TaskHistory")) { updateTasks = true; } // Someone's looking at configuration else if (reqPath.contains("/Configuration")) { updateServerInfo = true; updateTaskSchedulerInfo = true; updateLicenceInfo = true; } // Someone's looking at Policies else if (reqPath.contains("/Policy")) { updateTasks = true; } // Someone's looking at recovery points else if (reqPath.contains("/RecoveryPoints")) { updateRecoveryPoints = true; } // Someone's looking at all screens we're updating, no point in checking more... if (updateServerInfo && updateDiskQuotas && updateVolumes && updateDiskSafes && updateTasks && updateRecoveryPoints && updateLicenceInfo && updateCharts) break; } /* * Don't let one failed update spoil all */ try { if (updateServerInfo) postServerInfoUpdates(); } catch (Throwable ex) { logger.error(ex, I18NStrings.GLOBAL_UPDATER_FAILED_TO_UPDATE); } try { if (updateTaskSchedulerInfo) postSchedulerInfoUpdates(); } catch (Throwable ex) { logger.error(ex, I18NStrings.GLOBAL_UPDATER_FAILED_TO_UPDATE); } try { if (updateDiskQuotas) postDiskQuotaUpdates(); } catch (Throwable ex) { logger.error(ex, I18NStrings.GLOBAL_UPDATER_FAILED_TO_UPDATE); } try { if (updateTasks || updateRecoveryPoints) postTaskUpdates(); } catch (Throwable ex) { logger.error(ex, I18NStrings.GLOBAL_UPDATER_FAILED_TO_UPDATE); } try { if (updateLicenceInfo) postLicenseInfoUpdates(); } catch (Throwable ex) { logger.error(ex, I18NStrings.GLOBAL_UPDATER_FAILED_TO_UPDATE); } try { if (updateCharts) updateCharts(); } catch (Throwable ex) { logger.error(ex, I18NStrings.GLOBAL_UPDATER_FAILED_TO_UPDATE); } } private void postSchedulerInfoUpdates() { applicationEventQueues.get(EventConstants.TASK_SCHEDULER_INFO_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.TASK_SCHEDULER_INFO_UPDATE_EVENT_NAME, null, CDPServerFacade.getTaskSchedulerInfoSpec())); } private void postServerInfoUpdates() { applicationEventQueues.get(EventConstants.SERVER_INFO_EVENT_QUEUE_NAME).publish(new Event( EventConstants.SERVER_INFO_UPDATE_EVENT_NAME, null, CDPServerFacade.getServerInfoSpec())); } private void postLicenseInfoUpdates() { applicationEventQueues.get(EventConstants.LICENSING_EVENT_QUEUE_NAME).publish(new Event( EventConstants.LICENSING_INFO_UPDATE_EVENT_NAME, null, LicenseFacade.getLicenseInfoSpec())); } private void postDiskQuotaUpdates() { ServerProperties serverProps; try { serverProps = CDPServerFacade.getServerProperties(); } catch (IOException ex) { ex.printStackTrace(); logger.error(ex, I18NStrings.GLOBAL_UPDATER_GET_SERVER_PROPERTIES_FAILED); return; } Integer hardQuota = serverProps.getHardQuota(); Integer softQuota = serverProps.getSoftQuota(); List<String> devicesOutOfScope = new ArrayList<String>(diskQuotaInfos.keySet()); for (String storageDiskPath : CDPServerFacade.getStorageDiskPaths()) { SigarDiskCacheEntry cacheEntry = (SigarDiskCacheEntry) SigarDiskCache.getInstance() .getCacheEntry(storageDiskPath); if (cacheEntry == null || cacheEntry.getDevice() == null) continue; if (!diskQuotaInfos.containsKey(cacheEntry.getDevice().toLowerCase())) { DiskQuotaInfo dqi = new DiskQuotaInfo(cacheEntry, softQuota, hardQuota); dqi.initChart(); diskQuotaInfos.put(dqi.getDeviceName().toLowerCase(), dqi); } else { DiskQuotaInfo dqi = diskQuotaInfos.get(cacheEntry.getDevice().toLowerCase()); devicesOutOfScope.remove(dqi.getDeviceName().toLowerCase()); // FIXME consider that update should return a boolean if anything changed and if it didn't we do not need to fire event // or perhaps bytes of disk are likely always changing... so probably ok to update always dqi.update(cacheEntry, softQuota, hardQuota); dqi.updateChart(); } } // FIXME we need to fire an update event for this for (String deviceOutOfScope : devicesOutOfScope) { diskQuotaInfos.remove(deviceOutOfScope); } List<DiskQuotaInfo> updates = new ArrayList<DiskQuotaInfo>(diskQuotaInfos.values()); if (!updates.isEmpty()) { applicationEventQueues.get(EventConstants.NATIVE_DISK_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.NATIVE_DISKS_UPDATE_EVENT_NAME, null, updates)); } } private void initRunningContexts() { if (runningContexts == null) { runningContexts = new ArrayList<TaskExecutionContext>(); runningContexts.addAll(EntityManagerFacade.findPOJOByQueryParameter(TaskExecutionContext.class, runningStatesParam)); } } private void postTaskUpdates() { initRunningContexts(); List<SelectableTaskExecutionContext> updates = new ArrayList<SelectableTaskExecutionContext>(); List<SelectableTaskExecutionContext> created = new ArrayList<SelectableTaskExecutionContext>(); List<TaskExecutionContext> remove = new ArrayList<TaskExecutionContext>(); for (TaskExecutionContext ctx : runningContexts) { TaskExecutionContext updatedCTX = TaskFacade.getUpdatedTaskExecutionContext(ctx); if (updatedCTX != null) { updates.add(new SelectableTaskExecutionContext(updatedCTX)); if (updatedCTX.getState() != TaskState.RUNNING && updatedCTX.getState() != TaskState.QUEUED) remove.add(updatedCTX); } else { remove.add(ctx); } } if (!remove.isEmpty()) runningContexts.removeAll(remove); List<TaskExecutionContext> allRunning = EntityManagerFacade .findPOJOByQueryParameter(TaskExecutionContext.class, runningStatesParam); for (TaskExecutionContext ctx : allRunning) { if (!runningContexts.contains(ctx)) { runningContexts.add(ctx); created.add(new SelectableTaskExecutionContext(ctx)); } } Long currentExecutionCheck = System.currentTimeMillis(); QueryParameter<Date> executionTimeParam = new QueryParameter<Date>("executionTime", "executionTime", new Date(lastExecutionCheck), QueryComparisonOperator.GREATER_THAN_OR_EQUAL); lastExecutionCheck = currentExecutionCheck; List<TaskExecutionContext> recentlyCreated = EntityManagerFacade .findPOJOByQueryParameter(TaskExecutionContext.class, executionTimeParam); for (TaskExecutionContext ctx : recentlyCreated) { if (!ctx.getState().equals(TaskState.QUEUED) && !ctx.getState().equals(TaskState.RUNNING)) { if (!runningContexts.contains(ctx)) { runningContexts.add(ctx); created.add(new SelectableTaskExecutionContext(ctx)); } updates.add(new SelectableTaskExecutionContext(ctx)); } } List<SelectableTaskExecutionContext> all = new ArrayList<SelectableTaskExecutionContext>(); if (!created.isEmpty()) { applicationEventQueues.get(EventConstants.TASK_HISTORY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.TASKS_CREATE_EVENT_NAME, null, created)); all.addAll(created); } if (!updates.isEmpty()) { applicationEventQueues.get(EventConstants.TASK_HISTORY_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.TASKS_UPDATE_EVENT_NAME, null, updates)); all.addAll(updates); } if (!all.isEmpty()) postRecoveryPointUpdates(all); } private void updateCharts() { //System.out.println("Start update charts: " + new Date()); List<IZkossImageChart> updates = new ArrayList<IZkossImageChart>(); /* * Update TransferRateChart */ if (networkBandwidthChart == null) { networkBandwidthChart = new TransferRateChart(); networkBandwidthChart.initChart(); } /* generate test values for chart RunningTaskStatsInfo runningTasksStatsInfo = new RunningTaskStatsInfo(); long avgBytesSecond = ( ((long)(Calendar.getInstance().get(Calendar.SECOND))) * 100000L ) + ( ((long)(Calendar.getInstance().get(Calendar.MINUTE))) * 1000000L ); runningTasksStatsInfo.setTotalBytesPerSecond(avgBytesSecond); runningTasksStatsInfo.setTotalReplicationBytesPerSecond((avgBytesSecond - ((long)(avgBytesSecond * 0.33)))); runningTasksStatsInfo.setTotalRestoreBytesPerSecond((long)(avgBytesSecond * 0.33)); // runningTasksStatsInfo.setTotalBytesPerSecond(avgBytesSecond); // runningTasksStatsInfo.setTotalReplicationBytesPerSecond(avgBytesSecond); // runningTasksStatsInfo.setTotalRestoreBytesPerSecond(0L); */ networkBandwidthChart.updateChart(); updates.add(networkBandwidthChart); /* * Update Task Gauges */ // TaskSchedulerInfoSpec taskSchedulerInfoSpec = CDPServerFacade.getTaskSchedulerInfoSpec(); // // for( TaskPoolType poolType : TaskPoolType.values() ) { // if( !taskGauges.containsKey(poolType) ) { // TaskGauge taskGauge = new TaskGauge(poolType); // taskGauge.initChart(); // taskGauges.put(poolType, taskGauge); // } // // TaskGauge taskGauge = taskGauges.get(poolType); // taskGauge.updateChart(taskSchedulerInfoSpec.getTaskPoolSpec(poolType)); // updates.add(taskGauge); // } try { ServerProperties serverProps = CDPServerFacade.getServerProperties(); Integer hardQuota = serverProps.getHardQuota(); Integer softQuota = serverProps.getSoftQuota(); for (SigarDiskCacheEntry cacheEntry : SigarDiskCache.getInstance().getCacheEntries()) { Double fullPercentage = cacheEntry.getFullPercentage(); RingChart existingChart = storageCharts.get(cacheEntry.getMountPoint()); if (existingChart == null) { RingChart ringChart = new RingChart(fullPercentage, softQuota.doubleValue(), hardQuota.doubleValue()); storageCharts.put(cacheEntry.getMountPoint(), ringChart); } else { EqualsBuilder eb = new EqualsBuilder() .append(existingChart.getPercentFull(), fullPercentage) .append(existingChart.getWarningLimit(), softQuota) .append(existingChart.getErrorLimit(), hardQuota); if (!eb.isEquals()) { RingChart ringChart = new RingChart(fullPercentage, softQuota.doubleValue(), hardQuota.doubleValue()); storageCharts.put(cacheEntry.getMountPoint(), ringChart); } } } } catch (IOException e) { logger.error(e, I18NStrings.COULD_NOT_LOAD_SERVER_PROPERTIES); } for (Entry<Volume, CacheEntry<Volume>> entry : VolumeCache.getInstance().getCacheMap().entrySet()) { VolumeCacheEntry cacheEntry = (VolumeCacheEntry) entry.getValue(); Double hardQuota = entry.getKey().getHardQuota(); Double softQuota = entry.getKey().getSoftQuota(); Long usageBytes = cacheEntry.getOnDiskSize(); Double fullPercentage = hardQuota > 0 && usageBytes != null ? usageBytes.doubleValue() / hardQuota : 0; RingChart existingChart = volumeCharts.get(entry.getKey().getId()); if (existingChart == null) { RingChart ringChart = new RingChart(fullPercentage, softQuota, hardQuota); volumeCharts.put(entry.getKey().getId(), ringChart); } else { EqualsBuilder eb = new EqualsBuilder().append(existingChart.getPercentFull(), fullPercentage) .append(existingChart.getWarningLimit(), softQuota) .append(existingChart.getErrorLimit(), hardQuota); if (!eb.isEquals()) { RingChart ringChart = new RingChart(fullPercentage, softQuota.doubleValue(), hardQuota.doubleValue()); volumeCharts.put(entry.getKey().getId(), ringChart); } } } applicationEventQueues.get(EventConstants.ZKOSS_IMAGE_CHART_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.ZKOSS_IMAGE_CHARTS_UPDATE_EVENT, null, updates)); //System.out.println("Finish update charts: " + new Date()); } private void postRecoveryPointUpdates(List<SelectableTaskExecutionContext> updates) { Map<UUID, List<MergedRecoveryPointID>> mergeMap = new HashMap<UUID, List<MergedRecoveryPointID>>(); for (SelectableTaskExecutionContext ctx : updates) { if (ctx.getCompletionTime() != null && (ctx.getTaskClass().equals(DataProtectionPolicyTask.class) || ctx.getTaskClass().equals(MergeRecoveryPointsTask.class))) { List<MergedRecoveryPointID> mrpIDs = TaskFacade.getMergedRecoveryPointsPrimaryKeys(ctx.getId()); if (mrpIDs.isEmpty()) continue; UUID pointerID = (UUID) ctx.getContextData(BaseDiskSafeTask.DISK_SAFE_ID_KEY); if (!mergeMap.containsKey(pointerID)) mergeMap.put(pointerID, new ArrayList<MergedRecoveryPointID>()); mergeMap.get(pointerID).addAll(mrpIDs); } } if (!mergeMap.keySet().isEmpty()) { List<RecoveryPointInfo> rpUpdates = new ArrayList<RecoveryPointInfo>(); for (Entry<UUID, List<MergedRecoveryPointID>> mergeEntry : mergeMap.entrySet()) { DiskSafePointer pointer = EntityManagerFacade.findPOJO(DiskSafePointer.class, mergeEntry.getKey()); if (pointer == null || !pointer.isOpen()) continue; List<MergedRecoveryPointID> mrpIDs = mergeEntry.getValue(); DiskSafeMetaData dsmd = null; try { dsmd = DiskSafeManager.getInstance().openDiskSafe(pointer.getDiskSafeFile()); for (MergedRecoveryPointID mrpID : mrpIDs) { RecoveryPoint rp = dsmd.getRecoveryPoint(mrpID.getRecoveryPointID()); rpUpdates.add(new RecoveryPointInfo(pointer.getId(), rp)); } } catch (MetaDataException e) { logger.error(I18NStrings.COULD_NOT_LOAD_DISK_SAFE, pointer.getDescription()); continue; } finally { if (dsmd != null) DiskSafeManager.getInstance().returnDiskSafe(pointer.getDiskSafeFile(), dsmd); } } if (!rpUpdates.isEmpty()) { applicationEventQueues.get(EventConstants.RECOVERY_POINT_EVENT_QUEUE_NAME) .publish(new Event(EventConstants.RECOVERY_POINTS_UPDATE_EVENT_NAME, null, rpUpdates)); } } } } }