/*
* Copyright 2008-2012 Zuse Institute Berlin (ZIB)
* 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 de.zib.gndms.infra.action;
import de.zib.gndms.common.dspace.SliceConfiguration;
import de.zib.gndms.common.dspace.service.SubspaceService;
import de.zib.gndms.common.model.gorfx.types.AbstractOrder;
import de.zib.gndms.common.model.gorfx.types.Order;
import de.zib.gndms.common.rest.Specifier;
import de.zib.gndms.common.rest.UriFactory;
import de.zib.gndms.infra.GridConfig;
import de.zib.gndms.kit.config.ConfigProvider;
import de.zib.gndms.kit.config.MandatoryOptionMissingException;
import de.zib.gndms.kit.config.MapConfig;
import de.zib.gndms.logic.action.ProcessBuilderAction;
import de.zib.gndms.logic.model.dspace.ChownSliceConfiglet;
import de.zib.gndms.logic.model.dspace.DeleteSliceTaskAction;
import de.zib.gndms.logic.model.dspace.SliceProvider;
import de.zib.gndms.logic.model.gorfx.AbstractQuoteCalculator;
import de.zib.gndms.logic.model.gorfx.TaskFlowAction;
import de.zib.gndms.model.common.NoSuchResourceException;
import de.zib.gndms.model.common.PersistentContract;
import de.zib.gndms.model.dspace.Slice;
import de.zib.gndms.model.gorfx.types.DelegatingOrder;
import de.zib.gndms.model.util.TxFrame;
import de.zib.gndms.neomodel.common.Dao;
import de.zib.gndms.neomodel.common.Session;
import de.zib.gndms.neomodel.gorfx.Task;
import de.zib.gndms.neomodel.gorfx.Taskling;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import java.io.File;
/**
* @date: 12.08.12
* @time: 17:02
* @author: Jörg Bachmann
* @email: bachmann@zib.de
*/
public abstract class SlicedTaskFlowAction< K extends AbstractOrder > extends TaskFlowAction< K > {
public static final long DEFAULT_SLICE_SIZE = 100*1024*1024; // 100MB
private GridConfig gridConfig;
protected SliceProvider sliceProvider;
private AbstractQuoteCalculator<? extends Order> quoteCalculator;
private SubspaceService subspaceService;
public SlicedTaskFlowAction( @NotNull String taskFlowTypeId ) {
super( taskFlowTypeId );
}
public SlicedTaskFlowAction(
@NotNull String taskFlowTypeId,
@NotNull EntityManager em,
@NotNull Dao dao,
@NotNull Taskling model ) {
super( taskFlowTypeId, em, dao, model );
}
protected Slice findSlice( final String sliceId ) {
getLogger().info( "findSlice(" + ( sliceId == null ? "null" : '"' + sliceId + '"' ) + ')' );
if (sliceId == null)
return null;
final EntityManager em = getEntityManager();
final TxFrame txf = new TxFrame(em);
try {
final Slice slice = em.find(Slice.class, sliceId);
txf.commit();
return slice;
}
finally { txf.finish(); }
}
protected void updateSlice( Slice slice ) {
final EntityManager em = getEntityManager();
final TxFrame txf = new TxFrame(em);
try {
em.persist( slice );
txf.commit();
}
finally { txf.finish(); }
}
protected Slice findSlice() {
return findSlice( getSliceId() );
}
protected String getSliceId( ) {
final Specifier<Void> sliceSpecifier = getSliceSpecifier();
if( null == sliceSpecifier )
throw new NoSuchResourceException( "Could not get slice Id." );
return sliceSpecifier.getUriMap().get( UriFactory.SLICE );
}
protected Specifier< Void > getSliceSpecifier( ) {
// maybe cache the slice id
final Session session = getDao().beginSession();
try {
final Task task = getTask( session );
Specifier<Void> sliceSpec = ( Specifier<Void> ) task.getPayload();
session.success();
return sliceSpec;
}
finally {
session.finish();
}
}
protected void setSliceSpecifier( final Specifier< Void > sliceSpec, final Session session ) {
final Task task = getTask( session );
task.setPayload(sliceSpec);
}
protected void setSliceSpecifier( Specifier<Void> sliceSpec) {
final Session session = getDao().beginSession();
try {
setSliceSpecifier(sliceSpec, session );
session.success();
}
finally {
session.finish();
}
}
protected void attachSlice( final String sliceId ) throws Exception {
final ConfigProvider config = getOfferTypeConfig();
final String subspaceId = config.getOption( "subspace" );
String sliceKindKey = config.getOption( "sliceKind" );
Specifier< Void > sliceSpec = UriFactory.createSliceSpecifier(
getGridConfig().getBaseUrl(),
subspaceId,
sliceKindKey,
sliceId );
setSliceSpecifier( sliceSpec );
}
protected void createNewSlice() throws MandatoryOptionMissingException {
final ConfigProvider config = getOfferTypeConfig();
final String subspaceId = config.getOption( "subspace" );
String sliceKindId = config.getOption( "sliceKind" );
SliceConfiguration sconf = new SliceConfiguration();
sconf.setTerminationTime( getContract().getResultValidity() );
sconf.setSize( DEFAULT_SLICE_SIZE );
ResponseEntity< Specifier< Void > > sliceResponseEntity = subspaceService.createSlice(
subspaceId,
sliceKindId,
sconf.getStringRepresentation(),
getOrder().getDNFromContext() );
if (! HttpStatus.CREATED.equals( sliceResponseEntity.getStatusCode() ) )
throw new IllegalStateException( "Slice creation failed" );
setSliceSpecifier( sliceResponseEntity.getBody() );
// to provoke nasty test condition uncomment the following line
//throw new NullPointerException( );
getLogger().info("createNewSlice() = " + getSliceId());
}
protected void deleteSlice( final String sliceId ) {
final DeleteSliceTaskAction deleteSliceTaskAction = new DeleteSliceTaskAction();
getInjector().injectMembers( deleteSliceTaskAction );
getService().submitTaskAction(deleteSliceTaskAction,
new de.zib.gndms.model.gorfx.types.ModelIdHoldingOrder(sliceId), getWid());
}
protected void killSlice() {
deleteSlice(getSliceId());
}
protected void changeSliceOwner( Slice slice ) {
ChownSliceConfiglet csc = getConfigletProvider().getConfiglet( ChownSliceConfiglet.class, "sliceChown" );
if( csc == null )
throw new IllegalStateException( "chown configlet is null!");
final DelegatingOrder<?> order = getOrder();
String dn = order.getDNFromContext();
getLogger().debug( "cso DN: " + dn );
getLogger().debug( "changing owner of " + slice.getId() + " to " + order.getLocalUser() );
ProcessBuilderAction chownAct = csc.createChownSliceAction( order.getLocalUser(),
slice.getSubspace().getPath() + File.separator + slice.getKind().getSliceDirectory(),
slice.getDirectoryId() );
chownAct.call();
}
protected void checkQuotas() throws Exception {
final Slice sliceModel = findSlice();
final de.zib.gndms.infra.dspace.Slice slice = new de.zib.gndms.infra.dspace.Slice( sliceModel );
final long sliceSize = slice.getTotalStorageSize();
final long sliceUsage = slice.getDiskUsage();
getQuoteCalculator().setOrder( ( DelegatingOrder )getOrder() );
final long needSize = getQuoteCalculator().createQuotes().get( 0 ).getExpectedSize();
if( sliceUsage + needSize > sliceSize )
throw new IllegalStateException(
"Staging would exceed slice size: Need "
+ String.valueOf( needSize )
+ " Bytes but have only "
+ String.valueOf( sliceSize - sliceUsage )
+ " Bytes left." );
}
public @NotNull
MapConfig getOfferTypeConfig() {
return new MapConfig( getTaskFlowTypeConfigMapData() );
}
public PersistentContract getContract() {
final Session session = getDao().beginSession();
try {
final Task task = getTask(session);
final PersistentContract ret = task.getContract();
session.finish();
return ret;
}
finally {
session.success();
}
}
public SubspaceService getSubspaceService() {
return subspaceService;
}
@SuppressWarnings( "SpringJavaAutowiringInspection" )
@Inject
public void setSubspaceService( SubspaceService subspaceService ) {
this.subspaceService = subspaceService;
}
private String getWid() {
Session session = getDao().beginSession();
try {
String wid = getTask( session ).getWID();
session.success();
return wid;
} finally {session.finish();}
}
public AbstractQuoteCalculator<? extends Order> getQuoteCalculator() {
return quoteCalculator;
}
public void setQuoteCalculator( AbstractQuoteCalculator<? extends Order> quoteCalculator ) {
this.quoteCalculator = quoteCalculator;
}
public GridConfig getGridConfig() {
return gridConfig;
}
@Inject
public void setGridConfig( GridConfig gridConfig ) {
this.gridConfig = gridConfig;
}
@Inject
public void setSliceProvider( SliceProvider sliceProvider ) {
this.sliceProvider = sliceProvider;
}
protected SliceProvider getSliceProvider() {
return sliceProvider;
}
}