/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.ext.backup;
import org.exoplatform.services.jcr.ext.backup.impl.BackupMessagesLog;
import org.exoplatform.services.jcr.ext.backup.impl.BackupScheduler;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import java.io.File;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Created by The eXo Platform SAS
*
* Date: 05.12.2007
*
* @author <a href="mailto:peter.nedonosko@exoplatform.com.ua">Peter Nedonosko</a>
* @version $Id: TestBackupScheduler.java 760 2008-02-07 15:08:07Z pnedonosko $
*/
public class TestBackupScheduler extends AbstractBackupTestCase
{
private static final Log log = ExoLogger.getLogger("exo.jcr.component.ext.TestBackupScheduler");
protected ExtendedBackupManager getBackupManager()
{
return (ExtendedBackupManager) container.getComponentInstanceOfType(BackupManager.class);
}
class BackupWaiter implements BackupJobListener
{
private int jobId;
private int jobState;
final BackupMessagesLog errors = new BackupMessagesLog();
private CountDownLatch latch = null;
public void onError(BackupJob job, String message, Throwable error)
{
errors.addError(message, error);
}
public void onStateChanged(BackupJob job)
{
if (job.getId() == jobId && job.getState() == jobState && latch != null)
synchronized (latch)
{
latch.countDown(); // release waiter
}
}
/**
* @return true - ok, false - fail (tomeout expired)
* @throws InterruptedException
*/
boolean await(int jobId, int jobState, long timeout) throws InterruptedException
{
if (latch != null)
synchronized (latch)
{
latch = new CountDownLatch(1);
}
else
latch = new CountDownLatch(1);
this.jobId = jobId;
this.jobState = jobState;
this.errors.clear();
if (timeout > 0)
{
return this.latch.await(timeout, TimeUnit.MILLISECONDS);
}
else
{
this.latch.await();
return true;
}
}
}
/**
* 1. startTime only - run once forever
*/
public void testScheduler_p1() throws Exception
{
Date startTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
// full backup & incremental
File backDir = new File("target/backup/ws1.incr5");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_AND_INCREMENTAL);
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
scheduler.schedule(config, startTime, null, 0, 0);
// wait till backup will be started
while (Calendar.getInstance().getTime().before(startTime))
Thread.sleep(100);
Thread.sleep(100); // to know the full is started
BackupChain bch = backup.getCurrentBackups().iterator().next();
// wait till full backup will be stopped
while (bch.getFullBackupState() != BackupJob.FINISHED)
{
Thread.yield();
Thread.sleep(50);
}
// play with incremental
addContent(ws1TestRoot, 1, 20, 1);
scheduler.unschedule(config);
log.info("-----------------[ restore ]-------------------------");
// restore
restoreAndCheck("ws1back.incr5", "jdbcjcr6", bch.getLogFilePath(), backDir, 1, 20);
}
/**
* 2. startTime + incrementalPeriod - run once forever (with incremental backup)
*
*/
public void testScheduler_p2() throws Exception
{
Date startTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
// full backup & incremental
File backDir = new File("target/backup/ws1.incr6");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_AND_INCREMENTAL);
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
scheduler.schedule(config, startTime, null, 0, 10); // 10 sec incremental period
// wait till backup will be started
waitTime(startTime);
Thread.sleep(100); // to know the full is started
BackupChain bch = backup.getCurrentBackups().iterator().next();
// wait till full backup will be stopped
while (bch.getFullBackupState() != BackupJob.FINISHED)
{
Thread.yield();
Thread.sleep(50);
}
// play with incremental, each node will be added after 500ms
addContent(ws1TestRoot, 1, 20, 1100); // 20 * 1100 = 220000 ms = 22sec
scheduler.unschedule(config);
log.info("-----------------[ restore ]-------------------------");
// restore
restoreAndCheck("ws1back.incr6", "jdbcjcr7", bch.getLogFilePath(), backDir, 1, 20);
}
/**
* 3. startTime, endTime - run during a given period
*/
public void testScheduler_p3() throws Exception
{
Date startTime;
Date stopTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 40); // 30 sec to stop
stopTime = calendar.getTime();
// full backup & incremental forever (without log rotate)
File backDir = new File("target/backup/ws1.incr4");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_AND_INCREMENTAL);
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
scheduler.schedule(config, startTime, stopTime, 0, 0);
// wait till backup will be started
waitTime(startTime);
BackupChain bch = backup.getCurrentBackups().iterator().next();
// wait till full backup will be stopped
while (bch.getFullBackupState() != BackupJob.FINISHED)
{
Thread.yield();
Thread.sleep(50);
}
// play with incremental during 20 sec
addContent(ws1TestRoot, 1, 20, 1000);
// wait till backup will be stopped
waitTime(stopTime);
// wait a bit more
Thread.sleep(5000);
log.info("-----------------[ restore ]-------------------------");
// restore
restoreAndCheck("ws1back.incr4", "jdbcjcr8", bch.getLogFilePath(), backDir, 1, 20);
}
/**
* 4. startTime, endTime + incrementalPeriod - run during a given period (with incremental backup)
*/
public void testScheduler_p4() throws Exception
{
Date startTime;
Date stopTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 60); // 60 sec to stop
stopTime = calendar.getTime();
// full backup & incremental with log rotation 20sec
File backDir = new File("target/backup/ws1.incr3");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_AND_INCREMENTAL);
config.setIncrementalJobPeriod(20); // incrementalPeriod = 20 sec*
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
scheduler.schedule(config, startTime, stopTime, 0, 0); // incrementalPeriod = 20sec* (see
// before)
// wait till backup will be started
waitTime(startTime);
BackupChain bch = backup.getCurrentBackups().iterator().next();
// wait till full backup will be stopped
while (bch.getFullBackupState() != BackupJob.FINISHED)
{
Thread.yield();
Thread.sleep(50);
}
// play with incremental during 50 sec
addContent(ws1TestRoot, 1, 50, 1000);
// wait till backup will be stopped
waitTime(stopTime);
// wait a bit more
Thread.sleep(5000);
log.info("-----------------[ restore ]-------------------------");
// restore
restoreAndCheck("ws1back.incr3", "jdbcjcr9", bch.getLogFilePath(), backDir, 1, 50);
}
/**
* 5. startTime, endTime, chainPeriod - run periodic at given period
*
* test with timing - listener to know we have jobs stared in required time
*/
public void testScheduler_p5_timing() throws Exception
{
Date startTime;
Date stopTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 61);
stopTime = calendar.getTime();
// full backup each 20sec
File backDir = new File("target/backup/ws1.incr7");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_BACKUP_ONLY);;
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
BackupWaiter waiter = new BackupWaiter();
scheduler.schedule(config, startTime, stopTime, 20, 0, waiter); // 20 sec chain period
// wait till backup #1 will be started
assertTrue("Full backup #1 start expired", waiter.await(0, BackupJob.STARTING, 20500)); // 20.5sec
// to
// start
BackupChain bch1 = backup.getCurrentBackups().iterator().next();
log.info("full #1 " + bch1.getLogFilePath());
final int nodesCount = 20;
final int nodeTimeout = 500;
addContent(ws1TestRoot, 11, 10 + nodesCount, nodeTimeout);
// wait till full backup #2 will be started
assertTrue("Full backup #2 start expired", waiter.await(0, BackupJob.STARTING, 20500)); // 20.5sec
// for
// next
BackupChain bch2 = backup.getCurrentBackups().iterator().next();
log.info("full #2 " + bch2.getLogFilePath());
addContent(ws1TestRoot, 31, 30 + nodesCount, nodeTimeout);
// wait till full backup #3 will be started
assertTrue("Full backup #3 start expired", waiter.await(0, BackupJob.STARTING, 20500)); // 20.5sec
// for
// next
BackupChain bch3 = backup.getCurrentBackups().iterator().next();
log.info("full #3 " + bch3.getLogFilePath());
// wait till backup will be stopped
waitTime(stopTime);
Thread.sleep(20000); // wait 20 sec if next chain was started before the stop
log.info("-----------------[ restore #1 ]-------------------------");
restoreAndCheck("ws1back.incr7", "jdbcjcr10", bch1.getLogFilePath(), backDir, 1, 10);
log.info("-----------------[ restore #2 ]-------------------------");
restoreAndCheck("ws1back.incr8", "jdbcjcr11", bch2.getLogFilePath(), backDir, 11, 30);
log.info("-----------------[ restore #3 ]-------------------------");
restoreAndCheck("ws1back.incr9", "jdbcjcr12", bch3.getLogFilePath(), backDir, 31, 50);
}
// 6. startTime, endTime, chainPeriod + incrementalPeriod - run periodic at // given period (with
// incremental backup)
public void testScheduler_p6() throws Exception
{
Date startTime;
Date stopTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 55);
stopTime = calendar.getTime();
// full backup & incremental
File backDir = new File("target/backup/ws1.incr10");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_AND_INCREMENTAL);
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
scheduler.schedule(config, startTime, stopTime, 25, 10);
// wait till backup will be started
waitTime(startTime);
BackupChain bch = backup.getCurrentBackups().iterator().next();
// wait till full backup will be stopped
while (bch.getFullBackupState() != BackupJob.FINISHED)
{
Thread.yield();
Thread.sleep(50);
}
BackupChain bch1 = backup.getCurrentBackups().iterator().next();
log.info(" #1 " + bch1.getLogFilePath());
// BackupChain bch1 = backup.findBackup(config.getRepository(), config.getWorkspace());
// incr works, 15sec+
addContent(ws1TestRoot, 1, 20, 750);
// wait till next backup chain will be started
Thread.sleep(10000);
BackupChain bch2 = backup.getCurrentBackups().iterator().next();
log.info(" #2 " + bch2.getLogFilePath());
// BackupChain bch2 = backup.findBackup(config.getRepository(), config.getWorkspace());
addContent(ws1TestRoot, 21, 40, 750);
// wait till backup will be stopped
waitTime(stopTime);
Thread.sleep(25000); // wait 25 sec if next chain was started before the stop
log.info(" restore #1 " + bch1.getLogFilePath());
restoreAndCheck("ws1back.incr10", "jdbcjcr13", bch1.getLogFilePath(), backDir, 1, 20);
log.info(" restore #2 " + bch2.getLogFilePath());
restoreAndCheck("ws1back.incr11", "jdbcjcr14", bch2.getLogFilePath(), backDir, 21, 40);
}
/**
* 7. startTime, chainPeriod - run periodic forever
*/
public void testScheduler_p7() throws Exception
{
Date startTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
// full backup & incremental
File backDir = new File("target/backup/ws1.incr11");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_AND_INCREMENTAL);
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
scheduler.schedule(config, startTime, null, 10, 0);
// wait till backup will be started
waitTime(startTime);
BackupChain bch1 = backup.getCurrentBackups().iterator().next();
// BackupChain bch1 = backup.findBackup(config.getRepository(), config.getWorkspace());
addContent(ws1TestRoot, 1, 20, 10);
// wait till next backup will be started
Thread.sleep(11000);
BackupChain bch2 = backup.getCurrentBackups().iterator().next();
// BackupChain bch2 = backup.findBackup(config.getRepository(), config.getWorkspace());
addContent(ws1TestRoot, 21, 40, 1);
// Stop backup
Thread.sleep(10000); // for last started chain
scheduler.unschedule(config);
log.info("-----------------[ restore #1 ]-------------------------");
restoreAndCheck("ws1back.incr12", "jdbcjcr15", bch1.getLogFilePath(), backDir, 1, 20);
log.info("-----------------[ restore #2 ]-------------------------");
restoreAndCheck("ws1back.incr13", "jdbcjcr16", bch2.getLogFilePath(), backDir, 21, 40);
}
// 8. startTime, chainPeriod + incrementalPeriod - run periodic forever (with incremental backup)
public void testScheduler_p8() throws Exception
{
Date startTime;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 10);
startTime = calendar.getTime();
// full backup & incremental
File backDir = new File("target/backup/ws1.incr13");
backDir.mkdirs();
BackupConfig config = new BackupConfig();
config.setRepository(repository.getName());
config.setWorkspace("ws1");
config.setBackupType(BackupManager.FULL_AND_INCREMENTAL);
config.setBackupDir(backDir);
BackupScheduler scheduler = backup.getScheduler();
scheduler.schedule(config, startTime, null, 10, 6);
// wait till backup will be started
waitTime(startTime);
BackupChain bch1 = backup.getCurrentBackups().iterator().next();
// BackupChain bch1 = backup.findBackup(config.getRepository(), config.getWorkspace());
addContent(ws1TestRoot, 1, 20, 15);
// wait till next backup will be started
Thread.sleep(11000);
BackupChain bch2 = backup.getCurrentBackups().iterator().next();
// BackupChain bch2 = backup.findBackup(config.getRepository(), config.getWorkspace());
addContent(ws1TestRoot, 21, 40, 15);
// Stop backup
Thread.sleep(10000); // for last started chain
scheduler.unschedule(config);
log.info("-----------------[ restore #1 ]-------------------------");
restoreAndCheck("ws1back.incr14", "jdbcjcr17", bch1.getLogFilePath(), backDir, 1, 20);
log.info("-----------------[ restore #2 ]-------------------------");
restoreAndCheck("ws1back.incr15", "jdbcjcr18", bch2.getLogFilePath(), backDir, 21, 40);
}
}