Ticket #1744: multiple_recording_dirs.txt

File multiple_recording_dirs.txt, 25.3 KB (added by ltd@…, 18 years ago)

patch

Line 
1Index: libs/libmythtv/previewgenerator.cpp
2===================================================================
3--- libs/libmythtv/previewgenerator.cpp        (revision 9611)
4+++ libs/libmythtv/previewgenerator.cpp        (working copy)
5@@ -62,9 +62,23 @@
6     // Try to find a local means to access file...
7     QString baseName = programInfo.GetRecordBasename();
8     QString prefix   = gContext->GetSetting("RecordFilePrefix");
9-    QString localFN  = QString("%1/%2").arg(prefix).arg(baseName);
10-    if (!QFileInfo(localFN).exists())
11+    QString localFN;
12+
13+    // search through all recording directories
14+    bool found = false;
15+    QStringList recording_prefixes = QStringList::split(",",gContext->GetSetting("RecordFilePrefix"));
16+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
17     {
18+        if (!found)
19+        {
20+            localFN  = recording_prefixes[index] + "/" + baseName;
21+            if (QFileInfo(localFN).exists())
22+                found = true;
23+        }
24+    }
25+
26+    if (!found)
27+    {
28         // GetPlaybackURL tries to return a local filename if one exists
29         localFN = programInfo.GetPlaybackURL();
30         if (!(localFN.left(1) == "/" && QFileInfo(localFN).exists()))
31Index: libs/libmythtv/RingBuffer.cpp
32===================================================================
33--- libs/libmythtv/RingBuffer.cpp        (revision 9611)
34+++ libs/libmythtv/RingBuffer.cpp        (working copy)
35@@ -162,23 +162,33 @@
36 
37     bool is_local = false;
38     bool is_dvd = false;
39+    bool found = false;
40     (void) is_dvd; // not used when frontend is disabled.
41 
42     if ((filename.left(7) == "myth://") &&
43         (filename.length() > 7 ))
44     {
45-        QString local_pathname = gContext->GetSetting("RecordFilePrefix");
46+        QString local_pathname;
47         int hostlen = filename.find(QRegExp("/"), 7);
48 
49         if (hostlen != -1)
50         {
51-            local_pathname += filename.right(filename.length() - hostlen);
52+            // loop through our recording directories looking for it
53+            QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix"));
54+            for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
55+            {
56+                if (!found)
57+                {
58+                    local_pathname = recording_prefixes[index] + filename.right(filename.length() - hostlen);
59 
60-            QFile checkFile(local_pathname);
61-            if (checkFile.exists())
62-            {
63-                is_local = true;
64-                filename = local_pathname;
65+                    QFile checkFile(local_pathname);
66+                    if (checkFile.exists())
67+                    {
68+                        found = true;
69+                        is_local = true;
70+                        filename = local_pathname;
71+                    }
72+                }
73             }
74         }
75     }
76Index: libs/libmythtv/tv_rec.cpp
77===================================================================
78--- libs/libmythtv/tv_rec.cpp        (revision 9611)
79+++ libs/libmythtv/tv_rec.cpp        (working copy)
80@@ -627,8 +627,29 @@
81     if (!curRec)
82         return;
83 
84-    curRec->StartedRecording(rbFilePrefix, rbFileExt);
85-    VERBOSE(VB_RECORD, LOC + "StartedRecording("<<curRec<<") fn("
86+    // choose a directory to store our recording into
87+    // if we have multiple directories to choose from, choose
88+    // the one with the most free space
89+    long long total, used;
90+    int chosen_index = -1;
91+    long long cur_free_space = -1, highest_free_space = -1;
92+    QStringList recording_prefixes = QStringList::split(",",rbFilePrefix);
93+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
94+    {
95+        cur_free_space = getDiskSpace(recording_prefixes[index], total, used);
96+        if (cur_free_space > highest_free_space)
97+        {
98+            highest_free_space = cur_free_space;
99+            chosen_index = index;
100+        }
101+        VERBOSE(VB_RECORD, LOC + QString("filesystem: (%1)%2, free: %3, total: %4, "
102+                                         "used: %5  (chosen %6)")
103+                                        .arg(index).arg(recording_prefixes[index]).arg(cur_free_space)
104+                                        .arg(total).arg(used).arg(chosen_index));
105+    }
106+
107+    curRec->StartedRecording(recording_prefixes[chosen_index], rbFileExt);
108+    VERBOSE(VB_RECORD, LOC + "StartedRecording LTD("<<curRec<<") fn("
109             <<curRec->GetFileName()<<")");
110 
111     if (curRec->chancommfree != 0)
112Index: libs/libmythtv/programinfo.cpp
113===================================================================
114--- libs/libmythtv/programinfo.cpp        (revision 9611)
115+++ libs/libmythtv/programinfo.cpp        (working copy)
116@@ -1294,7 +1294,9 @@
117 {
118     QString starts = recstartts.toString("yyyyMMddhhmmss");
119 
120-    QString retval = QString("%1_%2.%3").arg(chanid)
121+    QString retval = QString("%1_%2_%3_%4_%5.%6")
122+                             .arg(title).arg(chanstr)
123+                             .arg(chansign).arg(chanid)
124                              .arg(starts).arg(ext);
125     
126     return retval;
127@@ -1362,6 +1364,23 @@
128  */
129 QString ProgramInfo::GetRecordFilename(const QString &prefix) const
130 {
131+    // since we support multiple recording directories, try to
132+    // find out which one we used for storing this file in ..
133+    // if we cannot find it then just fall back to existing
134+    // behavior
135+
136+    QStringList recording_prefixes = QStringList::split(",",prefix);
137+    QString filename;
138+    QString basename = GetRecordBasename();
139+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
140+    {
141+        filename = QString("%1/%2").arg(recording_prefixes[index]).arg(basename);
142+        QFile checkFile(filename);
143+        if (checkFile.exists())
144+            return filename;
145+    }
146+
147+    // bah - just return what we would have done previously
148     return QString("%1/%2").arg(prefix).arg(GetRecordBasename());
149 }               
150 
151Index: programs/mythbackend/mainserver.cpp
152===================================================================
153--- programs/mythbackend/mainserver.cpp        (revision 9611)
154+++ programs/mythbackend/mainserver.cpp        (working copy)
155@@ -1112,16 +1112,30 @@
156 
157             proginfo->stars = query.value(31).toDouble();
158 
159-            QString lpath = fileprefix + "/" + basename;
160+            // since we support multiple recording directories,
161+            // be sure to specify actual directory where file is
162+            // stored. if we cannot find it, fallback
163+            QString lpath;
164+            QStringList recording_prefixes = QStringList::split(",",fileprefix);
165+            int found_index = -1;
166+            for (int index = 0; index < (int)recording_prefixes.size() && found_index == -1; ++index)
167+            {
168+                lpath = recording_prefixes[index] + "/" + basename;
169+                QFile checkFile(lpath);
170+                if (checkFile.exists())
171+                    found_index = index;
172+            }
173+            if (found_index == -1)
174+                lpath = fileprefix + "/" + basename;
175+               
176             PlaybackSock *slave = NULL;
177-            QFile checkFile(lpath);
178 
179             if (proginfo->hostname != gContext->GetHostName())
180                 slave = getSlaveByHostname(proginfo->hostname);
181 
182-            if ((masterBackendOverride && checkFile.exists()) ||
183+            if ((masterBackendOverride && (found_index != -1)) ||
184                 (proginfo->hostname == gContext->GetHostName()) ||
185-                (!slave && checkFile.exists()))
186+                (!slave && (found_index != -1)))
187             {
188                 if (islocal)
189                     proginfo->pathname = lpath;
190@@ -1785,7 +1799,16 @@
191 {   
192     QStringList strlist;
193     long long totalKB = -1, usedKB = -1;
194-    getDiskSpace(recordfileprefix, totalKB, usedKB);
195+    long long cur_totalKB = -1, cur_usedKB = -1, cur_availKB = -1;
196+
197+    QStringList recording_prefixes = QStringList::split(",", recordfileprefix);
198+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
199+    {
200+        cur_availKB = getDiskSpace(recording_prefixes[index], cur_totalKB, cur_usedKB);
201+        totalKB += cur_totalKB;
202+        usedKB += cur_usedKB;
203+    }
204+
205     if (!allHosts)
206     {
207         encodeLongLong(strlist, totalKB);
208@@ -3585,8 +3608,9 @@
209     }
210     else
211     {
212+        QStringList recording_prefixes = QStringList::split(",", gContext->GetFilePrefix());
213         lpath = lpath.section('/', -1);
214-        lpath = gContext->GetFilePrefix() + "/" + lpath;
215+        lpath = recording_prefixes[0] + "/" + lpath;
216     }
217     VERBOSE(VB_FILE, QString("Local file path: %1").arg(lpath));
218 
219@@ -3913,8 +3937,16 @@
220     // drive space   ---------------------
221 
222     long long iTotal = -1, iUsed = -1, iAvail = -1;
223+    long long cur_iTotal = -1, cur_iUsed = -1, cur_iAvail = -1;
224 
225-    iAvail = getDiskSpace(recordfileprefix, iTotal, iUsed);
226+    QStringList recording_prefixes = QStringList::split(",", recordfileprefix);
227+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
228+    {
229+        cur_iAvail = getDiskSpace(recording_prefixes[index], cur_iTotal, cur_iUsed);
230+        iAvail += cur_iAvail;
231+        iTotal += cur_iTotal;
232+        iUsed += cur_iUsed;
233+    }
234 
235     storage.setAttribute("_local_:total", (int)(iTotal>>10));
236     storage.setAttribute("_local_:used" , (int)(iUsed>>10));
237Index: programs/mythbackend/main.cpp
238===================================================================
239--- programs/mythbackend/main.cpp        (revision 9611)
240+++ programs/mythbackend/main.cpp        (working copy)
241@@ -39,7 +39,6 @@
242 Scheduler *sched = NULL;
243 JobQueue *jobqueue = NULL;
244 QString pidfile;
245-QString lockfile_location;
246 HouseKeeper *housekeeping = NULL;
247 QString logfile = "";
248 
249@@ -201,7 +200,12 @@
250     if (pidfile != "")
251         unlink(pidfile.ascii());
252 
253-    unlink(lockfile_location.ascii());
254+    QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix"));
255+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
256+    {
257+        QString lockfile_location = recording_prefixes[index] + "/nfslockfile.lock";
258+        unlink(lockfile_location.ascii());
259+    }
260 
261     signal(SIGHUP, SIG_DFL);
262 }
263@@ -600,8 +604,6 @@
264 
265     VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1").arg(verboseString));
266 
267-    lockfile_location = gContext->GetSetting("RecordFilePrefix") + "/nfslockfile.lock";
268-
269     if (ismaster)
270 // Create a file in the recording directory.  A slave encoder will
271 // look for this file and return 0 bytes free if it finds it when it's
272@@ -610,14 +612,19 @@
273 // If the slave doesn't find this file then it will assume that it has
274 // a seperate store.
275     {
276-        if (creat(lockfile_location.ascii(), 0664) == -1)
277+        QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix"));
278+        for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
279         {
280-            perror(lockfile_location.ascii());
281-            cerr << "Unable to open lockfile!\n"
282-                 << "Be sure that \'" << gContext->GetSetting("RecordFilePrefix")
283-                 << "\' exists and that both \nthe directory and that "
284-                 << "file are writeable by this user.\n";
285-            return BACKEND_EXIT_OPENING_VLOCKFILE_ERROR;
286+            QString lockfile_location = recording_prefixes[index] + "/nfslockfile.lock";
287+            if (creat(lockfile_location.ascii(), 0664) == -1)
288+            {
289+                perror(lockfile_location.ascii());
290+                cerr << "Unable to open lockfile!\n"
291+                    << "Be sure that \'" << gContext->GetSetting("RecordFilePrefix")
292+                    << "\' exists and that both \nthe directory and that "
293+                    << "file are writeable by this user.\n";
294+                return BACKEND_EXIT_OPENING_VLOCKFILE_ERROR;
295+            }
296         }
297     }
298 
299Index: programs/mythbackend/autoexpire.cpp
300===================================================================
301--- programs/mythbackend/autoexpire.cpp        (revision 9611)
302+++ programs/mythbackend/autoexpire.cpp        (working copy)
303@@ -114,10 +114,32 @@
304             sharing = true;
305         else if (enc->IsConnected())
306         {
307+
308+            // to support multiple recording directories, we need to base
309+            // the expiry interval based on the SMALLEST filesystem we have
310+            // to accomplish this, iterate over all our disks & use only
311+            // the one with the least free space
312             long long total, used;
313-            beginSize  = getDiskSpace(recordFilePrefix, total, used);
314+
315+            int chosen_index = -1;
316+            long long cur_free_space = -1, lowest_free_space = -1;
317+            QStringList recording_prefixes = QStringList::split(",",recordFilePrefix);
318+            for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
319+            {
320+                cur_free_space = getDiskSpace(recording_prefixes[index], total, used);
321+                if ((cur_free_space < lowest_free_space) || (chosen_index == -1))
322+                {
323+                    lowest_free_space = cur_free_space;
324+                    chosen_index = index;
325+                }
326+                DBG_CALC_PARAM(QString("filesystem: (%1)%2, free: %3, total: %4, used: %5  (chosen %6)")
327+                               .arg(index).arg(recording_prefixes[index]).arg(cur_free_space)
328+                               .arg(total).arg(used).arg(chosen_index));
329+            }
330+
331+            beginSize  = getDiskSpace(recording_prefixes[chosen_index], total, used);
332             remoteSize = enc->GetFreeDiskSpace();
333-            endSize    = getDiskSpace(recordFilePrefix, total, used);
334+            endSize    = getDiskSpace(recording_prefixes[chosen_index], total, used);
335 
336             DBG_CALC_PARAM("CalcParams() -- A 2");
337             if (beginSize<0 || remoteSize<0 || endSize<0)
338@@ -219,7 +241,7 @@
339  *
340  *   Every "AutoExpireFrequency" minutes this will delete as many
341  *   files as needed to free "AutoExpireDiskThreshold" gigabytes of
342- *   space on the filesystem containing "RecordFilePrefix".
343+ *   space on the filesystems containing "RecordFilePrefix".
344  *
345  *   If this is run on the master backend this will also delete
346  *   programs exceeding the maximum number of episodes of that
347@@ -289,10 +311,12 @@
348     long long availFreeKB = 0;
349     long long tKB, uKB;
350 
351-    if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0)
352+    QStringList recording_prefixes = QStringList::split(",",record_file_prefix);
353+    // only ever store live tv on first recording directory ..
354+    if ((availFreeKB = getDiskSpace(recording_prefixes[0], tKB, uKB)) < 0)
355     {
356         QString msg = QString("ERROR: Could not calculate free space for %1.")
357-                              .arg(record_file_prefix);
358+                              .arg(recording_prefixes[0]);
359         VERBOSE(VB_IMPORTANT, LOC + msg);
360         gContext->LogEntry("mythbackend", LP_WARNING,
361                            "Autoexpire Recording", msg);
362@@ -302,7 +326,7 @@
363         VERBOSE(VB_FILE, LOC + QString("ExpireLiveTV(%1)").arg(type));
364         ClearExpireList();
365         FillDBOrdered(type);
366-        SendDeleteMessages(availFreeKB, 0, true);
367+        SendDeleteMessages(availFreeKB, 0, recording_prefixes[0], true);
368     }
369 }
370 
371@@ -315,39 +339,47 @@
372     long long availFreeKB = 0;
373     long long tKB, uKB;
374 
375-    if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0)
376+    // loop through all our recording directories, checking for minimum
377+    // space on each.  trigger deletions if below that threshold..
378+    QStringList recording_prefixes = QStringList::split(",",record_file_prefix);
379+    for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
380     {
381-        QString msg = QString("ERROR: Could not calculate free space.");
382-        VERBOSE(VB_IMPORTANT, LOC + msg);
383-        gContext->LogEntry("mythbackend", LP_WARNING,
384-                           "Autoexpire Recording", msg);
385-    }
386-    else if (((size_t)availFreeKB) < desired_space)
387-    {
388-        VERBOSE(VB_FILE, LOC +
389-                QString("Running autoexpire, we want %1 MB free, "
390-                        "but only have %2 MB.")
391-                .arg(desired_space/1024).arg(availFreeKB/1024));
392+        if ((availFreeKB = getDiskSpace(recording_prefixes[index], tKB, uKB)) < 0)
393+        {
394+            QString msg = QString("ERROR: Could not calculate free space for %1.")
395+                                  .arg(recording_prefixes[index]);
396+            VERBOSE(VB_IMPORTANT, LOC + msg);
397+            gContext->LogEntry("mythbackend", LP_WARNING,
398+                               "Autoexpire Recording", msg);
399+        }
400+        else if (((size_t)availFreeKB) < desired_space)
401+        {
402+            VERBOSE(VB_FILE, LOC +
403+                    QString("Running autoexpire in %1, we want %2 MB free, "
404+                            "but only have %3 MB.")
405+                    .arg(recording_prefixes[index])
406+                    .arg(desired_space/1024).arg(availFreeKB/1024));
407         
408-        FillExpireList();
409-        SendDeleteMessages(availFreeKB, desired_space);
410+            FillExpireList();
411+            SendDeleteMessages(availFreeKB, desired_space, recording_prefixes[index]);
412+        }
413     }
414 }
415 
416-/** \fn CheckFile(const ProgramInfo*, const QString&, const fsid_t&)
417+/** \fn CheckFile(const ProgramInfo*, QString&, const fsid_t&)
418  *  \brief Returns true iff file can be deleted.
419  *
420  *   CheckFile makes sure the file exists and is stored on the same file
421  *   system as the recordfileprefix.
422  *  \param pginfo           ProgramInfo for the program we wish to delete.
423- *  \param recordfileprefix Path where new recordings are stored.
424+ *  \param dir              Path where we are looking for files to remove from.
425  *  \param fsid             Unique ID of recordfileprefix's filesystem.
426  */
427 static bool CheckFile(const ProgramInfo *pginfo,
428-                      const QString &recordfileprefix,
429+                      QString &dir,
430                       const fsid_t& fsid)
431 {
432-    QString filename = pginfo->GetRecordFilename(recordfileprefix);
433+    QString filename = pginfo->GetRecordFilename(dir);
434     QFileInfo checkFile(filename);
435     if (!checkFile.exists())
436     {
437@@ -361,7 +393,8 @@
438             gContext->LogEntry("mythbackend", LP_WARNING,
439                                "Autoexpire Recording", msg);
440         }
441-        else if (pginfo->hostname == gContext->GetHostName())
442+        else if ((pginfo->hostname == gContext->GetHostName()) &&
443+                 (dir == gContext->GetSetting("RecordFilePrefix")))
444         {
445             QString msg =
446                 QString("ERROR when trying to autoexpire file: %1. "
447@@ -386,36 +419,46 @@
448     return true;
449 }
450 
451-/** \fn AutoExpire::SendDeleteMessages(size_t, size_t, bool)
452+/** \fn AutoExpire::SendDeleteMessages(size_t, size_t, QString&, bool)
453  *  \brief This sends delete message to main event thread.
454  */
455 void AutoExpire::SendDeleteMessages(size_t availFreeKB, size_t desiredFreeKB,
456-                                    bool deleteAll)
457+                                    QString &dir, bool deleteAll)
458 {
459     QString msg;
460-    fsid_t fsid = UniqueFileSystemID(record_file_prefix);
461+    fsid_t fsid = UniqueFileSystemID(dir);
462 
463     if (expire_list.size() == 0)
464     {
465         if ((!deleteAll) &&
466             (desiredFreeKB > 0) &&
467             (availFreeKB < desiredFreeKB))
468-            VERBOSE(VB_FILE, LOC + "SendDeleteMessages. WARNING: below free "
469-                    "disk space threshold, but nothing to expire~");
470+        {
471+            QString msg =
472+                QString("SendDeleteMessages. WARNING: below free "
473+                        "disk space threshold, but nothing to expire~ "
474+                        "(%1, %2 available, %3 desired)")
475+                        .arg(dir).arg(availFreeKB).arg(desiredFreeKB);
476+            VERBOSE(VB_FILE, LOC + msg);
477+        }
478         else
479-            VERBOSE(VB_FILE, LOC + "SendDeleteMessages. Nothing to expire.");
480-
481+        {
482+            QString msg =
483+                QString("SendDeleteMessages. Nothing to expire. (%1)").arg(dir);
484+            VERBOSE(VB_FILE, LOC + msg);
485+        }
486         return;
487     }
488 
489-    VERBOSE(VB_FILE, LOC + "SendDeleteMessages, cycling through expire list.");
490+    VERBOSE(VB_FILE, LOC + QString("SendDeleteMessages, cycling through "
491+                                   "expire list (%1).").arg(dir));
492     pginfolist_t::iterator it = expire_list.begin();
493     while (it != expire_list.end() &&
494            (deleteAll || availFreeKB < desiredFreeKB))
495     {
496         VERBOSE(VB_FILE, QString("    Checking %1 @ %2")
497                          .arg((*it)->chanid).arg((*it)->startts.toString()));
498-        if (CheckFile(*it, record_file_prefix, fsid))
499+        if (CheckFile(*it, dir, fsid))
500         {
501             // Print informative message
502             msg = QString("Expiring \"%1\" from %2, %3 MBytes")
503@@ -430,9 +473,10 @@
504             }
505             else
506                 msg += QString(", free space is too low (have %1 MBytes free "
507-                               ", but want %2 MBytes)")
508+                               ", but want %2 MBytes on %3)")
509                                .arg(availFreeKB/1024)
510-                               .arg(desiredFreeKB/1024);
511+                               .arg(desiredFreeKB/1024)
512+                               .arg(dir);
513 
514             if (print_verbose_messages & VB_IMPORTANT)
515                 VERBOSE(VB_IMPORTANT, msg);
516@@ -465,7 +509,7 @@
517     if (!deleteAll && availFreeKB < desiredFreeKB)
518     {
519         msg = QString("ERROR when trying to autoexpire files.  "
520-                      "No recordings available to expire.");
521+                      "No recordings available to expire on %1.").arg(dir);
522         VERBOSE(VB_IMPORTANT, LOC + msg);
523         gContext->LogEntry("mythbackend", LP_WARNING,
524                            "Autoexpire Recording", msg);
525Index: programs/mythbackend/autoexpire.h
526===================================================================
527--- programs/mythbackend/autoexpire.h        (revision 9611)
528+++ programs/mythbackend/autoexpire.h        (working copy)
529@@ -49,7 +49,7 @@
530 
531     void FillDBOrdered(int expMethod, bool allHosts = false);
532     void SendDeleteMessages(size_t availFreeKB, size_t desiredFreeKB,
533-                            bool deleteAll = false);
534+                            QString &dir, bool deleteAll = false);
535     void ClearExpireList(void);
536     void Sleep(int sleepTime);
537 
538Index: programs/mythbackend/encoderlink.cpp
539===================================================================
540--- programs/mythbackend/encoderlink.cpp        (revision 9611)
541+++ programs/mythbackend/encoderlink.cpp        (working copy)
542@@ -243,7 +243,21 @@
543     if (!use_cache)
544     {
545         if (local)
546-            freeDiskSpaceKB = getDiskSpace(recordfileprefix, totalKB, usedKB);
547+        {
548+            // since we can record to multiple mount points and always choose
549+            // the directory with the most free space, return just the space
550+            // for that one mount point
551+            long long cur_free_space;
552+            freeDiskSpaceKB = -1;
553+            QStringList recording_prefixes = QStringList::split(",",recordfileprefix);
554+            for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
555+            {
556+                cur_free_space = getDiskSpace(recording_prefixes[index], totalKB, usedKB);
557+
558+                if (cur_free_space > freeDiskSpaceKB)
559+                    freeDiskSpaceKB = cur_free_space;
560+            }
561+        }
562         else if (sock)
563         {
564             sock->GetFreeDiskSpace(totalKB, usedKB);
565Index: setup/checksetup.cpp
566===================================================================
567--- setup/checksetup.cpp        (revision 9611)
568+++ setup/checksetup.cpp        (working copy)
569@@ -60,8 +60,13 @@
570     if (query.size())
571     {
572         query.next();
573-        if (checkPath(query.value(0).toString(), probs))
574-            problemFound = true;
575+
576+        QStringList recording_prefixes = QStringList::split(",", query.value(0).toString());
577+        for (unsigned int index = 0; index < recording_prefixes.size(); ++index)
578+        {
579+            if (checkPath(recording_prefixes[index], probs))
580+                problemFound = true;
581+        }
582     }
583     else
584         VERBOSE(VB_GENERAL, QString("RecordFilePrefix is not set?"));
585Index: setup/backendsettings.cpp
586===================================================================
587--- setup/backendsettings.cpp        (revision 9611)
588+++ setup/backendsettings.cpp        (working copy)
589@@ -69,7 +69,8 @@
590     gc->setLabel(QObject::tr("Directory to hold recordings"));
591     gc->setValue("/mnt/store/");
592     gc->setHelpText(QObject::tr("All recordings get stored in this "
593-                    "directory."));
594+                    "directory (multiple directories can be specified, "
595+                    "seperated by commas)."));
596     return gc;
597 };
598