GEODE-9147: Revert to multi-hop PUTALL in the face of missing metadata (#784)

- This matches the behavior of the Java client
- Our current code to "tack on" values that we don't have metadata
  for will sometimes result in EventIds reaching a server out-of-order,
  causing them to be dropped and resulting in data loss.  Resorting
  to multi-hop avoids this altogether.
- Add test to repro issue of missing keys on single-hop putAll
diff --git a/cppcache/integration/test/RegionPutAllTest.cpp b/cppcache/integration/test/RegionPutAllTest.cpp
index 7fd7804..ca40fac 100644
--- a/cppcache/integration/test/RegionPutAllTest.cpp
+++ b/cppcache/integration/test/RegionPutAllTest.cpp
@@ -102,4 +102,39 @@
   }
 }
 
+//
+// verifies that putall works when not all metadata is present, i.e. not all
+// buckets exist yet on the cluster.
+//
+TEST(RegionPutAllTest, putAllAndVerifyKeysExist) {
+  Cluster cluster{LocatorCount{1}, ServerCount{3}};
+
+  cluster.start();
+
+  cluster.getGfsh()
+      .create()
+      .region()
+      .withName("region")
+      .withType("PARTITION")
+      .execute();
+
+  auto cache = createCache();
+  auto pool = createPool(cluster, cache);
+  auto region = setupRegion(cache, pool);
+
+  for (int i = 0; i < 50; i++) {
+    region->put(std::to_string(i), Cacheable::create(i));
+  }
+
+  HashMapOfCacheable all;
+  for (int i = 0; i < 113; i++) {
+    all.emplace(CacheableKey::create(std::to_string(i)), Cacheable::create(i));
+  }
+
+  std::this_thread::sleep_for(std::chrono::seconds(10));
+  region->putAll(all);
+  for (auto& key : all) {
+    ASSERT_TRUE(region->containsKeyOnServer(key.first));
+  }
+}
 }  // namespace
diff --git a/cppcache/src/ClientMetadataService.cpp b/cppcache/src/ClientMetadataService.cpp
index 3b46e35..7b1bde6 100644
--- a/cppcache/src/ClientMetadataService.cpp
+++ b/cppcache/src/ClientMetadataService.cpp
@@ -173,8 +173,6 @@
       new DataOutput(m_cache->createDataOutput(m_pool)), regionPath);
   TcrMessageReply reply(true, nullptr);
   // send this message to server and get metadata from server.
-  LOGFINE("Now sending GET_CLIENT_PR_METADATA for getting from server: %s",
-          regionPath);
   std::shared_ptr<Region> region = nullptr;
   GfErrType err = m_pool->sendSyncRequest(request, reply);
   if (err == GF_NOERR &&
@@ -186,7 +184,9 @@
       }
     }
     auto metadata = reply.getMetadata();
-    if (metadata == nullptr) return nullptr;
+    if (metadata == nullptr) {
+      return nullptr;
+    }
     if (metadata->empty()) {
       delete metadata;
       return nullptr;
@@ -358,8 +358,9 @@
       clientMetadata->getServerLocation(bucketId, isPrimary, serverLocation,
                                         version);
       if (!(serverLocation && serverLocation->isValid())) {
-        keysWhichLeft.push_back(key);
-        continue;
+        // If we're missing any metadata, give up.  This will cause us to revert
+        // to multi-hop, which is consistent with the Java client.
+        return nullptr;
       }
 
       buckets[bucketId] = serverLocation;