All pastes #183426 Raw Edit

Anonymous

public text v1 · immutable
#183426 ·published 2006-09-26 22:22 UTC
rendered paste body
Index: mythtv-trunk/libs/libmythtv/RingBuffer.cpp
===================================================================
--- mythtv-trunk.orig/libs/libmythtv/RingBuffer.cpp
+++ mythtv-trunk/libs/libmythtv/RingBuffer.cpp
@@ -163,23 +163,33 @@ void RingBuffer::OpenFile(const QString 
 
     bool is_local = false;
     bool is_dvd = false;
+    bool found = false;
     (void) is_dvd; // not used when frontend is disabled.
 
     if ((filename.left(7) == "myth://") &&
         (filename.length() > 7 ))
     {
-        QString local_pathname = gContext->GetSetting("RecordFilePrefix");
+        QString local_pathname;
         int hostlen = filename.find(QRegExp("/"), 7);
 
         if (hostlen != -1)
         {
-            local_pathname += filename.right(filename.length() - hostlen);
-
-            QFile checkFile(local_pathname);
-            if (checkFile.exists())
+            // loop through our recording directories looking for it
+            QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix"));
+            for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
             {
-                is_local = true;
-                filename = local_pathname;
+                if (!found)
+                {
+                    local_pathname = recording_prefixes[index] + filename.right(filename.length() - hostlen);
+
+                    QFile checkFile(local_pathname);
+                    if (checkFile.exists())
+                    {
+                        found = true;
+                        is_local = true;
+                        filename = local_pathname;
+                    }
+                }
             }
         }
     }
Index: mythtv-trunk/libs/libmythtv/previewgenerator.cpp
===================================================================
--- mythtv-trunk.orig/libs/libmythtv/previewgenerator.cpp
+++ mythtv-trunk/libs/libmythtv/previewgenerator.cpp
@@ -65,8 +65,22 @@ PreviewGenerator::PreviewGenerator(const
     // Try to find a local means to access file...
     QString baseName = programInfo.GetRecordBasename();
     QString prefix   = gContext->GetSetting("RecordFilePrefix");
-    QString localFN  = QString("%1/%2").arg(prefix).arg(baseName);
-    if (!QFileInfo(localFN).exists())
+    QString localFN;
+
+    // search through all recording directories
+    bool found = false;
+    QStringList recording_prefixes = QStringList::split(",",gContext->GetSetting("RecordFilePrefix"));
+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+    {
+        if (!found)
+        {
+            localFN  = recording_prefixes[index] + "/" + baseName;
+            if (QFileInfo(localFN).exists())
+                found = true;
+        }
+    }
+
+    if (!found)
     {
         // GetPlaybackURL tries to return a local filename if one exists
         localFN = programInfo.GetPlaybackURL();
Index: mythtv-trunk/libs/libmythtv/programinfo.cpp
===================================================================
--- mythtv-trunk.orig/libs/libmythtv/programinfo.cpp
+++ mythtv-trunk/libs/libmythtv/programinfo.cpp
@@ -1464,6 +1464,23 @@ QString ProgramInfo::GetRecordBasename(v
  */
 QString ProgramInfo::GetRecordFilename(const QString &prefix) const
 {
+    // since we support multiple recording directories, try to
+    // find out which one we used for storing this file in ..
+    // if we cannot find it then just fall back to existing
+    // behavior
+
+    QStringList recording_prefixes = QStringList::split(",",prefix);
+    QString filename;
+    QString basename = GetRecordBasename();
+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+    {
+        filename = QString("%1/%2").arg(recording_prefixes[index]).arg(basename);
+        QFile checkFile(filename);
+        if (checkFile.exists())
+            return filename;
+    }
+
+    // bah - just return what we would have done previously
     return QString("%1/%2").arg(prefix).arg(GetRecordBasename());
 }               
 
Index: mythtv-trunk/libs/libmythtv/tv_rec.cpp
===================================================================
--- mythtv-trunk.orig/libs/libmythtv/tv_rec.cpp
+++ mythtv-trunk/libs/libmythtv/tv_rec.cpp
@@ -642,8 +642,29 @@ void TVRec::StartedRecording(ProgramInfo
     if (!curRec)
         return;
 
-    curRec->StartedRecording(rbFilePrefix, rbFileExt);
-    VERBOSE(VB_RECORD, LOC + "StartedRecording("<<curRec<<") fn("
+    // choose a directory to store our recording into
+    // if we have multiple directories to choose from, choose
+    // the one with the most free space
+    long long total, used;
+    int chosen_index = -1;
+    long long cur_free_space = -1, highest_free_space = -1;
+    QStringList recording_prefixes = QStringList::split(",",rbFilePrefix);
+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+    {
+        cur_free_space = getDiskSpace(recording_prefixes[index], total, used);
+        if (cur_free_space > highest_free_space)
+        {
+            highest_free_space = cur_free_space;
+            chosen_index = index;
+        }
+        VERBOSE(VB_RECORD, LOC + QString("filesystem: (%1)%2, free: %3, total: %4, "
+                                         "used: %5  (chosen %6)")
+                                        .arg(index).arg(recording_prefixes[index]).arg(cur_free_space)
+                                        .arg(total).arg(used).arg(chosen_index));
+    }
+
+    curRec->StartedRecording(recording_prefixes[chosen_index], rbFileExt);
+    VERBOSE(VB_RECORD, LOC + "StartedRecording LTD("<<curRec<<") fn("
             <<curRec->GetFileName()<<")");
 
     if (curRec->chancommfree != 0)
Index: mythtv-trunk/programs/mythbackend/autoexpire.cpp
===================================================================
--- mythtv-trunk.orig/programs/mythbackend/autoexpire.cpp
+++ mythtv-trunk/programs/mythbackend/autoexpire.cpp
@@ -115,10 +115,32 @@ void AutoExpire::CalcParams(vector<Encod
             sharing = true;
         else if (enc->IsConnected())
         {
+
+            // to support multiple recording directories, we need to base
+            // the expiry interval based on the SMALLEST filesystem we have
+            // to accomplish this, iterate over all our disks & use only
+            // the one with the least free space
             long long total, used;
-            beginSize  = getDiskSpace(recordFilePrefix, total, used);
+
+            int chosen_index = -1;
+            long long cur_free_space = -1, lowest_free_space = -1;
+            QStringList recording_prefixes = QStringList::split(",",recordFilePrefix);
+            for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+            {
+                cur_free_space = getDiskSpace(recording_prefixes[index], total, used);
+                if ((cur_free_space < lowest_free_space) || (chosen_index == -1))
+                {
+                    lowest_free_space = cur_free_space;
+                    chosen_index = index;
+                }
+                DBG_CALC_PARAM(QString("filesystem: (%1)%2, free: %3, total: %4, used: %5  (chosen %6)")
+                               .arg(index).arg(recording_prefixes[index]).arg(cur_free_space)
+                               .arg(total).arg(used).arg(chosen_index));
+            }
+
+            beginSize  = getDiskSpace(recording_prefixes[chosen_index], total, used);
             remoteSize = enc->GetFreeDiskSpace();
-            endSize    = getDiskSpace(recordFilePrefix, total, used);
+            endSize    = getDiskSpace(recording_prefixes[chosen_index], total, used);
 
             DBG_CALC_PARAM("CalcParams() -- A 2");
             if (beginSize<0 || remoteSize<0 || endSize<0)
@@ -221,7 +243,7 @@ static inline bool operator!= (const fsi
  *
  *   Every "AutoExpireFrequency" minutes this will delete as many
  *   files as needed to free "AutoExpireDiskThreshold" gigabytes of
- *   space on the filesystem containing "RecordFilePrefix".
+ *   space on the filesystems containing "RecordFilePrefix".
  *
  *   If this is run on the master backend this will also delete
  *   programs exceeding the maximum number of episodes of that
@@ -330,20 +352,25 @@ void AutoExpire::ExpireLiveTV(int type)
     long long availFreeKB = 0;
     long long tKB, uKB;
 
-    if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0)
-    {
-        QString msg = QString("ERROR: Could not calculate free space for %1.")
-                              .arg(record_file_prefix);
-        VERBOSE(VB_IMPORTANT, LOC + msg);
-        gContext->LogEntry("mythbackend", LP_WARNING,
-                           "Autoexpire Recording", msg);
-    }
-    else
+    QStringList recording_prefixes = QStringList::split(",",record_file_prefix);
+    VERBOSE(VB_FILE, LOC + QString("ExpireLiveTV(%1)").arg(type));
+    for (QStringList::const_iterator it = recording_prefixes.begin();
+         it != recording_prefixes.end(); ++it)
     {
-        VERBOSE(VB_FILE, LOC + QString("ExpireLiveTV(%1)").arg(type));
-        ClearExpireList();
-        FillDBOrdered(type);
-        SendDeleteMessages(availFreeKB, 0, true);
+        if ((availFreeKB = getDiskSpace(*it, tKB, uKB)) < 0)
+        {
+            QString msg = QString("ERROR: Could not calculate free space for %1.")
+                .arg(*it);
+            VERBOSE(VB_IMPORTANT, LOC + msg);
+            gContext->LogEntry("mythbackend", LP_WARNING,
+                               "Autoexpire Recording", msg);
+        }
+        else
+        {
+            ClearExpireList();
+            FillDBOrdered(type);
+            SendDeleteMessages(availFreeKB, 0, *it, true);
+        }
     }
 }
 
@@ -356,39 +383,47 @@ void AutoExpire::ExpireRecordings(void)
     long long availFreeKB = 0;
     long long tKB, uKB;
 
-    if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0)
-    {
-        QString msg = QString("ERROR: Could not calculate free space.");
-        VERBOSE(VB_IMPORTANT, LOC + msg);
-        gContext->LogEntry("mythbackend", LP_WARNING,
-                           "Autoexpire Recording", msg);
-    }
-    else if (((size_t)availFreeKB) < desired_space)
+    // loop through all our recording directories, checking for minimum
+    // space on each.  trigger deletions if below that threshold..
+    QStringList recording_prefixes = QStringList::split(",",record_file_prefix);
+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
     {
-        VERBOSE(VB_FILE, LOC +
-                QString("Running autoexpire, we want %1 MB free, "
-                        "but only have %2 MB.")
-                .arg(desired_space/1024).arg(availFreeKB/1024));
+        if ((availFreeKB = getDiskSpace(recording_prefixes[index], tKB, uKB)) < 0)
+        {
+            QString msg = QString("ERROR: Could not calculate free space for %1.")
+                                  .arg(recording_prefixes[index]);
+            VERBOSE(VB_IMPORTANT, LOC + msg);
+            gContext->LogEntry("mythbackend", LP_WARNING,
+                               "Autoexpire Recording", msg);
+        }
+        else if (((size_t)availFreeKB) < desired_space)
+        {
+            VERBOSE(VB_FILE, LOC +
+                    QString("Running autoexpire in %1, we want %2 MB free, "
+                            "but only have %3 MB.")
+                    .arg(recording_prefixes[index])
+                    .arg(desired_space/1024).arg(availFreeKB/1024));
         
-        FillExpireList();
-        SendDeleteMessages(availFreeKB, desired_space);
+            FillExpireList();
+            SendDeleteMessages(availFreeKB, desired_space, recording_prefixes[index]);
+        }
     }
 }
 
-/** \fn CheckFile(const ProgramInfo*, const QString&, const fsid_t&)
+/** \fn CheckFile(const ProgramInfo*, QString&, const fsid_t&)
  *  \brief Returns true iff file can be deleted.
  *
  *   CheckFile makes sure the file exists and is stored on the same file
  *   system as the recordfileprefix.
  *  \param pginfo           ProgramInfo for the program we wish to delete.
- *  \param recordfileprefix Path where new recordings are stored.
+ *  \param dir              Path where we are looking for files to remove from.
  *  \param fsid             Unique ID of recordfileprefix's filesystem.
  */
 static bool CheckFile(const ProgramInfo *pginfo,
-                      const QString &recordfileprefix,
+                      QString &dir,
                       const fsid_t& fsid)
 {
-    QString filename = pginfo->GetRecordFilename(recordfileprefix);
+    QString filename = pginfo->GetRecordFilename(dir);
     QFileInfo checkFile(filename);
     if (!checkFile.exists())
     {
@@ -402,7 +437,8 @@ static bool CheckFile(const ProgramInfo 
             gContext->LogEntry("mythbackend", LP_WARNING,
                                "Autoexpire Recording", msg); 
         }
-        else if (pginfo->hostname == gContext->GetHostName())
+        else if ((pginfo->hostname == gContext->GetHostName()) &&
+                 (dir == gContext->GetSetting("RecordFilePrefix")))
         {
             QString msg =
                 QString("ERROR when trying to autoexpire file: %1. "
@@ -427,36 +463,46 @@ static bool CheckFile(const ProgramInfo 
     return true;
 }
 
-/** \fn AutoExpire::SendDeleteMessages(size_t, size_t, bool)
+/** \fn AutoExpire::SendDeleteMessages(size_t, size_t, QString&, bool)
  *  \brief This sends delete message to main event thread.
  */
 void AutoExpire::SendDeleteMessages(size_t availFreeKB, size_t desiredFreeKB,
-                                    bool deleteAll)
+                                    QString &dir, bool deleteAll)
 {
     QString msg;
-    fsid_t fsid = UniqueFileSystemID(record_file_prefix);
+    fsid_t fsid = UniqueFileSystemID(dir);
 
     if (expire_list.size() == 0)
     {
         if ((!deleteAll) &&
             (desiredFreeKB > 0) &&
             (availFreeKB < desiredFreeKB))
-            VERBOSE(VB_FILE, LOC + "SendDeleteMessages. WARNING: below free "
-                    "disk space threshold, but nothing to expire~");
+        {
+            QString msg =
+                QString("SendDeleteMessages. WARNING: below free "
+                        "disk space threshold, but nothing to expire~ "
+                        "(%1, %2 available, %3 desired)")
+                        .arg(dir).arg(availFreeKB).arg(desiredFreeKB);
+            VERBOSE(VB_FILE, LOC + msg);
+        }
         else
-            VERBOSE(VB_FILE, LOC + "SendDeleteMessages. Nothing to expire.");
-
+        {
+            QString msg =
+                QString("SendDeleteMessages. Nothing to expire. (%1)").arg(dir);
+            VERBOSE(VB_FILE, LOC + msg);
+        }
         return;
     }
 
-    VERBOSE(VB_FILE, LOC + "SendDeleteMessages, cycling through expire list.");
+    VERBOSE(VB_FILE, LOC + QString("SendDeleteMessages, cycling through "
+                                   "expire list (%1).").arg(dir));
     pginfolist_t::iterator it = expire_list.begin();
     while (it != expire_list.end() &&
            (deleteAll || availFreeKB < desiredFreeKB))
     {
         VERBOSE(VB_FILE, QString("    Checking %1 @ %2")
                          .arg((*it)->chanid).arg((*it)->startts.toString()));
-        if (CheckFile(*it, record_file_prefix, fsid))
+        if (CheckFile(*it, dir, fsid))
         {
             // Print informative message 
             QString titlestr = (*it)->title;
@@ -475,9 +521,10 @@ void AutoExpire::SendDeleteMessages(size
             }
             else
                 msg += QString(", free space is too low (have %1 MBytes free "
-                               ", but want %2 MBytes)")
+                               ", but want %2 MBytes on %3)")
                                .arg(availFreeKB/1024)
-                               .arg(desiredFreeKB/1024);
+                               .arg(desiredFreeKB/1024)
+                               .arg(dir);
 
             if (print_verbose_messages & VB_IMPORTANT)
                 VERBOSE(VB_IMPORTANT, msg);
@@ -510,7 +557,7 @@ void AutoExpire::SendDeleteMessages(size
     if (!deleteAll && availFreeKB < desiredFreeKB)
     {
         msg = QString("ERROR when trying to autoexpire files.  "
-                      "No recordings available to expire.");
+                      "No recordings available to expire on %1.").arg(dir);
         VERBOSE(VB_IMPORTANT, LOC + msg); 
         gContext->LogEntry("mythbackend", LP_WARNING,
                            "Autoexpire Recording", msg);
@@ -663,7 +710,7 @@ void AutoExpire::FillExpireList(void)
         case emLowestPriorityFirst:
         case emWeightedTimePriority:
                 FillDBOrdered(expMethod);
-                break;
+        break;
         // default falls through so list is empty so no AutoExpire
     }
 }
Index: mythtv-trunk/programs/mythbackend/autoexpire.h
===================================================================
--- mythtv-trunk.orig/programs/mythbackend/autoexpire.h
+++ mythtv-trunk/programs/mythbackend/autoexpire.h
@@ -60,7 +60,7 @@ class AutoExpire : public QObject
 
     void FillDBOrdered(int expMethod, bool allHosts = false);
     void SendDeleteMessages(size_t availFreeKB, size_t desiredFreeKB,
-                            bool deleteAll = false);
+                            QString &dir, bool deleteAll = false);
     void ClearExpireList(void);
     void Sleep(int sleepTime);
     void WaitForPendingTruncates(void);
Index: mythtv-trunk/programs/mythbackend/encoderlink.cpp
===================================================================
--- mythtv-trunk.orig/programs/mythbackend/encoderlink.cpp
+++ mythtv-trunk/programs/mythbackend/encoderlink.cpp
@@ -243,7 +243,21 @@ long long EncoderLink::GetFreeDiskSpace(
     if (!use_cache)
     {
         if (local)
-            freeDiskSpaceKB = getDiskSpace(recordfileprefix, totalKB, usedKB);
+        {
+            // since we can record to multiple mount points and always choose
+            // the directory with the most free space, return just the space
+            // for that one mount point
+            long long cur_free_space;
+            freeDiskSpaceKB = -1;
+            QStringList recording_prefixes = QStringList::split(",",recordfileprefix);
+            for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+            {
+                cur_free_space = getDiskSpace(recording_prefixes[index], totalKB, usedKB);
+
+                if (cur_free_space > freeDiskSpaceKB)
+                    freeDiskSpaceKB = cur_free_space;
+            }
+        }
         else if (sock)
         {
             sock->GetFreeDiskSpace(totalKB, usedKB);
Index: mythtv-trunk/programs/mythbackend/main.cpp
===================================================================
--- mythtv-trunk.orig/programs/mythbackend/main.cpp
+++ mythtv-trunk/programs/mythbackend/main.cpp
@@ -45,7 +45,6 @@ AutoExpire *expirer = NULL;
 Scheduler *sched = NULL;
 JobQueue *jobqueue = NULL;
 QString pidfile;
-QString lockfile_location;
 HouseKeeper *housekeeping = NULL;
 QString logfile = "";
 
@@ -216,7 +215,12 @@ void cleanup(void) 
     if (pidfile != "")
         unlink(pidfile.ascii());
 
-    unlink(lockfile_location.ascii());
+    QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix"));
+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+    {
+        QString lockfile_location = recording_prefixes[index] + "/nfslockfile.lock";
+        unlink(lockfile_location.ascii());
+    }
 
     signal(SIGHUP, SIG_DFL);
 }
@@ -648,8 +652,6 @@ int main(int argc, char **argv)
 
     VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1").arg(verboseString));
 
-    lockfile_location = gContext->GetSetting("RecordFilePrefix") + "/nfslockfile.lock";
-
     if (ismaster)
 // Create a file in the recording directory.  A slave encoder will 
 // look for this file and return 0 bytes free if it finds it when it's
@@ -658,14 +660,19 @@ int main(int argc, char **argv)
 // If the slave doesn't find this file then it will assume that it has
 // a seperate store.
     {
-        if (creat(lockfile_location.ascii(), 0664) == -1)
+        QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix"));
+        for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
         {
-            perror(lockfile_location.ascii()); 
-            cerr << "Unable to open lockfile!\n"
-                 << "Be sure that \'" << gContext->GetSetting("RecordFilePrefix")
-                 << "\' exists and that both \nthe directory and that "
-                 << "file are writeable by this user.\n";
-            return BACKEND_EXIT_OPENING_VLOCKFILE_ERROR;
+            QString lockfile_location = recording_prefixes[index] + "/nfslockfile.lock";
+            if (creat(lockfile_location.ascii(), 0664) == -1)
+            {
+                perror(lockfile_location.ascii());
+                cerr << "Unable to open lockfile!\n"
+                    << "Be sure that \'" << gContext->GetSetting("RecordFilePrefix")
+                    << "\' exists and that both \nthe directory and that "
+                    << "file are writeable by this user.\n";
+                return BACKEND_EXIT_OPENING_VLOCKFILE_ERROR;
+            }
         }
     }
 
Index: mythtv-trunk/programs/mythbackend/mainserver.cpp
===================================================================
--- mythtv-trunk.orig/programs/mythbackend/mainserver.cpp
+++ mythtv-trunk/programs/mythbackend/mainserver.cpp
@@ -1213,16 +1213,30 @@ void MainServer::HandleQueryRecordings(Q
 
             proginfo->stars = query.value(31).toDouble();
 
-            QString lpath = fileprefix + "/" + basename;
+            // since we support multiple recording directories,
+            // be sure to specify actual directory where file is
+            // stored. if we cannot find it, fallback
+            QString lpath;
+            QStringList recording_prefixes = QStringList::split(",",fileprefix);
+            int found_index = -1;
+            for (int index = 0; index < (int)recording_prefixes.size() && found_index == -1; ++index)
+            {
+                lpath = recording_prefixes[index] + "/" + basename;
+                QFile checkFile(lpath);
+                if (checkFile.exists())
+                    found_index = index;
+            }
+            if (found_index == -1)
+                lpath = fileprefix + "/" + basename;
+
             PlaybackSock *slave = NULL;
-            QFile checkFile(lpath);
 
             if (proginfo->hostname != gContext->GetHostName())
                 slave = getSlaveByHostname(proginfo->hostname);
 
-            if ((masterBackendOverride && checkFile.exists()) || 
+            if ((masterBackendOverride && (found_index != -1)) ||
                 (proginfo->hostname == gContext->GetHostName()) ||
-                (!slave && checkFile.exists()))
+                (!slave && (found_index != -1)))
             {
                 if (islocal)
                     proginfo->pathname = lpath;
@@ -2011,7 +2025,16 @@ void MainServer::HandleQueryFreeSpace(Pl
 {    
     QStringList strlist;
     long long totalKB = -1, usedKB = -1;
-    getDiskSpace(recordfileprefix, totalKB, usedKB);
+    long long cur_totalKB = -1, cur_usedKB = -1, cur_availKB = -1;
+
+    QStringList recording_prefixes = QStringList::split(",", recordfileprefix);
+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+    {
+        cur_availKB = getDiskSpace(recording_prefixes[index], cur_totalKB, cur_usedKB);
+        totalKB += cur_totalKB;
+        usedKB += cur_usedKB;
+    }
+
     if (!allHosts)
     {
         encodeLongLong(strlist, totalKB);
@@ -3854,8 +3877,9 @@ QString MainServer::LocalFilePath(QUrl &
     }
     else
     {
+        QStringList recording_prefixes = QStringList::split(",", gContext->GetFilePrefix());
         lpath = lpath.section('/', -1);
-        lpath = gContext->GetFilePrefix() + "/" + lpath;
+        lpath = recording_prefixes[0] + "/" + lpath;
     }
     VERBOSE(VB_FILE, QString("Local file path: %1").arg(lpath));
 
Index: mythtv-trunk/programs/mythtv-setup/backendsettings.cpp
===================================================================
--- mythtv-trunk.orig/programs/mythtv-setup/backendsettings.cpp
+++ mythtv-trunk/programs/mythtv-setup/backendsettings.cpp
@@ -70,7 +70,8 @@ static HostLineEdit *RecordFilePrefix()
     gc->setLabel(QObject::tr("Directory to hold recordings"));
     gc->setValue("/mnt/store/");
     gc->setHelpText(QObject::tr("All recordings get stored in this "
-                    "directory."));
+                    "directory (multiple directories can be specified, "
+                    "seperated by commas)."));
     return gc;
 };
 
Index: mythtv-trunk/programs/mythtv-setup/checksetup.cpp
===================================================================
--- mythtv-trunk.orig/programs/mythtv-setup/checksetup.cpp
+++ mythtv-trunk/programs/mythtv-setup/checksetup.cpp
@@ -60,8 +60,13 @@ bool checkStoragePaths(QString *probs)
     if (query.size())
     {
         query.next();
-        if (checkPath(query.value(0).toString(), probs))
-            problemFound = true;
+
+        QStringList recording_prefixes = QStringList::split(",", query.value(0).toString());
+        for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+        {
+            if (checkPath(recording_prefixes[index], probs))
+                problemFound = true;
+        }
     }
     else
         VERBOSE(VB_GENERAL, QString("RecordFilePrefix is not set?"));
Index: mythtv-trunk/programs/mythbackend/httpstatus.cpp
===================================================================
--- mythtv-trunk.orig/programs/mythbackend/httpstatus.cpp
+++ mythtv-trunk/programs/mythbackend/httpstatus.cpp
@@ -1283,9 +1283,18 @@ void HttpStatus::FillStatusXML( QDomDocu
     // drive space   --------------------- 
  
     long long iTotal = -1, iUsed = -1, iAvail = -1; 
- 
-    iAvail = getDiskSpace( gContext->GetFilePrefix(), iTotal, iUsed); 
- 
+    long long cur_iTotal = -1, cur_iUsed = -1, cur_iAvail = -1;
+
+    QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix"));
+
+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
+    {
+        cur_iAvail = getDiskSpace(recording_prefixes[index], cur_iTotal, cur_iUsed);
+        iAvail += cur_iAvail;
+        iTotal += cur_iTotal;
+        iUsed += cur_iUsed;
+    }
+
     storage.setAttribute("_local_total", (int)(iTotal>>10)); 
     storage.setAttribute("_local_used" , (int)(iUsed>>10)); 
     storage.setAttribute("_local_free" , (int)(iAvail>>10));