// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

#include "google/protobuf/arenaz_sampler.h"

#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <utility>
#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "absl/base/optimization.h"
#include "absl/log/absl_check.h"
#include "absl/log/log_streamer.h"
#include "absl/random/random.h"
#include "absl/random/seed_sequences.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock.h"
#include "google/protobuf/arena_allocation_policy.h"
#include "google/protobuf/serial_arena.h"


// Must be included last.
#include "google/protobuf/port_def.inc"

namespace google {
namespace protobuf {
namespace internal {
#if defined(PROTOBUF_ARENAZ_SAMPLE)
class ThreadSafeArenaStatsHandlePeer {
 public:
  static bool IsSampled(const ThreadSafeArenaStatsHandle& h) {
    return h.info_ != nullptr;
  }

  static ThreadSafeArenaStats* GetInfo(ThreadSafeArenaStatsHandle* h) {
    return h->info_;
  }
};

std::vector<size_t> GetBytesAllocated(ThreadSafeArenazSampler* s) {
  std::vector<size_t> res;
  s->Iterate([&](const ThreadSafeArenaStats& info) {
    for (const auto& block_stats : info.block_histogram) {
      size_t bytes_allocated =
          block_stats.bytes_allocated.load(std::memory_order_acquire);
      if (bytes_allocated != 0) {
        res.push_back(bytes_allocated);
      }
    }
  });
  return res;
}

ThreadSafeArenaStats* Register(ThreadSafeArenazSampler* s, size_t size,
                               int64_t stride) {
  auto* info = s->Register(stride);
  assert(info != nullptr);
  info->block_histogram[0].bytes_allocated.store(size,
                                                 std::memory_order_relaxed);
  return info;
}

#endif  // defined(PROTOBUF_ARENAZ_SAMPLE)

namespace {

#if defined(PROTOBUF_ARENAZ_SAMPLE)

TEST(ThreadSafeArenaStatsTest, PrepareForSampling) {
  ThreadSafeArenaStats info;
  constexpr int64_t kTestStride = 107;
  absl::MutexLock l(&info.init_mu);
  info.PrepareForSampling(kTestStride);

  for (const auto& block_stats : info.block_histogram) {
    EXPECT_EQ(block_stats.num_allocations.load(std::memory_order_relaxed), 0);
    EXPECT_EQ(block_stats.bytes_used.load(std::memory_order_relaxed), 0);
    EXPECT_EQ(block_stats.bytes_allocated.load(std::memory_order_relaxed), 0);
    EXPECT_EQ(block_stats.bytes_wasted.load(std::memory_order_relaxed), 0);
  }
  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 0);
  EXPECT_EQ(info.weight, kTestStride);

  for (auto& block_stats : info.block_histogram) {
    block_stats.num_allocations.store(1, std::memory_order_relaxed);
    block_stats.bytes_used.store(1, std::memory_order_relaxed);
    block_stats.bytes_allocated.store(1, std::memory_order_relaxed);
    block_stats.bytes_wasted.store(1, std::memory_order_relaxed);
  }
  info.max_block_size.store(1, std::memory_order_relaxed);

  info.PrepareForSampling(2 * kTestStride);
  for (auto& block_stats : info.block_histogram) {
    EXPECT_EQ(block_stats.num_allocations.load(std::memory_order_relaxed), 0);
    EXPECT_EQ(block_stats.bytes_used.load(std::memory_order_relaxed), 0);
    EXPECT_EQ(block_stats.bytes_allocated.load(std::memory_order_relaxed), 0);
    EXPECT_EQ(block_stats.bytes_wasted.load(std::memory_order_relaxed), 0);
  }
  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 0);
  EXPECT_EQ(info.weight, 2 * kTestStride);
}

TEST(ThreadSafeArenaStatsTest, FindBin) {
  size_t current_bin = 0;
  size_t bytes = 1;
  while (current_bin < ThreadSafeArenaStats::kBlockHistogramBins - 1) {
    size_t next_bin = ThreadSafeArenaStats::FindBin(bytes);
    if (next_bin != current_bin) {
      // Test the bins increase linearly.
      EXPECT_EQ(next_bin, current_bin + 1);
      // Test the bins change only at values of the form 2^k + 1.
      EXPECT_EQ(absl::popcount(bytes - 1), 1);
      current_bin = next_bin;
    }
    ++bytes;
  }
}

TEST(ThreadSafeArenaStatsTest, MinMaxBlockSizeForBin) {
  std::pair<size_t, size_t> current_limits =
      ThreadSafeArenaStats::MinMaxBlockSizeForBin(0);
  EXPECT_EQ(current_limits.first, 1);
  EXPECT_LT(current_limits.first, current_limits.second);
  for (size_t i = 1; i < ThreadSafeArenaStats::kBlockHistogramBins; ++i) {
    std::pair<size_t, size_t> next_limits =
        ThreadSafeArenaStats::MinMaxBlockSizeForBin(i);
    EXPECT_LT(next_limits.first, next_limits.second);
    // Test the limits do not have gaps.
    EXPECT_EQ(next_limits.first, current_limits.second + 1);
    if (i != ThreadSafeArenaStats::kBlockHistogramBins - 1) {
      EXPECT_EQ(next_limits.second, 2 * current_limits.second);
    }
    current_limits = next_limits;
  }
  // Test the limits cover the entire range possible.
  EXPECT_EQ(current_limits.second, std::numeric_limits<size_t>::max());
}

TEST(ThreadSafeArenaStatsTest, RecordAllocateSlow) {
  ThreadSafeArenaStats info;
  constexpr int64_t kTestStride = 458;
  absl::MutexLock l(&info.init_mu);
  info.PrepareForSampling(kTestStride);
  RecordAllocateSlow(&info, /*requested=*/0, /*allocated=*/128, /*wasted=*/0);
  EXPECT_EQ(
      info.block_histogram[0].num_allocations.load(std::memory_order_relaxed),
      1);
  EXPECT_EQ(info.block_histogram[0].bytes_used.load(std::memory_order_relaxed),
            0);
  EXPECT_EQ(
      info.block_histogram[0].bytes_allocated.load(std::memory_order_relaxed),
      128);
  EXPECT_EQ(
      info.block_histogram[0].bytes_wasted.load(std::memory_order_relaxed), 0);
  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 128);
  RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/256,
                     /*wasted=*/28);
  EXPECT_EQ(info.block_histogram[0].bytes_used.load(std::memory_order_relaxed),
            100);
  EXPECT_EQ(
      info.block_histogram[0].bytes_wasted.load(std::memory_order_relaxed), 28);
  EXPECT_EQ(
      info.block_histogram[1].num_allocations.load(std::memory_order_relaxed),
      1);
  EXPECT_EQ(
      info.block_histogram[1].bytes_allocated.load(std::memory_order_relaxed),
      256);
  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 256);
}

TEST(ThreadSafeArenaStatsTest, RecordAllocateSlowMaxBlockSizeTest) {
  ThreadSafeArenaStats info;
  constexpr int64_t kTestStride = 458;
  absl::MutexLock l(&info.init_mu);
  info.PrepareForSampling(kTestStride);
  RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/128, /*wasted=*/0);
  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 128);
  RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/256,
                     /*wasted=*/28);
  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 256);
  RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/128,
                     /*wasted=*/28);
  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 256);
}

TEST(ThreadSafeArenazSamplerTest, SamplingCorrectness) {
  SetThreadSafeArenazEnabled(true);
  for (int p = 0; p <= 15; ++p) {
    SetThreadSafeArenazSampleParameter(1 << p);
    SetThreadSafeArenazGlobalNextSample(1 << p);
    const int kTrials = 1000 << p;
    std::vector<ThreadSafeArenaStatsHandle> hv;
    for (int i = 0; i < kTrials; ++i) {
      ThreadSafeArenaStatsHandle h = Sample();
      if (h.MutableStats() != nullptr) hv.push_back(std::move(h));
    }
    // Ideally samples << p should be very close to kTrials.  But we keep a
    // factor of two guard band.
    EXPECT_GE(hv.size() << p, kTrials / 2);
    EXPECT_LE(hv.size() << p, 2 * kTrials);
  }
}

TEST(ThreadSafeArenazSamplerTest, SmallSampleParameter) {
  SetThreadSafeArenazEnabled(true);
  SetThreadSafeArenazSampleParameter(100);
  constexpr int64_t kTestStride = 0;

  for (int i = 0; i < 1000; ++i) {
    SamplingState sampling_state = {kTestStride, kTestStride};
    ThreadSafeArenaStats* sample = SampleSlow(sampling_state);
    EXPECT_GT(sampling_state.next_sample, 0);
    EXPECT_NE(sample, nullptr);
    UnsampleSlow(sample);
  }
}

TEST(ThreadSafeArenazSamplerTest, LargeSampleParameter) {
  SetThreadSafeArenazEnabled(true);
  SetThreadSafeArenazSampleParameter(std::numeric_limits<int32_t>::max());
  constexpr int64_t kTestStride = 0;

  for (int i = 0; i < 1000; ++i) {
    SamplingState sampling_state = {kTestStride, kTestStride};
    ThreadSafeArenaStats* sample = SampleSlow(sampling_state);
    EXPECT_GT(sampling_state.next_sample, 0);
    EXPECT_NE(sample, nullptr);
    UnsampleSlow(sample);
  }
}

TEST(ThreadSafeArenazSamplerTest, Sample) {
  SetThreadSafeArenazEnabled(true);
  SetThreadSafeArenazSampleParameter(100);
  SetThreadSafeArenazGlobalNextSample(0);
  int64_t num_sampled = 0;
  int64_t total = 0;
  double sample_rate = 0.0;
  for (int i = 0; i < 1000000; ++i) {
    ThreadSafeArenaStatsHandle h = Sample();
    ++total;
    if (ThreadSafeArenaStatsHandlePeer::IsSampled(h)) {
      ++num_sampled;
    }
    sample_rate = static_cast<double>(num_sampled) / total;
    if (0.005 < sample_rate && sample_rate < 0.015) break;
  }
  EXPECT_NEAR(sample_rate, 0.01, 0.005);
}

TEST(ThreadSafeArenazSamplerTest, Handle) {
  auto& sampler = GlobalThreadSafeArenazSampler();
  constexpr int64_t kTestStride = 17;
  ThreadSafeArenaStatsHandle h(sampler.Register(kTestStride));
  auto* info = ThreadSafeArenaStatsHandlePeer::GetInfo(&h);
  info->block_histogram[0].bytes_allocated.store(0x12345678,
                                                 std::memory_order_relaxed);

  bool found = false;
  sampler.Iterate([&](const ThreadSafeArenaStats& h) {
    if (&h == info) {
      EXPECT_EQ(
          h.block_histogram[0].bytes_allocated.load(std::memory_order_relaxed),
          0x12345678);
      EXPECT_EQ(h.weight, kTestStride);
      found = true;
    }
  });
  EXPECT_TRUE(found);

  h = ThreadSafeArenaStatsHandle();
  found = false;
  sampler.Iterate([&](const ThreadSafeArenaStats& h) {
    if (&h == info) {
      // this will only happen if some other thread has resurrected the info
      // the old handle was using.
      if (h.block_histogram[0].bytes_allocated.load(
              std::memory_order_relaxed) == 0x12345678) {
        found = true;
      }
    }
  });
  EXPECT_FALSE(found);
}

TEST(ThreadSafeArenazSamplerTest, Registration) {
  ThreadSafeArenazSampler sampler;
  constexpr int64_t kTestStride = 100;
  auto* info1 = Register(&sampler, 1, kTestStride);
  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1));

  auto* info2 = Register(&sampler, 2, kTestStride);
  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 2));
  info1->block_histogram[0].bytes_allocated.store(3, std::memory_order_relaxed);
  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(3, 2));

  sampler.Unregister(info1);
  sampler.Unregister(info2);
}

TEST(ThreadSafeArenazSamplerTest, Unregistration) {
  ThreadSafeArenazSampler sampler;
  std::vector<ThreadSafeArenaStats*> infos;
  constexpr int64_t kTestStride = 200;
  for (size_t i = 0; i < 3; ++i) {
    infos.push_back(Register(&sampler, i + 1, kTestStride));
  }
  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 2, 3));

  sampler.Unregister(infos[1]);
  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 3));

  infos.push_back(Register(&sampler, 3, kTestStride));
  infos.push_back(Register(&sampler, 4, kTestStride));
  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 3, 3, 4));
  sampler.Unregister(infos[3]);
  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 3, 4));

  sampler.Unregister(infos[0]);
  sampler.Unregister(infos[2]);
  sampler.Unregister(infos[4]);
  EXPECT_THAT(GetBytesAllocated(&sampler), IsEmpty());
}

// This will log the following:
// ```
// Tagged seed sequence (ABSL_RANDOM_SALT_OVERRIDE=fBAY_g): SEED_MT_0=XVKmv...
// Tagged seed sequence (ABSL_RANDOM_SALT_OVERRIDE=fBAY_g): SEED_MT_1=5wvqx...
//   ...
// ```
// To try to reproduce a run using the same random sequence, do this:
//   $ export SEED_MT_0=XVKmv... SEED_MT_1=5wvqx... ... bazel test <this test>
TEST(ThreadSafeArenazSamplerTest, MultiThreaded) {
  ThreadSafeArenazSampler sampler;
  absl::Notification stop;
  ThreadPool pool(10);

  for (int i = 0; i < 10; ++i) {
    const int64_t sampling_stride = 11 + i % 3;
    pool.Schedule([i, &sampler, &stop, sampling_stride]() {
      absl::BitGen bitgen{absl::MakeTaggedSeedSeq(
          /*env_var=*/absl::StrCat("SEED_", test_info_->name(), "_", i).c_str(),
          /*stream=*/absl::LogInfoStreamer().stream())};
      std::vector<ThreadSafeArenaStats*> infoz;
      while (!stop.HasBeenNotified()) {
        if (infoz.empty()) {
          infoz.push_back(sampler.Register(sampling_stride));
        }
        switch (absl::Uniform(absl::IntervalClosedClosed, bitgen, 0, 1)) {
          case 0: {
            infoz.push_back(sampler.Register(sampling_stride));
            break;
          }
          case 1: {
            size_t p = absl::Uniform<size_t>(bitgen, 0, infoz.size());
            ThreadSafeArenaStats* info = infoz[p];
            infoz[p] = infoz.back();
            infoz.pop_back();
            EXPECT_EQ(info->weight, sampling_stride);
            sampler.Unregister(info);
            break;
          }
          default:
            ABSL_UNREACHABLE();
            break;
        }
      }
    });
  }
  // The threads will hammer away.  Give it a little bit of time for tsan to
  // spot errors.
  absl::SleepFor(absl::Seconds(3));
  stop.Notify();
}

TEST(ThreadSafeArenazSamplerTest, Callback) {
  ThreadSafeArenazSampler sampler;
  constexpr int64_t kTestStride = 203;

  auto* info1 = Register(&sampler, 1, kTestStride);
  auto* info2 = Register(&sampler, 2, kTestStride);

  static const ThreadSafeArenaStats* expected;

  auto callback = [](const ThreadSafeArenaStats& info) {
    // We can't use `info` outside of this callback because the object will be
    // disposed as soon as we return from here.
    EXPECT_EQ(&info, expected);
  };

  // Set the callback.
  EXPECT_EQ(sampler.SetDisposeCallback(callback), nullptr);
  expected = info1;
  sampler.Unregister(info1);

  // Unset the callback.
  EXPECT_EQ(callback, sampler.SetDisposeCallback(nullptr));
  expected = nullptr;  // no more calls.
  sampler.Unregister(info2);
}

TEST(ThreadSafeArenazSamplerTest, InitialBlockReportsZeroUsedAndWasted) {
  SetThreadSafeArenazEnabled(true);
  // Setting 1 as the parameter value means one in every two arenas would be
  // sampled, on average.
  int32_t oldparam = ThreadSafeArenazSampleParameter();
  SetThreadSafeArenazSampleParameter(1);
  SetThreadSafeArenazGlobalNextSample(0);
  constexpr int kSize = 571;
  int count_found_allocation = 0;
  auto& sampler = GlobalThreadSafeArenazSampler();
  for (int i = 0; i < 10; ++i) {
    char block[kSize];
    google::protobuf::Arena arena(/*initial_block=*/block, /*initial_block_size=*/kSize);
    benchmark::DoNotOptimize(&arena);
    sampler.Iterate([&](const ThreadSafeArenaStats& h) {
      const auto& histbin =
          h.block_histogram[ThreadSafeArenaStats::FindBin(kSize)];
      if (histbin.bytes_allocated.load(std::memory_order_relaxed) == kSize) {
        count_found_allocation++;
        EXPECT_EQ(histbin.bytes_used, 0);
        EXPECT_EQ(histbin.bytes_wasted, 0);
      }
    });
  }
  EXPECT_GT(count_found_allocation, 0);
  SetThreadSafeArenazSampleParameter(oldparam);
}

class ThreadSafeArenazSamplerTestThread : public Thread {
 protected:
  void Run() override {
    google::protobuf::ArenaSafeUniquePtr<
        protobuf_test_messages::proto2::TestAllTypesProto2>
        message = google::protobuf::MakeArenaSafeUnique<
            protobuf_test_messages::proto2::TestAllTypesProto2>(arena_);
    ABSL_CHECK(message != nullptr);
    // Signal that a message on the arena has been created.  This should create
    // a SerialArena for this thread.
    if (barrier_->Block()) {
      delete barrier_;
    }
  }

 public:
  ThreadSafeArenazSamplerTestThread(const thread::Options& options,
                                    absl::string_view name,
                                    google::protobuf::Arena* arena,
                                    absl::Barrier* barrier)
      : Thread(options, name), arena_(arena), barrier_(barrier) {}

 private:
  google::protobuf::Arena* arena_;
  absl::Barrier* barrier_;
};

TEST(ThreadSafeArenazSamplerTest, MultiThread) {
  SetThreadSafeArenazEnabled(true);
  // Setting 1 as the parameter value means one in every two arenas would be
  // sampled, on average.
  int32_t oldparam = ThreadSafeArenazSampleParameter();
  SetThreadSafeArenazSampleParameter(1);
  SetThreadSafeArenazGlobalNextSample(0);
  auto& sampler = GlobalThreadSafeArenazSampler();
  int count = 0;
  for (int i = 0; i < 10; ++i) {
    const int kNumThreads = 10;
    absl::Barrier* barrier = new absl::Barrier(kNumThreads + 1);
    google::protobuf::Arena arena;
    thread::Options options;
    options.set_joinable(true);
    std::vector<std::unique_ptr<ThreadSafeArenazSamplerTestThread>> threads;
    for (int i = 0; i < kNumThreads; i++) {
      auto t = std::make_unique<ThreadSafeArenazSamplerTestThread>(
          options, absl::StrCat("thread", i), &arena, barrier);
      t->Start();
      threads.push_back(std::move(t));
    }
    // Wait till each thread has created a message on the arena.
    if (barrier->Block()) {
      delete barrier;
    }
    sampler.Iterate([&](const ThreadSafeArenaStats& h) { ++count; });
    for (int i = 0; i < kNumThreads; i++) {
      threads[i]->Join();
    }
  }
  EXPECT_GT(count, 0);
  SetThreadSafeArenazSampleParameter(oldparam);
}

class SampleFirstArenaThread : public Thread {
 protected:
  void Run() override {
    google::protobuf::Arena arena;
    google::protobuf::ArenaSafeUniquePtr<
        protobuf_test_messages::proto2::TestAllTypesProto2>
        message = google::protobuf::MakeArenaSafeUnique<
            protobuf_test_messages::proto2::TestAllTypesProto2>(&arena);
    ABSL_CHECK(message != nullptr);
    arena_created_.Notify();
    samples_counted_.WaitForNotification();
  }

 public:
  explicit SampleFirstArenaThread(const thread::Options& options)
      : Thread(options, "SampleFirstArenaThread") {}

  absl::Notification arena_created_;
  absl::Notification samples_counted_;
};

// Test that the first arena created on a thread may and may not be chosen for
// sampling.
TEST(ThreadSafeArenazSamplerTest, SampleFirstArena) {
  SetThreadSafeArenazEnabled(true);
  auto& sampler = GlobalThreadSafeArenazSampler();

  enum class SampleResult {
    kSampled,
    kUnsampled,
    kSpoiled,
  };

  auto count_samples = [&]() {
    int count = 0;
    sampler.Iterate([&](const ThreadSafeArenaStats& h) { ++count; });
    return count;
  };

  auto run_sample_experiment = [&]() {
    int before = count_samples();
    thread::Options options;
    options.set_joinable(true);
    SampleFirstArenaThread t(options);
    t.Start();
    t.arena_created_.WaitForNotification();
    int during = count_samples();
    t.samples_counted_.Notify();
    t.Join();
    int after = count_samples();

    // If we didn't get back where we were, some other thread may have
    // created an arena and produced an invalid experiment run.
    if (before != after) return SampleResult::kSpoiled;

    switch (during - before) {
      case 1:
        return SampleResult::kSampled;
      case 0:
        return SampleResult::kUnsampled;
      default:
        return SampleResult::kSpoiled;
    }
  };

  constexpr int kTrials = 10000;
  bool sampled = false;
  bool unsampled = false;
  for (int i = 0; i < kTrials; ++i) {
    switch (run_sample_experiment()) {
      case SampleResult::kSampled:
        sampled = true;
        break;
      case SampleResult::kUnsampled:
        unsampled = true;
        break;
      default:
        break;
    }

    // This is the success criteria for the entire test.  At some point
    // we sampled the first arena and at some point we did not.
    if (sampled && unsampled) return;
  }
  EXPECT_TRUE(sampled);
  EXPECT_TRUE(unsampled);
}

TEST(ThreadSafeArenazSamplerTest, UsedAndWasted) {
  SetThreadSafeArenazEnabled(true);
  int32_t oldparam = ThreadSafeArenazSampleParameter();
  SetThreadSafeArenazSampleParameter(1);
  SetThreadSafeArenazGlobalNextSample(0);
  auto& sampler = GlobalThreadSafeArenazSampler();
  google::protobuf::Arena arena;
  // Do enough small allocations to completely fill 3 first blocks.
  // Test that they are fully used and none wasted.
  for (int i = 0; i < 1000; ++i) {
    Arena::Create<char>(&arena);
  }
  sampler.Iterate([&](const ThreadSafeArenaStats& h) {
    for (size_t i = 0; i < 3; ++i) {
      constexpr auto kSize =
          google::protobuf::internal::AllocationPolicy::kDefaultStartBlockSize;
      const auto& histbin =
          h.block_histogram[ThreadSafeArenaStats::FindBin(kSize << i)];
      EXPECT_EQ(histbin.bytes_allocated, kSize << i);
      EXPECT_EQ(histbin.bytes_used,
                (kSize << i) - google::protobuf::internal::SerialArena::kBlockHeaderSize);
      EXPECT_EQ(histbin.bytes_wasted, 0);
    }
  });
  SetThreadSafeArenazSampleParameter(oldparam);
}
#endif  // defined(PROTOBUF_ARENAZ_SAMPLE)

}  // namespace
}  // namespace internal
}  // namespace protobuf
}  // namespace google

#include "google/protobuf/port_undef.inc"
