Coverage Report

Created: 2025-07-03 06:58

/src/Fast-DDS/src/cpp/rtps/persistence/SQLite3PersistenceService.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2018 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
 * @file SQLite3PersistenceService.cpp
17
 *
18
 */
19
20
#include <rtps/persistence/SQLite3PersistenceService.h>
21
#include <rtps/persistence/SQLite3PersistenceServiceStatements.h>
22
#include <fastdds/dds/log/Log.hpp>
23
#include <fastdds/rtps/history/WriterHistory.hpp>
24
25
#include <rtps/persistence/sqlite3.h>
26
27
#include <sstream>
28
29
namespace eprosima {
30
namespace fastdds {
31
namespace rtps {
32
33
/**
34
 * @brief Retrieve the schema version of the database
35
 * @param db [IN] Database of which we want to get the schema version
36
 * @return Integer representing the schema version. Zero if an error occurs during the processing.
37
 */
38
static unsigned int database_version(
39
        sqlite3* db)
40
0
{
41
0
    sqlite3_stmt* version_stmt;
42
0
    unsigned int version = 1;
43
0
    if (sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &version_stmt, NULL) != SQLITE_OK)
44
0
    {
45
0
        return 0;
46
0
    }
47
48
0
    if (SQLITE_ROW == sqlite3_step(version_stmt))
49
0
    {
50
0
        version = sqlite3_column_int(version_stmt, 0);
51
0
        if (version == 0)
52
0
        {
53
            //No version information. It really means version 1
54
0
            version = 1;
55
0
        }
56
0
    }
57
0
    sqlite3_finalize(version_stmt);
58
0
    return version;
59
0
}
60
61
static int upgrade(
62
        sqlite3* db,
63
        int from,
64
        int to)
65
0
{
66
0
    if (from == to)
67
0
    {
68
0
        return SQLITE_OK;
69
0
    }
70
71
0
    if (from == 1 && to == 2)
72
0
    {
73
0
        return sqlite3_exec(db, SQLite3PersistenceServiceSchemaV2::update_from_v1_statement().c_str(), 0, 0, 0);
74
0
    }
75
76
0
    if (from == 2 && to == 3
77
0
            && SQLite3PersistenceServiceSchemaV3::database_create_temporary_defaults_table(db))
78
0
    {
79
0
        return sqlite3_exec(db, SQLite3PersistenceServiceSchemaV3::update_from_v2_statement().c_str(), 0, 0, 0);
80
0
    }
81
82
    // iterate if not direct upgrade
83
0
    if (from < to)
84
0
    {
85
0
        if (SQLITE_ERROR != upgrade(db, from, to - 1))
86
0
        {
87
0
            return upgrade(db, to - 1, to);
88
0
        }
89
0
    }
90
91
    // unsupported upgrade path
92
0
    EPROSIMA_LOG_ERROR(RTPS_PERSISTENCE, "Unsupported database upgrade from version " << from << " to version " << to);
93
0
    return SQLITE_ERROR;
94
0
}
95
96
static sqlite3* open_or_create_database(
97
        const char* filename,
98
        bool update_schema)
99
0
{
100
0
    sqlite3* db = NULL;
101
0
    int rc;
102
0
    int version = 3;
103
104
    // Open database
105
0
    int flags = SQLITE_OPEN_READWRITE |
106
0
            SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_SHAREDCACHE;
107
0
    rc = sqlite3_open_v2(filename, &db, flags, 0); // malloc that is not erased
108
0
    if (rc != SQLITE_OK)
109
0
    {
110
        // In case file cantopen, memory is reserved in db, so it must be free (for valgrind sake)
111
0
        if (rc == SQLITE_CANTOPEN)
112
0
        {
113
0
            sqlite3_close(db);
114
0
        }
115
116
        //probably the database does not exists. Create new and no need to upgrade schema
117
0
        flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
118
0
                SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_SHAREDCACHE;
119
0
        rc = sqlite3_open_v2(filename, &db, flags, 0);
120
0
        if (rc != SQLITE_OK)
121
0
        {
122
0
            EPROSIMA_LOG_ERROR(RTPS_PERSISTENCE, "Unable to create persistence database " << filename);
123
0
            sqlite3_close(db);
124
0
            return NULL;
125
0
        }
126
0
    }
127
0
    else
128
0
    {
129
        // Find the database version and handle upgrades
130
0
        int db_version = database_version(db);
131
0
        if (db_version == 0)
132
0
        {
133
0
            EPROSIMA_LOG_ERROR(RTPS_PERSISTENCE, "Error retrieving version on database " << filename);
134
0
            sqlite3_close(db);
135
0
            return NULL;
136
0
        }
137
0
        if (db_version != version)
138
0
        {
139
0
            if (update_schema)
140
0
            {
141
0
                rc = upgrade(db, db_version, version);
142
0
                if (rc != SQLITE_OK)
143
0
                {
144
0
                    sqlite3_close(db);
145
0
                    return NULL;
146
0
                }
147
0
            }
148
0
            else
149
0
            {
150
0
                EPROSIMA_LOG_ERROR(RTPS_PERSISTENCE, "Old schema version " << db_version << " on database " << filename
151
0
                                                                           << ". Set property dds.persistence.update_schema to force automatic schema upgrade");
152
0
                sqlite3_close(db);
153
0
                return NULL;
154
0
            }
155
156
0
        }
157
0
    }
158
159
    // Create tables if they don't exist
160
0
    rc = sqlite3_exec(db, SQLite3PersistenceServiceSchemaV3::database_create_statement().c_str(), 0, 0, 0);
161
0
    if (rc != SQLITE_OK)
162
0
    {
163
0
        sqlite3_close(db);
164
0
        return NULL;
165
0
    }
166
167
0
    return db;
168
0
}
169
170
static void finalize_statement(
171
        sqlite3_stmt*& stmt)
172
0
{
173
0
    if (stmt != NULL)
174
0
    {
175
0
        int res = sqlite3_finalize(stmt);
176
0
        if (res != SQLITE_OK)
177
0
        {
178
0
            EPROSIMA_LOG_WARNING(RTPS_PERSISTENCE, "Statement could not be finalized. sqlite3_finalize code: " << res);
179
0
        }
180
0
        stmt = NULL;
181
0
    }
182
0
}
183
184
IPersistenceService* create_SQLite3_persistence_service(
185
        const char* filename,
186
        bool update_schema)
187
0
{
188
0
    sqlite3* db = open_or_create_database(filename, update_schema);
189
0
    return (db == NULL) ? nullptr : new SQLite3PersistenceService(db);
190
0
}
191
192
SQLite3PersistenceService::SQLite3PersistenceService(
193
        sqlite3* db)
194
0
    : db_(db)
195
    , load_writer_stmt_(NULL)
196
    , add_writer_change_stmt_(NULL)
197
    , remove_writer_change_stmt_(NULL)
198
    , load_writer_last_seq_num_stmt_(NULL)
199
    , update_writer_last_seq_num_stmt_(NULL)
200
    , load_reader_stmt_(NULL)
201
    , update_reader_stmt_(NULL)
202
0
{
203
    // Prepare writer statements
204
0
    sqlite3_prepare_v3(db_, "SELECT seq_num, instance, payload, related_sample_guid, related_sample_seq_num, source_timestamp "
205
0
            "FROM writers_histories WHERE guid=?;", -1,
206
0
            SQLITE_PREPARE_PERSISTENT,
207
0
            &load_writer_stmt_,
208
0
            NULL);
209
0
    sqlite3_prepare_v3(db_, "INSERT INTO writers_histories VALUES(?,?,?,?,?,?,?);", -1, SQLITE_PREPARE_PERSISTENT,
210
0
            &add_writer_change_stmt_, NULL);
211
0
    sqlite3_prepare_v3(db_, "DELETE FROM writers_histories WHERE guid=? AND seq_num=?;", -1, SQLITE_PREPARE_PERSISTENT,
212
0
            &remove_writer_change_stmt_, NULL);
213
214
0
    sqlite3_prepare_v3(db_, "SELECT last_seq_num FROM writers_states WHERE guid=?;", -1, SQLITE_PREPARE_PERSISTENT,
215
0
            &load_writer_last_seq_num_stmt_, NULL);
216
0
    sqlite3_prepare_v3(db_, "INSERT OR REPLACE INTO writers_states VALUES(?,?);", -1, SQLITE_PREPARE_PERSISTENT,
217
0
            &update_writer_last_seq_num_stmt_, NULL);
218
219
    // Prepare reader statements
220
0
    sqlite3_prepare_v3(db_, "SELECT writer_guid_prefix,writer_guid_entity,seq_num FROM readers WHERE guid=?;", -1,
221
0
            SQLITE_PREPARE_PERSISTENT, &load_reader_stmt_, NULL);
222
0
    sqlite3_prepare_v3(db_, "INSERT OR REPLACE INTO readers VALUES(?,?,?,?);", -1, SQLITE_PREPARE_PERSISTENT,
223
0
            &update_reader_stmt_, NULL);
224
0
}
225
226
SQLite3PersistenceService::~SQLite3PersistenceService()
227
0
{
228
    // Finalize writer statements
229
0
    finalize_statement(load_writer_stmt_);
230
0
    finalize_statement(add_writer_change_stmt_);
231
0
    finalize_statement(remove_writer_change_stmt_);
232
233
    // Finalize reader statements
234
0
    finalize_statement(load_reader_stmt_);
235
0
    finalize_statement(update_reader_stmt_);
236
237
    // Finalize writer seq_num statements
238
0
    finalize_statement(load_writer_last_seq_num_stmt_);
239
0
    finalize_statement(update_writer_last_seq_num_stmt_);
240
241
0
    int res = sqlite3_close(db_);
242
0
    if (res != SQLITE_OK) // (0) SQLITE_OK
243
0
    {
244
0
        EPROSIMA_LOG_ERROR(RTPS_PERSISTENCE, "Database could not be closed. sqlite3_close code: " << res);
245
0
    }
246
0
    db_ = NULL;
247
0
}
248
249
/**
250
 * Get all data stored for a writer.
251
 *
252
 * @param [in]     persistence_guid   GUID of the writer used to store samples.
253
 * @param [in]     writer_guid        GUID of the writer to load.
254
 * @param [in,out] history            History of the writer to load.
255
 * @param [out]    next_sequence      Sequence that should be applied to the next created sample.
256
 *
257
 * @return True if operation was successful.
258
 */
259
bool SQLite3PersistenceService::load_writer_from_storage(
260
        const std::string& persistence_guid,
261
        const GUID_t& writer_guid,
262
        WriterHistory* history,
263
        SequenceNumber_t& next_sequence)
264
0
{
265
0
    EPROSIMA_LOG_INFO(RTPS_PERSISTENCE, "Loading writer " << writer_guid);
266
267
0
    if (load_writer_stmt_ != NULL)
268
0
    {
269
0
        sqlite3_reset(load_writer_stmt_);
270
0
        sqlite3_bind_text(load_writer_stmt_, 1, persistence_guid.c_str(), -1, SQLITE_STATIC);
271
272
0
        std::vector<CacheChange_t*>& changes = get_changes(history);
273
274
0
        while (SQLITE_ROW == sqlite3_step(load_writer_stmt_))
275
0
        {
276
0
            SequenceNumber_t sn(sqlite3_column_int64(load_writer_stmt_, 0));
277
0
            CacheChange_t* change = nullptr;
278
0
            int size = sqlite3_column_bytes(load_writer_stmt_, 2);
279
280
0
            change = history->create_change(size, ALIVE);
281
0
            if (nullptr == change)
282
0
            {
283
0
                continue;
284
0
            }
285
286
0
            SampleIdentity identity;
287
0
            identity.writer_guid(writer_guid);
288
0
            identity.sequence_number(sn);
289
290
0
            int instance_size = sqlite3_column_bytes(load_writer_stmt_, 1);
291
0
            instance_size = (instance_size > 16) ? 16 : instance_size;
292
0
            change->kind = ALIVE;
293
0
            change->writerGUID = writer_guid;
294
0
            memcpy(change->instanceHandle.value, sqlite3_column_blob(load_writer_stmt_, 1), instance_size);
295
0
            change->sequenceNumber = identity.sequence_number();
296
0
            change->serializedPayload.length = size;
297
0
            memcpy(change->serializedPayload.data, sqlite3_column_blob(load_writer_stmt_, 2), size);
298
0
            change->writer_info.previous = nullptr;
299
0
            change->writer_info.next = nullptr;
300
0
            change->writer_info.num_sent_submessages = 0;
301
0
            change->vendor_id = c_VendorId_eProsima;
302
303
            // related sample identity
304
0
            {
305
0
                using namespace std;
306
                // GUID_t
307
0
                istringstream is(string(reinterpret_cast<const char*>(sqlite3_column_text(load_writer_stmt_, 3))));
308
0
                auto& si = change->write_params.related_sample_identity();
309
0
                is >> si.writer_guid();
310
                // Sequence Number
311
0
                SequenceNumber_t rsn(sqlite3_column_int64(load_writer_stmt_, 4));
312
0
                si.sequence_number(rsn);
313
0
            }
314
315
            // timestamp
316
0
            change->sourceTimestamp.from_ns(sqlite3_column_int64(load_writer_stmt_, 5));
317
318
0
            set_fragments(history, change);
319
320
0
            changes.insert(changes.begin(), change);
321
0
        }
322
323
0
        sqlite3_reset(load_writer_last_seq_num_stmt_);
324
0
        sqlite3_bind_text(load_writer_last_seq_num_stmt_, 1, persistence_guid.c_str(), -1, SQLITE_STATIC);
325
326
0
        while (SQLITE_ROW == sqlite3_step(load_writer_last_seq_num_stmt_))
327
0
        {
328
0
            next_sequence = SequenceNumber_t(sqlite3_column_int64(load_writer_last_seq_num_stmt_, 0));
329
0
        }
330
0
    }
331
332
0
    return true;
333
0
}
334
335
/**
336
 * Add a change to storage.
337
 * @param change The cache change to add.
338
 * @return True if operation was successful.
339
 */
340
bool SQLite3PersistenceService::add_writer_change_to_storage(
341
        const std::string& persistence_guid,
342
        const CacheChange_t& change)
343
0
{
344
0
    EPROSIMA_LOG_INFO(RTPS_PERSISTENCE,
345
0
            "Writer " << change.writerGUID << " storing change for seq " << change.sequenceNumber);
346
347
0
    if (add_writer_change_stmt_ != NULL)
348
0
    {
349
        //First add the last seq number, it is needed for the foreign key on writers_histories
350
0
        sqlite3_reset(update_writer_last_seq_num_stmt_);
351
0
        sqlite3_bind_text(update_writer_last_seq_num_stmt_, 1, persistence_guid.c_str(), -1, SQLITE_STATIC);
352
0
        sqlite3_bind_int64(update_writer_last_seq_num_stmt_, 2, change.sequenceNumber.to64long());
353
354
0
        if (sqlite3_step(update_writer_last_seq_num_stmt_) == SQLITE_DONE)
355
0
        {
356
0
            sqlite3_reset(add_writer_change_stmt_);
357
0
            sqlite3_bind_text(add_writer_change_stmt_, 1, persistence_guid.c_str(), -1, SQLITE_STATIC);
358
0
            sqlite3_bind_int64(add_writer_change_stmt_, 2, change.sequenceNumber.to64long());
359
0
            if (change.instanceHandle.isDefined())
360
0
            {
361
0
                sqlite3_bind_blob(add_writer_change_stmt_, 3, change.instanceHandle.value, 16, SQLITE_STATIC);
362
0
            }
363
0
            else
364
0
            {
365
0
                sqlite3_bind_zeroblob(add_writer_change_stmt_, 3, 16);
366
0
            }
367
0
            sqlite3_bind_blob(add_writer_change_stmt_, 4, change.serializedPayload.data,
368
0
                    change.serializedPayload.length, SQLITE_STATIC);
369
370
            // related sample identity
371
0
            std::ostringstream os;
372
0
            auto& si = change.write_params.related_sample_identity();
373
0
            os << si.writer_guid();
374
375
            // IMPORTANT: this element must survive until the call (sqlite3_step) has been fulfilled.
376
            // Another way would be to use SQLITE_TRANSIENT instead of static, forcing an internal copy,
377
            // but this way a copy is saved (with cost of taking care that this string should survive)
378
0
            std::string guids = os.str();
379
380
0
            sqlite3_bind_text(add_writer_change_stmt_, 5, guids.c_str(), -1, SQLITE_STATIC);
381
0
            sqlite3_bind_int64(add_writer_change_stmt_, 6, si.sequence_number().to64long());
382
383
            // source time stamp
384
0
            sqlite3_bind_int64(add_writer_change_stmt_, 7, change.sourceTimestamp.to_ns());
385
386
0
            return sqlite3_step(add_writer_change_stmt_) == SQLITE_DONE;
387
0
        }
388
0
    }
389
390
0
    return false;
391
0
}
392
393
/**
394
 * Remove a change from storage.
395
 * @param change The cache change to remove.
396
 * @return True if operation was successful.
397
 */
398
bool SQLite3PersistenceService::remove_writer_change_from_storage(
399
        const std::string& persistence_guid,
400
        const CacheChange_t& change)
401
0
{
402
0
    EPROSIMA_LOG_INFO(RTPS_PERSISTENCE,
403
0
            "Writer " << change.writerGUID << " removing change for seq " << change.sequenceNumber);
404
405
0
    if (remove_writer_change_stmt_ != NULL)
406
0
    {
407
0
        sqlite3_reset(remove_writer_change_stmt_);
408
0
        sqlite3_bind_text(remove_writer_change_stmt_, 1, persistence_guid.c_str(), -1, SQLITE_STATIC);
409
0
        sqlite3_bind_int64(remove_writer_change_stmt_, 2, change.sequenceNumber.to64long());
410
0
        return sqlite3_step(remove_writer_change_stmt_) == SQLITE_DONE;
411
0
    }
412
413
0
    return false;
414
0
}
415
416
/**
417
 * Get all data stored for a reader.
418
 * @param reader_guid GUID of the reader to load.
419
 * @return True if operation was successful.
420
 */
421
bool SQLite3PersistenceService::load_reader_from_storage(
422
        const std::string& reader_guid,
423
        foonathan::memory::map<GUID_t, SequenceNumber_t, IPersistenceService::map_allocator_t>& seq_map)
424
0
{
425
0
    EPROSIMA_LOG_INFO(RTPS_PERSISTENCE, "Loading reader " << reader_guid);
426
427
0
    if (load_reader_stmt_ != NULL)
428
0
    {
429
0
        sqlite3_reset(load_reader_stmt_);
430
0
        sqlite3_bind_text(load_reader_stmt_, 1, reader_guid.c_str(), -1, SQLITE_STATIC);
431
432
0
        while (SQLITE_ROW == sqlite3_step(load_reader_stmt_))
433
0
        {
434
0
            GUID_t guid;
435
0
            memcpy(guid.guidPrefix.value, sqlite3_column_blob(load_reader_stmt_, 0), GuidPrefix_t::size);
436
0
            memcpy(guid.entityId.value, sqlite3_column_blob(load_reader_stmt_, 1), EntityId_t::size);
437
0
            sqlite3_int64 sn = sqlite3_column_int64(load_reader_stmt_, 2);
438
0
            SequenceNumber_t seq((int32_t)((sn >> 32) & 0xFFFFFFFF), (uint32_t)(sn & 0xFFFFFFFF));
439
0
            seq_map[guid] = seq;
440
0
        }
441
0
    }
442
443
0
    return true;
444
0
}
445
446
/**
447
 * Update the sequence number associated to a writer on a reader.
448
 * @param reader_guid GUID of the reader to update.
449
 * @param writer_guid GUID of the associated writer to update.
450
 * @param seq_number New sequence number value to set for the associated writer.
451
 * @return True if operation was successful.
452
 */
453
bool SQLite3PersistenceService::update_writer_seq_on_storage(
454
        const std::string& reader_guid,
455
        const GUID_t& writer_guid,
456
        const SequenceNumber_t& seq_number)
457
0
{
458
0
    EPROSIMA_LOG_INFO(RTPS_PERSISTENCE,
459
0
            "Reader " << reader_guid << " setting seq for writer " << writer_guid << " to " << seq_number);
460
461
0
    if (update_reader_stmt_ != NULL)
462
0
    {
463
0
        sqlite3_reset(update_reader_stmt_);
464
0
        sqlite3_bind_text(update_reader_stmt_, 1, reader_guid.c_str(), -1, SQLITE_STATIC);
465
0
        sqlite3_bind_blob(update_reader_stmt_, 2, writer_guid.guidPrefix.value, GuidPrefix_t::size, SQLITE_STATIC);
466
0
        sqlite3_bind_blob(update_reader_stmt_, 3, writer_guid.entityId.value, EntityId_t::size, SQLITE_STATIC);
467
0
        sqlite3_bind_int64(update_reader_stmt_, 4, seq_number.to64long());
468
0
        return sqlite3_step(update_reader_stmt_) == SQLITE_DONE;
469
0
    }
470
471
0
    return false;
472
0
}
473
474
bool SQLite3PersistenceServiceSchemaV3::database_create_temporary_defaults_table(
475
        sqlite3* db)
476
0
{
477
0
    using namespace std;
478
479
0
    sqlite3_stmt* insert_default_stmt;
480
481
    // create temporary table
482
0
    int rc = sqlite3_exec(
483
0
        db,
484
0
        "CREATE TEMP TABLE IF NOT EXISTS Defaults (Name TEST PRIMARY KEY, Value TEST);",
485
0
        0, 0, 0);
486
487
0
    if (rc != SQLITE_OK)
488
0
    {
489
0
        return false;
490
0
    }
491
492
    // Insert default values
493
0
    sqlite3_prepare_v3(
494
0
        db,
495
0
        "INSERT OR REPLACE INTO TEMP.Defaults VALUES (?, ?);",
496
0
        -1, SQLITE_PREPARE_PERSISTENT,
497
0
        &insert_default_stmt, NULL);
498
499
    // Default GUID_t value
500
0
    sqlite3_reset(insert_default_stmt);
501
0
    sqlite3_bind_text(insert_default_stmt, 1, "GUID_t", -1, SQLITE_STATIC);
502
0
    sqlite3_bind_text(insert_default_stmt, 2, SQLite3PersistenceServiceSchemaV3::default_guid(), -1, SQLITE_STATIC);
503
0
    rc = sqlite3_step(insert_default_stmt);
504
505
0
    if (rc != SQLITE_DONE)
506
0
    {
507
0
        return false;
508
0
    }
509
510
    // Default SequenceNumber_t
511
0
    sqlite3_reset(insert_default_stmt);
512
0
    sqlite3_bind_text(insert_default_stmt, 1, "SequenceNumber_t", -1, SQLITE_STATIC);
513
0
    sqlite3_bind_int64(insert_default_stmt, 2, SQLite3PersistenceServiceSchemaV3::default_seqnum());
514
0
    rc = sqlite3_step(insert_default_stmt);
515
516
0
    if (rc != SQLITE_DONE)
517
0
    {
518
0
        return false;
519
0
    }
520
521
    // Default rtps::Time_t
522
0
    sqlite3_reset(insert_default_stmt);
523
0
    sqlite3_bind_text(insert_default_stmt, 1, "rtps::Time_t", -1, SQLITE_STATIC);
524
525
0
    sqlite3_bind_int64(insert_default_stmt, 2, SQLite3PersistenceServiceSchemaV3::now());
526
0
    rc = sqlite3_step(insert_default_stmt);
527
528
0
    if (rc != SQLITE_DONE)
529
0
    {
530
0
        return false;
531
0
    }
532
533
    // free resources
534
0
    finalize_statement(insert_default_stmt);
535
536
0
    return true;
537
0
}
538
539
const char* SQLite3PersistenceServiceSchemaV3::default_guid()
540
0
{
541
0
    using namespace std;
542
543
0
    static string def_guid;
544
545
0
    if (def_guid.empty())
546
0
    {
547
0
        ostringstream ss;
548
0
        auto def = GUID_t::unknown();
549
0
        ss << def;
550
0
        def_guid = ss.str();
551
0
    }
552
553
0
    return def_guid.c_str();
554
0
}
555
556
uint64_t SQLite3PersistenceServiceSchemaV3::default_seqnum()
557
0
{
558
0
    return SequenceNumber_t::unknown().to64long();
559
0
}
560
561
int64_t SQLite3PersistenceServiceSchemaV3::now()
562
0
{
563
0
    Time_t ts;
564
0
    Time_t::now(ts);
565
0
    return ts.to_ns();
566
0
}
567
568
} /* namespace rtps */
569
} /* namespace fastdds */
570
} /* namespace eprosima */