// Copyright 2011 Google Inc. // // 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.google.appengine.tools.pipeline.impl.model; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; import com.google.appengine.tools.pipeline.impl.PipelineManager; import java.io.IOException; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * A slot to be filled in with a value. * * @author [email protected] (Mitch Rudominer) */ public class Slot extends PipelineModelObject { public static final String DATA_STORE_KIND = "pipeline-slot"; private static final String FILLED_PROPERTY = "filled"; private static final String VALUE_PROPERTY = "value"; private static final String WAITING_ON_ME_PROPERTY = "waitingOnMe"; private static final String FILL_TIME_PROPERTY = "fillTime"; private static final String SOURCE_JOB_KEY_PROPERTY = "sourceJob"; // persistent private boolean filled; private Date fillTime; private Object value; private Key sourceJobKey; private final List<Key> waitingOnMeKeys; // transient private List<Barrier> waitingOnMeInflated; private Object serializedVersion; public Slot(Key rootJobKey, Key generatorJobKey, String graphGUID) { super(rootJobKey, generatorJobKey, graphGUID); waitingOnMeKeys = new LinkedList<>(); } public Slot(Entity entity) { this(entity, false); } public Slot(Entity entity, boolean lazy) { super(entity); filled = (Boolean) entity.getProperty(FILLED_PROPERTY); fillTime = (Date) entity.getProperty(FILL_TIME_PROPERTY); sourceJobKey = (Key) entity.getProperty(SOURCE_JOB_KEY_PROPERTY); waitingOnMeKeys = getListProperty(WAITING_ON_ME_PROPERTY, entity); if (lazy) { serializedVersion = entity.getProperty(VALUE_PROPERTY); } else { value = deserializeValue(entity.getProperty(VALUE_PROPERTY)); } } private Object deserializeValue(Object serializedValue) { try { return PipelineManager.getBackEnd().deserializeValue(this, serializedValue); } catch (IOException e) { throw new RuntimeException(e); } } @Override public Entity toEntity() { Entity entity = toProtoEntity(); entity.setUnindexedProperty(FILLED_PROPERTY, filled); if (null != fillTime) { entity.setUnindexedProperty(FILL_TIME_PROPERTY, fillTime); } if (null != sourceJobKey) { entity.setProperty(SOURCE_JOB_KEY_PROPERTY, sourceJobKey); } entity.setProperty(WAITING_ON_ME_PROPERTY, waitingOnMeKeys); if (serializedVersion != null) { entity.setUnindexedProperty(VALUE_PROPERTY, serializedVersion); } else { try { entity.setUnindexedProperty(VALUE_PROPERTY, PipelineManager.getBackEnd().serializeValue(this, value)); } catch (IOException e) { throw new RuntimeException(e); } } return entity; } @Override protected String getDatastoreKind() { return DATA_STORE_KIND; } public void inflate(Map<Key, Barrier> pool) { waitingOnMeInflated = buildInflated(waitingOnMeKeys, pool); } public void addWaiter(Barrier waiter) { waitingOnMeKeys.add(waiter.getKey()); if (null == waitingOnMeInflated) { waitingOnMeInflated = new LinkedList<>(); } waitingOnMeInflated.add(waiter); } public boolean isFilled() { return filled; } public Object getValue() { if (serializedVersion != null) { value = deserializeValue(serializedVersion); serializedVersion = null; } return value; } /** * Will return {@code null} if this slot is not filled. */ public Date getFillTime() { return fillTime; } public Key getSourceJobKey() { return sourceJobKey; } public void setSourceJobKey(Key key) { sourceJobKey = key; } public void fill(Object value) { filled = true; this.value = value; serializedVersion = null; fillTime = new Date(); } public List<Key> getWaitingOnMeKeys() { return waitingOnMeKeys; } /** * If this slot has not yet been inflated this method returns null; */ public List<Barrier> getWaitingOnMeInflated() { return waitingOnMeInflated; } @Override public String toString() { return "Slot[" + getKeyName(getKey()) + ", value=" + (serializedVersion != null ? "..." : value) + ", filled=" + filled + ", waitingOnMe=" + waitingOnMeKeys + ", parent=" + getKeyName(getGeneratorJobKey()) + ", guid=" + getGraphGuid() + "]"; } }