package org.apache.usergrid.persistence.collection.mvcc.stage.write;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.usergrid.persistence.collection.MvccEntity;
import org.apache.usergrid.persistence.collection.MvccLogEntry;
import org.apache.usergrid.persistence.collection.exception.WriteStartException;
import org.apache.usergrid.persistence.collection.mvcc.entity.Stage;
import org.apache.usergrid.persistence.collection.mvcc.entity.impl.MvccEntityImpl;
import org.apache.usergrid.persistence.collection.mvcc.entity.impl.MvccLogEntryImpl;
import org.apache.usergrid.persistence.collection.mvcc.stage.CollectionIoEvent;
import org.apache.usergrid.persistence.collection.serialization.MvccLogEntrySerializationStrategy;
import org.apache.usergrid.persistence.core.scope.ApplicationScope;
import org.apache.usergrid.persistence.model.entity.Entity;
import org.apache.usergrid.persistence.model.entity.Id;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.netflix.astyanax.MutationBatch;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import rx.functions.Func1;
import static org.apache.usergrid.persistence.core.util.ValidationUtils.verifyEntityWrite;
/**
* This is the first stage and should be invoked immediately when a write is started. It should
* persist the start of a new write in the data store for a checkpoint and recovery
*/
@Singleton
public class WriteStart implements Func1<CollectionIoEvent<Entity>, CollectionIoEvent<MvccEntity>> {
private static final Logger logger = LoggerFactory.getLogger( WriteStart.class );
private final MvccLogEntrySerializationStrategy logStrategy;
/**
* Create a new stage with the current context and status for entity.
*/
@Inject
public WriteStart ( final MvccLogEntrySerializationStrategy logStrategy) {
this.logStrategy = logStrategy;
}
@Override
public CollectionIoEvent<MvccEntity> call( final CollectionIoEvent<Entity> ioEvent ) {
verifyEntityWrite( ioEvent.getEvent() );
final Entity entity = ioEvent.getEvent();
final ApplicationScope applicationScope = ioEvent.getEntityCollection();
final Id entityId = entity.getId();
final UUID newVersion = UUIDGenerator.newTimeUUID();
final MvccLogEntry startEntry = new MvccLogEntryImpl( entityId, newVersion,
Stage.ACTIVE, MvccLogEntry.State.COMPLETE);
MutationBatch write = logStrategy.write( applicationScope, startEntry );
final MvccEntityImpl nextStage = new MvccEntityImpl( entityId, newVersion, MvccEntity.Status.COMPLETE, entity );
if(ioEvent.getEvent().hasVersion()) {
try {
write.execute();
} catch (ConnectionException e) {
logger.error("Failed to execute write ", e);
throw new WriteStartException(nextStage, applicationScope,
"Failed to execute write ", e);
} catch (NullPointerException e) {
logger.error("Failed to execute write ", e);
throw new WriteStartException(nextStage, applicationScope,
"Failed to execute write", e);
}
}
//create the mvcc entity for the next stage
return new CollectionIoEvent<>( applicationScope, nextStage );
}
}