Ticket #11801: 0001-Wait-until-there-s-more-space-to-write-in-buffer.patch

File 0001-Wait-until-there-s-more-space-to-write-in-buffer.patch, 6.3 KB (added by JYA, 11 years ago)
  • mythtv/libs/libmythbase/threadedfilewriter.cpp

    From b15ea225af5e601d3a12ffaa72cf013b730c3b9d Mon Sep 17 00:00:00 2001
    From: Jean-Yves Avenard <jyavenard@mythtv.org>
    Date: Sat, 31 Aug 2013 07:22:03 -0400
    Subject: [PATCH] =?UTF-8?q?Wait=20until=20there=E2=80=99s=20more=20space?=
     =?UTF-8?q?=20to=20write=20in=20buffer.?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Writing should never result in a truncated file.
    Also write using blocks of 1MB maximum, and reduce write buffer from 128MB to 8MB.
    
    Fixes #11801
    ---
     mythtv/libs/libmythbase/threadedfilewriter.cpp | 98 ++++++++++++++++----------
     mythtv/libs/libmythbase/threadedfilewriter.h   |  5 ++
     2 files changed, 66 insertions(+), 37 deletions(-)
    
    diff --git a/mythtv/libs/libmythbase/threadedfilewriter.cpp b/mythtv/libs/libmythbase/threadedfilewriter.cpp
    index 03073b6..e1a3a8d 100644
    a b void TFWSyncThread::run(void) 
    4040    RunEpilog();
    4141}
    4242
    43 const uint ThreadedFileWriter::kMaxBufferSize = 128 * 1024 * 1024;
    44 const uint ThreadedFileWriter::kMinWriteSize = 64 * 1024;
     43const uint ThreadedFileWriter::kMaxBufferSize   = 8 * 1024 * 1024;
     44const uint ThreadedFileWriter::kMinWriteSize    = 64 * 1024;
     45const uint ThreadedFileWriter::kMaxBlockSize    = 1 * 1024 * 1024;
    4546
    4647/** \class ThreadedFileWriter
    4748 *  \brief This class supports the writing of recordings to disk.
    ThreadedFileWriter::ThreadedFileWriter(const QString &fname, 
    6768    ignore_writes(false),                tfw_min_write_size(kMinWriteSize),
    6869    totalBufferUse(0),
    6970    // threads
    70     writeThread(NULL),                   syncThread(NULL)
     71    writeThread(NULL),                   syncThread(NULL),
     72    m_warned(false)
    7173{
    7274    filename.detach();
    7375}
    uint ThreadedFileWriter::Write(const void *data, uint count) 
    206208    if (ignore_writes)
    207209        return count;
    208210
    209     if (totalBufferUse + count > kMaxBufferSize)
     211    uint written    = 0;
     212    uint left       = count;
     213
     214    while (written < count)
    210215    {
    211         LOG(VB_GENERAL, LOG_ERR, LOC +
    212                 "Maximum buffer size exceeded."
    213                 "\n\t\t\tfile will be truncated, no further writing "
    214                 "will be done."
    215                 "\n\t\t\tThis generally indicates your disk performance "
    216                 "\n\t\t\tis insufficient to deal with the number of on-going "
    217                 "\n\t\t\trecordings, or you have a disk failure.");
    218         ignore_writes = true;
    219         return count;
    220     }
     216        uint towrite = (left > kMaxBlockSize) ? kMaxBlockSize : left;
    221217
    222     TFWBuffer *buf = NULL;
     218        if (totalBufferUse + towrite > kMaxBufferSize)
     219        {
     220            if (!m_warned)
     221            {
     222                LOG(VB_GENERAL, LOG_WARNING, LOC +
     223                        "Maximum buffer size exceeded."
     224                        "\n\t\t\tThis generally indicates your disk performance "
     225                        "\n\t\t\tis insufficient or you have a disk failure.");
     226                m_warned = true;
     227            }
     228            // wait until some was written to disk, and try again
     229            if (!bufferWasFreed.wait(locker.mutex(), 1000))
     230            {
     231                LOG(VB_GENERAL, LOG_DEBUG, LOC +
     232                    QString("Taking a long time waiting to write.. "
     233                            "buffer size %1 (needing %2, %3 to go)")
     234                    .arg(totalBufferUse).arg(towrite)
     235                    .arg(towrite-(kMaxBufferSize-totalBufferUse)));
     236            }
     237            continue;
     238        }
    223239
    224     if (!writeBuffers.empty() &&
    225         (writeBuffers.back()->data.size() + count) < kMinWriteSize)
    226     {
    227         buf = writeBuffers.back();
    228         writeBuffers.pop_back();
    229     }
    230     else
    231     {
    232         if (!emptyBuffers.empty())
     240        TFWBuffer *buf = NULL;
     241
     242        if (!writeBuffers.empty() &&
     243            (writeBuffers.back()->data.size() + towrite) < kMinWriteSize)
    233244        {
    234             buf = emptyBuffers.front();
    235             emptyBuffers.pop_front();
    236             buf->data.clear();
     245            buf = writeBuffers.back();
     246            writeBuffers.pop_back();
    237247        }
    238248        else
    239249        {
    240             buf = new TFWBuffer();
     250            if (!emptyBuffers.empty())
     251            {
     252                buf = emptyBuffers.front();
     253                emptyBuffers.pop_front();
     254                buf->data.clear();
     255            }
     256            else
     257            {
     258                buf = new TFWBuffer();
     259            }
    241260        }
    242     }
    243261
    244     totalBufferUse += count;
    245     const char *cdata = (const char*) data;
    246     buf->data.insert(buf->data.end(), cdata, cdata+count);
    247     buf->lastUsed = MythDate::current();
     262        totalBufferUse += towrite;
    248263
    249     writeBuffers.push_back(buf);
     264        const char *cdata = (const char*) data + written;
     265        buf->data.insert(buf->data.end(), cdata, cdata+towrite);
     266        buf->lastUsed = MythDate::current();
    250267
    251     if ((writeBuffers.size() > 1) || (buf->data.size() >= kMinWriteSize))
    252     {
    253         bufferHasData.wakeAll();
     268        writeBuffers.push_back(buf);
     269
     270        if ((writeBuffers.size() > 1) || (buf->data.size() >= kMinWriteSize))
     271        {
     272            bufferHasData.wakeAll();
     273        }
     274
     275        written += towrite;
     276        left    -= towrite;
    254277    }
    255278
    256279    LOG(VB_FILE, LOG_DEBUG, LOC + QString("Write(*, %1) total %2 cnt %3")
    void ThreadedFileWriter::DiskLoop(void) 
    435458        TFWBuffer *buf = writeBuffers.front();
    436459        writeBuffers.pop_front();
    437460        totalBufferUse -= buf->data.size();
     461        bufferWasFreed.wakeAll();
    438462        minWriteTimer.start();
    439463
    440464        //////////////////////////////////////////
  • mythtv/libs/libmythbase/threadedfilewriter.h

    diff --git a/mythtv/libs/libmythbase/threadedfilewriter.h b/mythtv/libs/libmythbase/threadedfilewriter.h
    index c75dc03..3cd5c8e 100644
    a b class MBASE_PUBLIC ThreadedFileWriter 
    9595    QWaitCondition  bufferEmpty;
    9696    QWaitCondition  bufferHasData;
    9797    QWaitCondition  bufferSyncWait;
     98    QWaitCondition  bufferWasFreed;
    9899
    99100    // constants
    100101    static const uint kMaxBufferSize;
    101102    /// Minimum to write to disk in a single write, when not flushing buffer.
    102103    static const uint kMinWriteSize;
     104    /// Maximum block size to write at a time
     105    static const uint kMaxBlockSize;
     106
     107    bool m_warned;
    103108};
    104109
    105110#endif