POCO (Portable Components)

repository·main·Indexed 27 days ago

https://github.com/pocoproject/poco

A collection of C++ class libraries for internet-age, network-centric applications. POCO provides portable solutions for embedded to server environments, including components for MongoDB, DNS-SD (Zeroconf), and an SQL Parser. It supports flexible dependency management via the POCO_UNBUNDLED flag for libraries like zlib, pcre2, and sqlite3, and includes a comprehensive benchmark suite based on Google Benchmark.

Tokens
16.3K
Snippets
37
Records
84
Agent score
94%

What's inside POCO

  1. Overview of POCO C++ Libraries

    main

    POCO (Portable Components) is a collection of C++ class libraries designed to solve frequently-encountered practical problems, specifically for 'internet-age' network-centric applications.

    Key characteristics:

    • Conceptually similar to the Java Class Library, .NET Framework, or Apple's Cocoa.
    • Written in efficient, modern, 100% ANSI/ISO Standard C++.
    • Complements the C++ Standard Library (STL).
    • Highly portable across many platforms.
    • Open Source, licensed under the Boost Software License.
  2. Understand MongoDB Replica Set SDAM Compliance

    main

    The Poco::MongoDB implementation follows the MongoDB Server Discovery and Monitoring (SDAM) Specification.

    Implemented Features

    • Server Type Detection: Identifies Primary, Secondary, Arbiter, Standalone, Mongos, etc.
    • Topology Discovery: Discovers members via hello command responses.
    • Background Monitoring: Periodic heartbeat checks (default 10s, minimum 500ms).
    • Topology Type Detection: Supports Single, ReplicaSetWithPrimary, ReplicaSetNoPrimary, Sharded, and Unknown.
    • Read Preference Support: All 5 modes including tag-based selection.
    • Automatic Failover: Detects and recovers from server failures.
    • Cross-Contamination Prevention: Prevents adding hosts from mismatched replica sets.

    Known Limitations & Risks

    • Security: Missing "me" field validation (risk of topology poisoning).
    • Data Integrity: Missing setVersion and electionId tracking (potential split-brain during network partitions).
    • Topology Management: Server removal logic is incomplete; decommissioned servers may remain in the topology indefinitely.
    • Staleness: Uses updateTime instead of lastWriteDate for staleness calculations.
    • Latency: The "nearest" read preference selects members randomly rather than using RTT-based selection.
  3. Getting started with POCO

    main

    To begin using the POCO libraries, refer to the official documentation for the Guided Tour and Getting Started guides.

    Note: The links below point to documentation for version 1.5.3. For newer versions, please visit the official POCO website.

  4. Build the Poco Benchmark suite

    main

    To build the benchmarks, ensure you have Poco Foundation and Poco Util installed. Use one of the following methods depending on your environment.

    Using Make (Linux/macOS):

    cd poco
    make -C Benchmark

    Using CMake (Linux/macOS):

    cmake -B build -DENABLE_BENCHMARK=ON
    cmake --build build --target Benchmark

    Using CMake (Windows): Note: Use the Ninja generator for reliable builds on Windows. Ensure CMAKE_PREFIX_PATH points to your Google Benchmark installation.

    cmake -B build -G Ninja -DENABLE_BENCHMARK=ON -DCMAKE_PREFIX_PATH=C:\local
    cmake --build build --target Benchmark
    cmake -B build -DENABLE_BENCHMARK=ON
    cmake --build build --target Benchmark
  5. Write a new Poco Benchmark

    main

    To add a new benchmark, create a .cpp file in the src/ directory. Use the benchmark::State object to control the loop and benchmark::DoNotOptimize to prevent compiler optimizations from skewing results.

    Example Benchmark Implementation:

    #include <benchmark/benchmark.h>
    #include "Poco/MyComponent.h"
    
    using Poco::MyComponent;
    
    static void BM_MyOperation(benchmark::State& state)
    {
        MyComponent component;
    
        for (auto _ : state)
        {
            auto result = component.doSomething();
            benchmark::DoNotOptimize(result);
        }
    
        state.SetBytesProcessed(state.iterations() * sizeof(result));
    }
    BENCHMARK(BM_MyOperation);

    Registering the new benchmark:

    1. Update CMakeLists.txt:
    set(SRCS
        src/BenchmarkApp.cpp
        src/PatternFormatterBench.cpp
        src/MyComponentBench.cpp  # Add your file here
    )
    1. Update Makefile:
    objects = BenchmarkApp PatternFormatterBench MyComponentBench
    static void BM_MyOperation(benchmark::State& state)
    {
        MyComponent component;
        for (auto _ : state)
        {
            auto result = component.doSomething();
            benchmark::DoNotOptimize(result);
        }
    }
    BENCHMARK(BM_MyOperation);
  6. Unbundle Poco dependencies using POCO_UNBUNDLED

    main

    By default, Poco uses bundled versions of certain third-party libraries located in the dependencies/ directory. If you prefer to use system-installed versions of these libraries instead, you can enable the POCO_UNBUNDLED flag.

    When enabled, Poco will attempt to locate the libraries using find_package() (in CMake) or -l flags (in GNU Make).

    Supported Unbundleable Libraries:

    • zlib (Foundation: compression/decompression)
    • pcre2 (Foundation: regular expressions)
    • utf8proc (Foundation: Unicode normalization)
    • expat (XML: SAX/DOM parser)
    • sqlite3 (Data/SQLite: embedded database)
    • png (PDF: PNG image support)
  7. Monitor Topology Changes via Notifications

    main

    The ReplicaSet automatically posts TopologyChangeNotification objects to Poco::NotificationCenter::defaultCenter() whenever the topology changes (e.g., primary election, server count changes, or type changes). You can use NObserver to listen for these changes without manual polling.

    #include "Poco/MongoDB/ReplicaSet.h"
    #include "Poco/MongoDB/TopologyChangeNotification.h"
    #include "Poco/NotificationCenter.h"
    #include "Poco/NObserver.h"
    
    class MyMongoObserver {
    public:
        MyMongoObserver() {
            NotificationCenter::defaultCenter().addNObserver(*this, &MyMongoObserver::handleTopologyChange);
        }
        ~MyMongoObserver() {
            NotificationCenter::defaultCenter().removeNObserver(*this);
        }
        void handleTopologyChange(const AutoPtr<TopologyChangeNotification>& pNf) {
            const auto& data = pNf->data();
            std::string topologyType = data["topologyType"];
            // React to "Replica Set (with Primary)" or "Replica Set (no Primary)"
        }
    };
  8. Build POCO DNS-SD without CMake

    main

    You can build the library without CMake using the following methods:

    • Windows: Build the included Visual C++ solution.
    • Linux/macOS: Set the POCO_BASE environment variable to the root of your POCO source tree, then use make within the DNSSD directory.
    $ export POCO_BASE=`pwd`
    $ cd DNSSD
    $ make -s -j8
    $ make -s -j8 -C Default
  9. Configure TLS/SSL connections

    main
    Poco::MongoDB does not provide a built-in TLS factory. To use secure connections, you must supply a custom SocketFactory that returns a Poco::Net::SecureStreamSocket. In connection URIs, the tls= option is an alias for the historical ssl= option (supported since 1.15.x).
  10. Build MongoDB Replica Set support with CMake

    main

    To build the MongoDB components, ensure ENABLE_MONGODB=ON is passed to CMake. You can build specific targets like MongoDB, ReplicaSetMonitor, ReplicaSet, or URIExample.

    cd poco
    mkdir build && cd build
    cmake .. -DENABLE_MONGODB=ON -DENABLE_SAMPLES=ON -DENABLE_TESTS=OFF
    cmake --build . --target MongoDB
    cmake --build . --target ReplicaSetMonitor
    cmake --build . --target ReplicaSet
    cmake --build . --target URIExample
  11. Porting from NetSSL_OpenSSL to NetSSL_Win

    main

    NetSSL_Win is a Schannel-based implementation of the POCO NetSSL library. While code based on NetSSL_OpenSSL can generally be ported with minor changes, be aware of the following API differences:

    Context Differences

    • Constructor: The Context constructor uses different arguments. Instead of a certificate file name, you must specify a certificate subject name.
    • Certificate Loading: Certificates can be loaded from the Windows certificate store or from PKCS #12 files (.pfx, .p12) if OPT_LOAD_CERT_FROM_FILE is specified. If using files, a private key passphrase handler must be set up.
    • Unavailable Methods: The following methods are not available in NetSSL_Win:
      • addChainCertificate()
      • disableStatelessSessionResumption()
      • enableSessionCache()
      • flushSessionCache()
      • getSessionCacheSize()
      • getSessionTimeout()
      • setSessionCacheSize()
      • setSessionTimeout()
      • sslContext()
      • useCertificate()
      • usePrivateKey()

    SSLManager Differences

    • Configuration properties differ from NetSSL_OpenSSL. Refer to the SSLManager header file for the correct properties.
    • The isFIPSEnabled() method is not available.

    X509Certificate Differences

    • Saving a certificate is not supported.