Commit 28927661 authored by jan.koester's avatar jan.koester
Browse files

test

parent 7994c243
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
mediadb (20260419+23) unstable; urgency=critical

  * Fix Cluster Media Import: Always upload media data blobs ("media:<id>") to 
    cluster layer during .mdb imports, even if the node already knows about this file 
    in its index. This allows re-importing .mdb archives to successfully act as a 
    self-healing repair ("heile machen") for nodes with missing/broken stripes 
    (which previously skipped uploading and thus broke preview/playback).

 -- Jan Koester <jan.koester@tuxist.de>  Sun, 19 Apr 2026 12:45:00 +0200

mediadb (20260419+22) unstable; urgency=critical

  * Fix Cluster Media Import data loss / corruption: The import_db_from_buffer
+28 −25
Original line number Diff line number Diff line
@@ -777,8 +777,11 @@ bool BinDb::import_from_stream(std::istream& in,
                    bin_write_str(store_buf, created_at);
                    bin_write_u64(store_buf, data_size);

                    if (data_size > 0 && new_media) {
                        // Read media data and replicate as separate key: media:<id>
                    if (data_size > 0) {
                        // In cluster mode, ALWAYS read and replicate media data:
                        // This allows re-importing an .mdb file to self-heal missing
                        // stripes and orphan blobs on nodes (e.g. from previous failures)
                        // even if the metadata itself is already present.
                        std::vector<std::uint8_t> media_data(data_size);
                        in.read(reinterpret_cast<char*>(media_data.data()),
                                static_cast<std::streamsize>(data_size));
@@ -786,9 +789,6 @@ bool BinDb::import_from_stream(std::istream& in,
                        if (got < data_size) media_data.resize(got);
                        on_replicate("media:" + media_id,
                                     media_data.data(), media_data.size());
                    } else if (data_size > 0) {
                        // Existing media: skip past raw data
                        in.seekg(static_cast<std::streamoff>(data_size), std::ios::cur);
                    }

                    // Register metadata only (no raw data in RAM)
@@ -1280,13 +1280,15 @@ private:
        size_t n = std::min(avail, remaining);
        if (n == 0) return;

        if (cur_media_new_) {
        if (stream_to_cluster_) {
                // Accumulate media binary data separately for "media:<id>" key
            // In cluster mode, ALWAYS read and replicate media data:
            // This allows re-importing an .mdb file to self-heal missing
            // stripes and orphan blobs on nodes.
            media_data_buf_.insert(media_data_buf_.end(),
                                   buf_.data() + pos_,
                                   buf_.data() + pos_ + n);
            } else if (store_out_.is_open()) {
        } else if (cur_media_new_) {
            if (store_out_.is_open()) {
                // Write directly to store file
                store_out_.write(buf_.data() + pos_, static_cast<std::streamsize>(n));
                if (!store_out_.good()) {
@@ -1301,7 +1303,7 @@ private:
                    buf_.data() + pos_ + n);
            }
        }
        // Skip data for existing media (just advance pos_)
        // Advance pos_
        pos_ += n;
        data_written_ += n;
    }
@@ -1324,12 +1326,13 @@ private:
            db_.media_[mid] = std::move(*pending_media_);
            db_.albums_[aid].media_ids.push_back(mid);
            pending_media_.reset();
        }

        // Cluster: replicate binary data as separate "media:<id>" key
        if (stream_to_cluster_ && !media_data_buf_.empty()) {
            auto data = std::make_shared<std::vector<uint8_t>>(
                std::move(media_data_buf_));
                std::string key = "media:" + mid;
            std::string key = "media:" + cur_media_id_;
            {
                std::lock_guard<std::mutex> dlk(deferred_mutex_);
                pending_ops_.push_back([this, key, data]() {
@@ -1338,7 +1341,7 @@ private:
            }
        }
        media_data_buf_.clear();
        }
        
        ++mi_;
        if (mi_ < num_media_) {
            phase_ = Phase::MEDIA_HEADER;