001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.store.kahadb.scheduler.legacy; 018 019import java.io.File; 020import java.io.IOException; 021import java.util.List; 022import java.util.Set; 023 024import org.apache.activemq.store.kahadb.data.KahaAddScheduledJobCommand; 025import org.apache.activemq.store.kahadb.scheduler.JobSchedulerStoreImpl; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029/** 030 * Used to upgrade a Legacy Job Scheduler store to the latest version this class 031 * loads a found legacy scheduler store and generates new add commands for all 032 * jobs currently in the store. 033 */ 034public class LegacyStoreReplayer { 035 036 static final Logger LOG = LoggerFactory.getLogger(LegacyStoreReplayer.class); 037 038 private LegacyJobSchedulerStoreImpl store; 039 private final File legacyStoreDirectory; 040 041 /** 042 * Creates a new Legacy Store Replayer with the given target store 043 * @param directory 044 */ 045 public LegacyStoreReplayer(File directory) { 046 this.legacyStoreDirectory = directory; 047 } 048 049 /** 050 * Loads the legacy store and prepares it for replay into a newer Store instance. 051 * 052 * @throws IOException if an error occurs while reading in the legacy store. 053 */ 054 public void load() throws IOException { 055 056 store = new LegacyJobSchedulerStoreImpl(); 057 store.setDirectory(legacyStoreDirectory); 058 store.setFailIfDatabaseIsLocked(true); 059 060 try { 061 store.start(); 062 } catch (IOException ioe) { 063 LOG.warn("Legacy store load failed: ", ioe); 064 throw ioe; 065 } catch (Exception e) { 066 LOG.warn("Legacy store load failed: ", e); 067 throw new IOException(e); 068 } 069 } 070 071 /** 072 * Unloads a previously loaded legacy store to release any resources associated with it. 073 * 074 * Once a store is unloaded it cannot be replayed again until it has been reloaded. 075 * @throws IOException 076 */ 077 public void unload() throws IOException { 078 079 if (store != null) { 080 try { 081 store.stop(); 082 } catch (Exception e) { 083 LOG.warn("Legacy store unload failed: ", e); 084 throw new IOException(e); 085 } finally { 086 store = null; 087 } 088 } 089 } 090 091 /** 092 * Performs a replay of scheduled jobs into the target JobSchedulerStore. 093 * 094 * @param targetStore 095 * The JobSchedulerStore that will receive the replay events from the legacy store. 096 * 097 * @throws IOException if an error occurs during replay of the legacy store. 098 */ 099 public void startReplay(JobSchedulerStoreImpl targetStore) throws IOException { 100 checkLoaded(); 101 102 if (targetStore == null) { 103 throw new IOException("Cannot replay to a null store"); 104 } 105 106 try { 107 Set<String> schedulers = store.getJobSchedulerNames(); 108 if (!schedulers.isEmpty()) { 109 110 for (String name : schedulers) { 111 LegacyJobSchedulerImpl scheduler = store.getJobScheduler(name); 112 LOG.info("Replay of legacy store {} starting.", name); 113 replayScheduler(scheduler, targetStore); 114 } 115 } 116 117 LOG.info("Replay of legacy store complate."); 118 } catch (IOException ioe) { 119 LOG.warn("Failed during replay of legacy store: ", ioe); 120 throw ioe; 121 } catch (Exception e) { 122 LOG.warn("Failed during replay of legacy store: ", e); 123 throw new IOException(e); 124 } 125 } 126 127 private final void replayScheduler(LegacyJobSchedulerImpl legacy, JobSchedulerStoreImpl target) throws Exception { 128 List<LegacyJobImpl> jobs = legacy.getAllJobs(); 129 130 String schedulerName = legacy.getName(); 131 132 for (LegacyJobImpl job : jobs) { 133 LOG.trace("Storing job from legacy store to new store: {}", job); 134 KahaAddScheduledJobCommand newJob = new KahaAddScheduledJobCommand(); 135 newJob.setScheduler(schedulerName); 136 newJob.setJobId(job.getJobId()); 137 newJob.setStartTime(job.getStartTime()); 138 newJob.setCronEntry(job.getCronEntry()); 139 newJob.setDelay(job.getDelay()); 140 newJob.setPeriod(job.getPeriod()); 141 newJob.setRepeat(job.getRepeat()); 142 newJob.setNextExecutionTime(job.getNextExecutionTime()); 143 newJob.setPayload(job.getPayload()); 144 145 target.store(newJob); 146 } 147 } 148 149 private final void checkLoaded() throws IOException { 150 if (this.store == null) { 151 throw new IOException("Cannot replay until legacy store is loaded."); 152 } 153 } 154}