public PutResponse putImpl()

in api_dev/src/main/java/com/google/appengine/api/datastore/dev/LocalDatastoreService.java [836:938]


  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()) {
          // If there's a transaction we delay the put until
          // 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;
  }