/*
* Copyright 2012-2015, the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.flipkart.aesop.serializer.stateengine;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Calendar;
import org.trpr.platform.core.PlatformException;
import org.trpr.platform.core.impl.logging.LogFactory;
import org.trpr.platform.core.spi.logging.Logger;
import com.flipkart.aesop.serializer.SerializerConstants;
import com.netflix.zeno.fastblob.FastBlobStateEngine;
import com.netflix.zeno.fastblob.io.FastBlobWriter;
/**
* The <code>DailyStateTransitioner</code> class is a sub-type of {@link StateTransitioner} that creates or suitably initializes an existing
* {@link FastBlobStateEngine} for producing daily snapshots followed by any number of deltas for the day.
*
* @see StateTransitioner
* @author Regunath B
* @version 1.0, 5 March 2014
*/
public class DailyStateTransitioner<T> extends StateTransitioner<T> {
/** The Logger interface*/
private static final Logger LOGGER = LogFactory.getLogger(DailyStateTransitioner.class);
/** The FastBlobStateEngine that this StateTransitioner creates and manages */
private FastBlobStateEngine stateEngine;
/**
* Abstract method implementation. Creates a new FastBlobStateEngine, if required, and
* loads the last daily snapshot, if one is available
* @see com.flipkart.aesop.serializer.stateengine.StateTransitioner#getStateEngine()
*/
public FastBlobStateEngine getStateEngine() {
return this.stateEngine;
}
/**
* Abstract method implementation. Persists state held by the FastBlobStateEngine and prepares it for the next cycle
* @see com.flipkart.aesop.serializer.stateengine.StateTransitioner#saveState()
*/
public void saveState() {
this.getStateEngine().prepareForWrite();
// Create a writer, which will be responsible for creating snapshot and/or delta blobs.
FastBlobWriter writer = new FastBlobWriter(this.getStateEngine());
DataOutputStream dataOS = null;
try {
Calendar calendar = Calendar.getInstance();
File dayDir = new File (this.serializedDataLocationDir, SerializerConstants.DAILY_DIR_FORMAT.format(calendar.getTime()));
if (!dayDir.exists() || this.stateEngine.getLatestVersion() == null || this.stateEngine.getLatestVersion().trim().length() == 0) {
// no snapshot for today or state engine contents has not been written out before, write a snapshot for today and return
dayDir.mkdir();
File snapshotFile = new File (dayDir, SerializerConstants.DAILY_FILE_FORMAT.format(calendar.getTime()) + SerializerConstants.DELIM_CHAR
+ SerializerConstants.SNAPSHOT_FILE);
snapshotFile.createNewFile();
dataOS = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(snapshotFile)));
writer.writeSnapshot(dataOS);
LOGGER.info("Fast blob state engine data written to snapshot file : " + snapshotFile.getAbsolutePath());
} else { // write delta
File deltaFile = new File (dayDir, SerializerConstants.DAILY_FILE_FORMAT.format(calendar.getTime()) + SerializerConstants.DELIM_CHAR
+ SerializerConstants.DELTA_FILE);
deltaFile.createNewFile();
dataOS = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(deltaFile)));
writer.writeDelta(dataOS);
LOGGER.info("Fast blob state engine data written to delta file : " + deltaFile.getAbsolutePath());
}
dataOS.close();
// set the state engine version to the snapshot or delta file that was written
this.stateEngine.setLatestVersion(SerializerConstants.DAILY_FILE_FORMAT.format(calendar.getTime()));
this.getStateEngine().prepareForNextCycle(); // prepare the state engine for next run
} catch (Exception e) {
throw new PlatformException("Error saving state engine data : " + e.getMessage(), e);
}
}
/**
* Overriden super class method. Additionally creates and initializes the FastBlobStateEngine
* @see com.flipkart.aesop.serializer.stateengine.StateTransitioner#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
this.stateEngine = new FastBlobStateEngine(this.serializerFactory);
}
}