ThorsAnvil

Home API Documentation

Internal: Mug · ThorsMug · ThorsSlack · NisseServer · NisseHTTP · ThorsSocket · ThorsCrypto · ThorsSerializer · ThorsMongo · ThorsLogging · ThorsIOUtil


ThorsMongo Internal Documentation

Detailed architecture, message flow, cursor/range mechanics, and class-level documentation for the ThorsMongo MongoDB client.

Source: third/ThorsMongo/src/ThorsMongo/


Table of Contents


File Map

File Purpose
ThorsMongo.h/.cpp Public entry point (ThorsMongo, DB, Collection) and connection-owned cursor helpers (getMore(), killCursor()).
ConnectionMongo.h/.cpp ConnectionMongo stream wrapper around a MongoDB TCP connection (built on ThorsSocket iostreams).
ConnectionBufferMongo.h/.cpp std::streambuf implementation tuned for Mongo wire protocol framing and buffering.
MessageHandler.h/.cpp MessageHandler base + MongoActionWriteInterface / MongoActionReadInterface used by all commands. Builds OP_MSG / OP_COMPRESSED.
Authenticate.h/.cpp High-level authentication orchestration.
AuthenticateScramSha.h/.cpp SCRAM-SHA-* implementation (currently the primary mechanism in this codebase).
AuthInfo.h Authentication payload types (username/password, certificates, etc.).
AuthClient.h/.cpp Client metadata sent to server during handshake (Auth::Client).
MongoUtil.h Macro machinery for field-access generation and for creating filter/update types (ThorsMongo_CreateFieldAccess, ThorsMongo_FilterFromAccess, ThorsMongo_UpdateFromAccess). Also common enums (op codes, compression, flags).
MongoQuery.h Query operator types (e.g. Eq, Gt, And, Exists, …) + Query<T> wrapper used by remove and some commands.
MongoUpdate.h Update operator types (e.g. Set, Inc, Unset, Push, …).
ThorsMongoCommon.h/.cpp Shared types: CmdReplyBase, sort/projection helpers, ActionConfig<> base for command configs, cluster time metadata, write error structures.
MongoCursor.h Cursor model + generic Range<R> and input iterator + CursorData<T> lifetime and paging logic.
ThorsMongoInsert.h/.tpp insert command builder + InsertResult.
ThorsMongoFind.h/.tpp find command builder + FindRange<T> and FindResult<T> glue.
ThorsMongoGetMore.h/.tpp getMore paging command.
ThorsMongoKillCursor.h/.tpp killCursors cleanup command.
ThorsMongoRemove.h/.tpp delete/remove command builder.
ThorsMongoFindAndModify.h/.tpp findAndModify family (findAndReplaceOne, findAndRemoveOne, findAndUpdateOne).
ThorsMongoCount.h/.tpp countDocuments command builder.
ThorsMongoDistinct.h/.tpp distinct command builder.
ThorsMongoListDatabase.h/.tpp listDatabases command builder + range wrapper.
ThorsMongoListCollection.h/.tpp listCollections command builder + range wrapper.
ThorsMongoAdmin.h/.tpp Admin commands like renameCollection, drop, createCollection.
ReadConcern.h / WriteConcern.h Read/write concern payloads.
test/* Unit + integration tests and generated mocking hooks.

Architecture Overview

At a high level, ThorsMongo is a thin command layer over:

┌───────────────────────────────────────────────────────────┐
│                    Application code                        │
│  ThorsMongo / DB / Collection                              │
│  Filters (QueryOp + field access macros)                   │
│  Updates (QueryOp + field access macros)                   │
├───────────────────────────────────────────────────────────┤
│               Command builder objects                       │
│  Insert / Find / Remove / FindAndModify / Distinct / ...    │
├───────────────────────────────────────────────────────────┤
│     MessageHandler (OP_MSG / OP_COMPRESSED / checksum)      │
├───────────────────────────────────────────────────────────┤
│   ConnectionMongo (iostream) + ConnectionBufferMongo        │
│   built on ThorsSocket::BaseSocketStream                    │
├───────────────────────────────────────────────────────────┤
│                       TCP socket                            │
└───────────────────────────────────────────────────────────┘

Public Facade Types (Thin Handles)

ThorsMongo

File: ThorsMongo.h

Owns:

Exposes:

DB

File: ThorsMongo.h

Lightweight handle consisting of:

Exposes:

Collection

File: ThorsMongo.h

Lightweight handle consisting of:

Exposes the core data operations:

Also exposes helpers:


Connection and Streams

ConnectionMongo

File: ConnectionMongo.h

ConnectionMongo is a std::iostream (via ThorsSocket::BaseSocketStream<ConnectionBufferMongo>) that connects to the MongoDB host/port.

Key points:

MongoMessageHandler

File: ThorsMongo.h

Concrete MessageHandler that owns a ConnectionMongo and returns it via getStream().

This is the bridge between:


MessageHandler and Message Framing

MongoActionWriteInterface / MongoActionReadInterface

File: MessageHandler.h

These are the internal “capability” interfaces for any object that can be sent to or received from MongoDB:

For most command objects and reply objects, ThorsMongo uses trivial adapters:

This keeps command classes simple: they just need to be ThorsSerializer-trait’d.

MessageHandler

File: MessageHandler.h/.cpp

Responsibilities:

High-level flow:

Command object (traits) ──writeBson()──► MessageHandler ──► ConnectionMongo stream
Reply object   (traits) ◄──readBson()── MessageHandler ◄── ConnectionMongo stream

Command Objects (Insert/Find/Remove/etc.)

Each MongoDB command is represented by a small “command object” that:

Common patterns:

Important nuance:


Cursor-backed Ranges

Cursor model

File: MongoCursor.h

MongoDB cursors are represented as:

Only the CursorFirst<T> instance is kept in the long-lived cursor state; when getMore returns, CursorNext<T> is swapped/moved into CursorFirst<T>.

Range<R> and CursorIterator

File: MongoCursor.h

Range<R> is the shared implementation used by multiple “range results”:

It holds a std::shared_ptr<R>; copying the range shares the same cursor state.

Iteration uses a single-pass input iterator:

CursorData<T> paging and cleanup

File: MongoCursor.h (class), ThorsMongo.h (destructor + paging glue)

CursorData<T> owns:

Two key behaviors:

This is why ThorsMongo::getMore() / killCursor() are private but CursorData<T> is a friend.


Filters (MongoQuery) and Updates (MongoUpdate)

Query operator types

File: MongoQuery.h

Mongo query operators are modeled as small types in ThorsAnvil::DB::Mongo::QueryOp:

Each operator type:

Update operator types

File: MongoUpdate.h

Updates follow the same idea but emit update documents ($set, $inc, …). Examples include:

Field access + macro generation

File: MongoUtil.h

The key ergonomics trick is: you declare a “field access” once, and then derive many query/update types from it.

Internally these macros:


Config Objects and Error Model

CmdReplyBase

File: MongoUtil.h / ThorsMongoCommon.h

Most results derive from CmdReplyBase which provides:

This is what enables the idiom:

auto result = collection.insert(data);
if (!result) {
    std::cerr << "Error: " << result << "\n";
}

ActionConfig<T>

File: ThorsMongoCommon.h

All command-specific config types derive from ActionConfig<>, which centralizes low-level behavior:

Command config classes then add their own optional parameters and expose fluent setters.


Concerns and Preferences

ThorsMongo supports setting defaults and overrides at multiple levels:

Types involved:

The DB and Collection handles implement get*/set* by delegating into those maps via the shared owning ThorsMongo.


Endianness and BSON

MongoDB wire protocol and BSON are little-endian. The code enforces that at compile time:

If big-endian support is needed in the future, all “write integers to wire” helpers in the message framing path need to be audited and endian-corrected.


Header-Only Mode

ThorsMongo can be built in a “header-only” configuration when ThorsSerializer is in header-only mode.

Pattern:

#if defined(THORS_SERIALIZER_HEADER_ONLY) && THORS_SERIALIZER_HEADER_ONLY == 1
// ...
#include "ThorsMongo.source"
#endif

This mirrors the approach used across ThorsAnvil libraries: it avoids separate compilation while keeping a single code path.


Testing and Mocking

Tests live under third/ThorsMongo/src/ThorsMongo/test/ and include:

Mocking infrastructure is generated into src/ThorsMongo/coverage/MockHeaders.h and included by test/MockHeaderInclude.h. In non-test builds, mock macros resolve to the real underlying functions; in test builds, they can be redirected to injected lambdas.