use of com.google.apphosting.datastore.DatastoreV3Pb.Cost in project appengine-java-standard by GoogleCloudPlatform.
the class LocalDatastoreService method putImpl.
// status
@SuppressWarnings("unused")
public PutResponse putImpl(Status status, PutRequest request) {
PutResponse response = new PutResponse();
if (request.entitySize() == 0) {
return response;
}
Cost totalCost = response.getMutableCost();
String app = request.entitys().get(0).getKey().getApp();
List<EntityProto> clones = new ArrayList<>();
for (EntityProto entity : request.entitys()) {
validateAndProcessEntityProto(entity);
EntityProto clone = entity.clone();
clones.add(clone);
checkArgument(clone.hasKey());
Reference key = clone.getKey();
checkArgument(key.getPath().elementSize() > 0);
clone.getMutableKey().setApp(app);
Element lastPath = getLastElement(key);
if (lastPath.getId() == 0 && !lastPath.hasName()) {
if (autoIdAllocationPolicy == AutoIdAllocationPolicy.SEQUENTIAL) {
lastPath.setId(entityIdSequential.getAndIncrement());
} else {
lastPath.setId(toScatteredId(entityIdScattered.getAndIncrement()));
}
}
preprocessEntity(clone);
if (clone.getEntityGroup().elementSize() == 0) {
// The entity needs its entity group set.
Path group = clone.getMutableEntityGroup();
Element root = key.getPath().elements().get(0);
Element pathElement = group.addElement();
pathElement.setType(root.getType());
if (root.hasName()) {
pathElement.setName(root.getName());
} else {
pathElement.setId(root.getId());
}
} else {
// update an existing entity
checkState(clone.hasEntityGroup() && clone.getEntityGroup().elementSize() > 0);
}
}
Map<Path, List<EntityProto>> entitiesByEntityGroup = new LinkedHashMap<>();
Map<Reference, Long> writtenVersions = new HashMap<>();
final Profile profile = getOrCreateProfile(app);
synchronized (profile) {
LiveTxn liveTxn = null;
for (EntityProto clone : clones) {
Profile.EntityGroup eg = profile.getGroup(clone.getEntityGroup());
if (request.hasTransaction()) {
// the transaction is committed.
if (liveTxn == null) {
liveTxn = profile.getTxn(request.getTransaction().getHandle());
}
checkRequest(!liveTxn.isReadOnly(), "Cannot modify entities in a read-only transaction.");
// this will throw an exception if we attempt to
// modify the wrong entity group
eg.addTransaction(liveTxn).addWrittenEntity(clone);
} else {
List<EntityProto> entities = entitiesByEntityGroup.get(clone.getEntityGroup());
if (entities == null) {
entities = new ArrayList<>();
entitiesByEntityGroup.put(clone.getEntityGroup(), entities);
}
entities.add(clone);
}
response.mutableKeys().add(clone.getKey());
}
for (final Map.Entry<Path, List<EntityProto>> entry : entitiesByEntityGroup.entrySet()) {
Profile.EntityGroup eg = profile.getGroup(entry.getKey());
eg.incrementVersion();
LocalDatastoreJob job = new WriteJob(highRepJobPolicy, eg, profile, entry.getValue(), Collections.<Reference>emptyList());
addTo(totalCost, job.calculateJobCost());
eg.addJob(job);
for (EntityProto entity : entry.getValue()) {
writtenVersions.put(entity.getKey(), job.getMutationTimestamp(entity.getKey()));
}
}
}
if (!request.hasTransaction()) {
logger.fine("put: " + request.entitySize() + " entities");
// Fill the version numbers, in the same order
for (Reference key : response.keys()) {
response.addVersion(writtenVersions.get(key));
}
}
response.setCost(totalCost);
return response;
}
use of com.google.apphosting.datastore.DatastoreV3Pb.Cost in project appengine-java-standard by GoogleCloudPlatform.
the class LocalDatastoreCostAnalysis method getWriteOps.
/**
* Determines the cost of writing {@code newEntity}, assuming its current state in the datastore
* matches {@code oldEntity}.
*
* @param oldEntity Entity representing the current state in the datastore. Can be {@code null}.
* @param newEntity Entity representing the desired state in the datastore.
* @return The cost of writing {@code newEntity}.
*/
public Cost getWriteOps(@Nullable EntityProto oldEntity, EntityProto newEntity) {
Cost cost = new Cost().setEntityWrites(0).setIndexWrites(0);
// check for a no-op write, only possible if an entity already existed
if (equalProperties(oldEntity, newEntity)) {
return cost;
}
// Not a no-op write, so one write for the entity.
cost.setEntityWrites(1);
int indexWrites = changedIndexRows(oldEntity, newEntity);
if (oldEntity == null) {
// 1 additional index write for the EntitiesByKind index, which is only written to when we're
// writing an entity for the first time (kind is immutable).
indexWrites++;
}
return cost.setIndexWrites(indexWrites);
}
use of com.google.apphosting.datastore.DatastoreV3Pb.Cost in project appengine-java-standard by GoogleCloudPlatform.
the class LocalDatastoreService method commitImpl.
/**
* Requires a lock on the provided profile.
*/
private CommitResponse commitImpl(LiveTxn liveTxn, final Profile profile) {
// assumes we already have a lock on the profile
CommitResponse response = new CommitResponse();
for (EntityGroupTracker tracker : liveTxn.getAllTrackers()) {
// This will throw an exception if the entity group
// has been modified since this transaction started.
tracker.checkEntityGroupVersion();
}
int deleted = 0;
int written = 0;
Cost totalCost = new Cost();
long commitTimestamp = profile.incrementAndGetCommitTimestamp();
for (EntityGroupTracker tracker : liveTxn.getAllTrackers()) {
Profile.EntityGroup eg = tracker.getEntityGroup();
eg.incrementVersion();
final Collection<EntityProto> writtenEntities = tracker.getWrittenEntities();
final Collection<Reference> deletedKeys = tracker.getDeletedKeys();
LocalDatastoreJob job = new WriteJob(highRepJobPolicy, eg, profile, commitTimestamp, writtenEntities, deletedKeys);
addTo(totalCost, job.calculateJobCost());
eg.addJob(job);
deleted += deletedKeys.size();
written += writtenEntities.size();
for (EntityProto writtenEntity : writtenEntities) {
response.addVersion().setRootEntityKey(writtenEntity.getKey()).setVersion(job.getMutationTimestamp(writtenEntity.getKey()));
}
for (Reference deletedKey : deletedKeys) {
response.addVersion().setRootEntityKey(deletedKey).setVersion(job.getMutationTimestamp(deletedKey));
}
}
logger.fine("committed: " + written + " puts, " + deleted + " deletes in " + liveTxn.getAllTrackers().size() + " entity groups");
response.setCost(totalCost);
return response;
}
use of com.google.apphosting.datastore.DatastoreV3Pb.Cost in project appengine-java-standard by GoogleCloudPlatform.
the class LocalDatastoreService method deleteImpl.
// status
@SuppressWarnings("unused")
public DeleteResponse deleteImpl(Status status, DeleteRequest request) {
DeleteResponse response = new DeleteResponse();
if (request.keySize() == 0) {
return response;
}
Cost totalCost = response.getMutableCost();
// We don't support requests that span apps, so the app for the first key
// is the app for all keys.
String app = request.keys().get(0).getApp();
final Profile profile = getOrCreateProfile(app);
LiveTxn liveTxn = null;
// Maintain a mapping of keys by entity group so that we can apply one job
// per entity group.
Map<Path, List<Reference>> keysByEntityGroup = new LinkedHashMap<>();
Map<Reference, Long> writtenVersions = new HashMap<>();
synchronized (profile) {
for (final Reference key : request.keys()) {
validatePathComplete(key);
Path group = getGroup(key);
if (request.hasTransaction()) {
if (liveTxn == null) {
liveTxn = profile.getTxn(request.getTransaction().getHandle());
}
checkRequest(!liveTxn.isReadOnly(), "Cannot modify entities in a read-only transaction.");
Profile.EntityGroup eg = profile.getGroup(group);
// this will throw an exception if we attempt to modify
// the wrong entity group
eg.addTransaction(liveTxn).addDeletedEntity(key);
} else {
List<Reference> keysToDelete = keysByEntityGroup.get(group);
if (keysToDelete == null) {
keysToDelete = new ArrayList<>();
keysByEntityGroup.put(group, keysToDelete);
}
keysToDelete.add(key);
}
}
// does all the work for each entity group.
for (final Map.Entry<Path, List<Reference>> entry : keysByEntityGroup.entrySet()) {
Profile.EntityGroup eg = profile.getGroup(entry.getKey());
eg.incrementVersion();
LocalDatastoreJob job = new WriteJob(highRepJobPolicy, eg, profile, Collections.<EntityProto>emptyList(), entry.getValue());
addTo(totalCost, job.calculateJobCost());
eg.addJob(job);
for (Reference deletedKey : entry.getValue()) {
writtenVersions.put(deletedKey, job.getMutationTimestamp(deletedKey));
}
}
}
if (!request.hasTransaction()) {
for (Reference key : request.keys()) {
response.addVersion(writtenVersions.get(key));
}
}
return response;
}
use of com.google.apphosting.datastore.DatastoreV3Pb.Cost in project appengine-java-standard by GoogleCloudPlatform.
the class LocalDatastoreService method commit.
// status
@SuppressWarnings("unused")
public CommitResponse commit(Status status, final Transaction req) {
Profile profile = profiles.get(req.getApp());
checkNotNull(profile);
CommitResponse response = new CommitResponse();
globalLock.readLock().lock();
// Synchronized so we can't commit and rollback at the same time.
synchronized (profile) {
LiveTxn liveTxn;
try {
liveTxn = profile.removeTxn(req.getHandle());
try {
if (liveTxn.isDirty()) {
response = commitImpl(liveTxn, profile);
} else {
// cost of a read-only txn is 0
response.setCost(new Cost().setEntityWrites(0).setIndexWrites(0));
}
} catch (ApplicationException e) {
// commit failed, re-add transaction so that it can be rolled back or reset.
profile.addTxn(req.getHandle(), new LiveTxn(clock, liveTxn.allowMultipleEg, liveTxn.originalTransactionMode, true));
throw e;
}
} finally {
globalLock.readLock().unlock();
}
// taskqueue tasks become durable.
for (TaskQueueAddRequest action : liveTxn.getActions()) {
try {
addActionImpl(action);
} catch (ApplicationException e) {
logger.log(Level.WARNING, "Transactional task: " + action + " has been dropped.", e);
}
}
}
return response;
}
Aggregations