1 | Index: libs/libmythtv/previewgenerator.cpp |
---|
2 | =================================================================== |
---|
3 | --- libs/libmythtv/previewgenerator.cpp (revision 11121) |
---|
4 | +++ libs/libmythtv/previewgenerator.cpp (working copy) |
---|
5 | @@ -65,9 +65,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())) |
---|
31 | Index: libs/libmythtv/RingBuffer.cpp |
---|
32 | =================================================================== |
---|
33 | --- libs/libmythtv/RingBuffer.cpp (revision 11121) |
---|
34 | +++ libs/libmythtv/RingBuffer.cpp (working copy) |
---|
35 | @@ -163,23 +163,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 | } |
---|
76 | Index: libs/libmythtv/tv_rec.cpp |
---|
77 | =================================================================== |
---|
78 | --- libs/libmythtv/tv_rec.cpp (revision 11121) |
---|
79 | +++ libs/libmythtv/tv_rec.cpp (working copy) |
---|
80 | @@ -638,8 +638,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) |
---|
112 | Index: libs/libmythtv/programinfo.cpp |
---|
113 | =================================================================== |
---|
114 | --- libs/libmythtv/programinfo.cpp (revision 11121) |
---|
115 | +++ libs/libmythtv/programinfo.cpp (working copy) |
---|
116 | @@ -1458,6 +1458,23 @@ |
---|
117 | */ |
---|
118 | QString ProgramInfo::GetRecordFilename(const QString &prefix) const |
---|
119 | { |
---|
120 | + // since we support multiple recording directories, try to |
---|
121 | + // find out which one we used for storing this file in .. |
---|
122 | + // if we cannot find it then just fall back to existing |
---|
123 | + // behavior |
---|
124 | + |
---|
125 | + QStringList recording_prefixes = QStringList::split(",",prefix); |
---|
126 | + QString filename; |
---|
127 | + QString basename = GetRecordBasename(); |
---|
128 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
129 | + { |
---|
130 | + filename = QString("%1/%2").arg(recording_prefixes[index]).arg(basename); |
---|
131 | + QFile checkFile(filename); |
---|
132 | + if (checkFile.exists()) |
---|
133 | + return filename; |
---|
134 | + } |
---|
135 | + |
---|
136 | + // bah - just return what we would have done previously |
---|
137 | return QString("%1/%2").arg(prefix).arg(GetRecordBasename()); |
---|
138 | } |
---|
139 | |
---|
140 | Index: programs/mythtv-setup/checksetup.cpp |
---|
141 | =================================================================== |
---|
142 | --- programs/mythtv-setup/checksetup.cpp (revision 11121) |
---|
143 | +++ programs/mythtv-setup/checksetup.cpp (working copy) |
---|
144 | @@ -60,8 +60,13 @@ |
---|
145 | if (query.size()) |
---|
146 | { |
---|
147 | query.next(); |
---|
148 | - if (checkPath(query.value(0).toString(), probs)) |
---|
149 | - problemFound = true; |
---|
150 | + |
---|
151 | + QStringList recording_prefixes = QStringList::split(",", query.value(0).toString()); |
---|
152 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
153 | + { |
---|
154 | + if (checkPath(recording_prefixes[index], probs)) |
---|
155 | + problemFound = true; |
---|
156 | + } |
---|
157 | } |
---|
158 | else |
---|
159 | VERBOSE(VB_GENERAL, QString("RecordFilePrefix is not set?")); |
---|
160 | Index: programs/mythtv-setup/backendsettings.cpp |
---|
161 | =================================================================== |
---|
162 | --- programs/mythtv-setup/backendsettings.cpp (revision 11121) |
---|
163 | +++ programs/mythtv-setup/backendsettings.cpp (working copy) |
---|
164 | @@ -70,7 +70,8 @@ |
---|
165 | gc->setLabel(QObject::tr("Directory to hold recordings")); |
---|
166 | gc->setValue("/mnt/store/"); |
---|
167 | gc->setHelpText(QObject::tr("All recordings get stored in this " |
---|
168 | - "directory.")); |
---|
169 | + "directory (multiple directories can be specified, " |
---|
170 | + "seperated by commas).")); |
---|
171 | return gc; |
---|
172 | }; |
---|
173 | |
---|
174 | Index: programs/mythbackend/mainserver.cpp |
---|
175 | =================================================================== |
---|
176 | --- programs/mythbackend/mainserver.cpp (revision 11121) |
---|
177 | +++ programs/mythbackend/mainserver.cpp (working copy) |
---|
178 | @@ -1176,16 +1176,30 @@ |
---|
179 | |
---|
180 | proginfo->stars = query.value(31).toDouble(); |
---|
181 | |
---|
182 | - QString lpath = fileprefix + "/" + basename; |
---|
183 | + // since we support multiple recording directories, |
---|
184 | + // be sure to specify actual directory where file is |
---|
185 | + // stored. if we cannot find it, fallback |
---|
186 | + QString lpath; |
---|
187 | + QStringList recording_prefixes = QStringList::split(",",fileprefix); |
---|
188 | + int found_index = -1; |
---|
189 | + for (int index = 0; index < (int)recording_prefixes.size() && found_index == -1; ++index) |
---|
190 | + { |
---|
191 | + lpath = recording_prefixes[index] + "/" + basename; |
---|
192 | + QFile checkFile(lpath); |
---|
193 | + if (checkFile.exists()) |
---|
194 | + found_index = index; |
---|
195 | + } |
---|
196 | + if (found_index == -1) |
---|
197 | + lpath = fileprefix + "/" + basename; |
---|
198 | + |
---|
199 | PlaybackSock *slave = NULL; |
---|
200 | - QFile checkFile(lpath); |
---|
201 | |
---|
202 | if (proginfo->hostname != gContext->GetHostName()) |
---|
203 | slave = getSlaveByHostname(proginfo->hostname); |
---|
204 | |
---|
205 | - if ((masterBackendOverride && checkFile.exists()) || |
---|
206 | + if ((masterBackendOverride && (found_index != -1)) || |
---|
207 | (proginfo->hostname == gContext->GetHostName()) || |
---|
208 | - (!slave && checkFile.exists())) |
---|
209 | + (!slave && (found_index != -1))) |
---|
210 | { |
---|
211 | if (islocal) |
---|
212 | proginfo->pathname = lpath; |
---|
213 | @@ -1971,7 +1985,16 @@ |
---|
214 | { |
---|
215 | QStringList strlist; |
---|
216 | long long totalKB = -1, usedKB = -1; |
---|
217 | - getDiskSpace(recordfileprefix, totalKB, usedKB); |
---|
218 | + long long cur_totalKB = -1, cur_usedKB = -1, cur_availKB = -1; |
---|
219 | + |
---|
220 | + QStringList recording_prefixes = QStringList::split(",", recordfileprefix); |
---|
221 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
222 | + { |
---|
223 | + cur_availKB = getDiskSpace(recording_prefixes[index], cur_totalKB, cur_usedKB); |
---|
224 | + totalKB += cur_totalKB; |
---|
225 | + usedKB += cur_usedKB; |
---|
226 | + } |
---|
227 | + |
---|
228 | if (!allHosts) |
---|
229 | { |
---|
230 | encodeLongLong(strlist, totalKB); |
---|
231 | @@ -3814,8 +3837,9 @@ |
---|
232 | } |
---|
233 | else |
---|
234 | { |
---|
235 | + QStringList recording_prefixes = QStringList::split(",", gContext->GetFilePrefix()); |
---|
236 | lpath = lpath.section('/', -1); |
---|
237 | - lpath = gContext->GetFilePrefix() + "/" + lpath; |
---|
238 | + lpath = recording_prefixes[0] + "/" + lpath; |
---|
239 | } |
---|
240 | VERBOSE(VB_FILE, QString("Local file path: %1").arg(lpath)); |
---|
241 | |
---|
242 | Index: programs/mythbackend/httpstatus.cpp |
---|
243 | =================================================================== |
---|
244 | --- programs/mythbackend/httpstatus.cpp (revision 11121) |
---|
245 | +++ programs/mythbackend/httpstatus.cpp (working copy) |
---|
246 | @@ -1283,8 +1283,16 @@ |
---|
247 | // drive space --------------------- |
---|
248 | |
---|
249 | long long iTotal = -1, iUsed = -1, iAvail = -1; |
---|
250 | + long long cur_iTotal = -1, cur_iUsed = -1, cur_iAvail = -1; |
---|
251 | |
---|
252 | - iAvail = getDiskSpace( gContext->GetFilePrefix(), iTotal, iUsed); |
---|
253 | + QStringList recording_prefixes = QStringList::split(",", gContext->GetFilePrefix()); |
---|
254 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
255 | + { |
---|
256 | + cur_iAvail = getDiskSpace(recording_prefixes[index], cur_iTotal, cur_iUsed); |
---|
257 | + iAvail += cur_iAvail; |
---|
258 | + iTotal += cur_iTotal; |
---|
259 | + iUsed += cur_iUsed; |
---|
260 | + } |
---|
261 | |
---|
262 | storage.setAttribute("_local_total", (int)(iTotal>>10)); |
---|
263 | storage.setAttribute("_local_used" , (int)(iUsed>>10)); |
---|
264 | Index: programs/mythbackend/main.cpp |
---|
265 | =================================================================== |
---|
266 | --- programs/mythbackend/main.cpp (revision 11121) |
---|
267 | +++ programs/mythbackend/main.cpp (working copy) |
---|
268 | @@ -45,7 +45,6 @@ |
---|
269 | Scheduler *sched = NULL; |
---|
270 | JobQueue *jobqueue = NULL; |
---|
271 | QString pidfile; |
---|
272 | -QString lockfile_location; |
---|
273 | HouseKeeper *housekeeping = NULL; |
---|
274 | QString logfile = ""; |
---|
275 | |
---|
276 | @@ -216,7 +215,12 @@ |
---|
277 | if (pidfile != "") |
---|
278 | unlink(pidfile.ascii()); |
---|
279 | |
---|
280 | - unlink(lockfile_location.ascii()); |
---|
281 | + QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix")); |
---|
282 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
283 | + { |
---|
284 | + QString lockfile_location = recording_prefixes[index] + "/nfslockfile.lock"; |
---|
285 | + unlink(lockfile_location.ascii()); |
---|
286 | + } |
---|
287 | |
---|
288 | signal(SIGHUP, SIG_DFL); |
---|
289 | } |
---|
290 | @@ -645,8 +649,6 @@ |
---|
291 | |
---|
292 | VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1").arg(verboseString)); |
---|
293 | |
---|
294 | - lockfile_location = gContext->GetSetting("RecordFilePrefix") + "/nfslockfile.lock"; |
---|
295 | - |
---|
296 | if (ismaster) |
---|
297 | // Create a file in the recording directory. A slave encoder will |
---|
298 | // look for this file and return 0 bytes free if it finds it when it's |
---|
299 | @@ -655,14 +657,19 @@ |
---|
300 | // If the slave doesn't find this file then it will assume that it has |
---|
301 | // a seperate store. |
---|
302 | { |
---|
303 | - if (creat(lockfile_location.ascii(), 0664) == -1) |
---|
304 | + QStringList recording_prefixes = QStringList::split(",", gContext->GetSetting("RecordFilePrefix")); |
---|
305 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
306 | { |
---|
307 | - perror(lockfile_location.ascii()); |
---|
308 | - cerr << "Unable to open lockfile!\n" |
---|
309 | - << "Be sure that \'" << gContext->GetSetting("RecordFilePrefix") |
---|
310 | - << "\' exists and that both \nthe directory and that " |
---|
311 | - << "file are writeable by this user.\n"; |
---|
312 | - return BACKEND_EXIT_OPENING_VLOCKFILE_ERROR; |
---|
313 | + QString lockfile_location = recording_prefixes[index] + "/nfslockfile.lock"; |
---|
314 | + if (creat(lockfile_location.ascii(), 0664) == -1) |
---|
315 | + { |
---|
316 | + perror(lockfile_location.ascii()); |
---|
317 | + cerr << "Unable to open lockfile!\n" |
---|
318 | + << "Be sure that \'" << gContext->GetSetting("RecordFilePrefix") |
---|
319 | + << "\' exists and that both \nthe directory and that " |
---|
320 | + << "file are writeable by this user.\n"; |
---|
321 | + return BACKEND_EXIT_OPENING_VLOCKFILE_ERROR; |
---|
322 | + } |
---|
323 | } |
---|
324 | } |
---|
325 | |
---|
326 | Index: programs/mythbackend/autoexpire.cpp |
---|
327 | =================================================================== |
---|
328 | --- programs/mythbackend/autoexpire.cpp (revision 11121) |
---|
329 | +++ programs/mythbackend/autoexpire.cpp (working copy) |
---|
330 | @@ -115,10 +115,32 @@ |
---|
331 | sharing = true; |
---|
332 | else if (enc->IsConnected()) |
---|
333 | { |
---|
334 | + |
---|
335 | + // to support multiple recording directories, we need to base |
---|
336 | + // the expiry interval based on the SMALLEST filesystem we have |
---|
337 | + // to accomplish this, iterate over all our disks & use only |
---|
338 | + // the one with the least free space |
---|
339 | long long total, used; |
---|
340 | - beginSize = getDiskSpace(recordFilePrefix, total, used); |
---|
341 | + |
---|
342 | + int chosen_index = -1; |
---|
343 | + long long cur_free_space = -1, lowest_free_space = -1; |
---|
344 | + QStringList recording_prefixes = QStringList::split(",",recordFilePrefix); |
---|
345 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
346 | + { |
---|
347 | + cur_free_space = getDiskSpace(recording_prefixes[index], total, used); |
---|
348 | + if ((cur_free_space < lowest_free_space) || (chosen_index == -1)) |
---|
349 | + { |
---|
350 | + lowest_free_space = cur_free_space; |
---|
351 | + chosen_index = index; |
---|
352 | + } |
---|
353 | + DBG_CALC_PARAM(QString("filesystem: (%1)%2, free: %3, total: %4, used: %5 (chosen %6)") |
---|
354 | + .arg(index).arg(recording_prefixes[index]).arg(cur_free_space) |
---|
355 | + .arg(total).arg(used).arg(chosen_index)); |
---|
356 | + } |
---|
357 | + |
---|
358 | + beginSize = getDiskSpace(recording_prefixes[chosen_index], total, used); |
---|
359 | remoteSize = enc->GetFreeDiskSpace(); |
---|
360 | - endSize = getDiskSpace(recordFilePrefix, total, used); |
---|
361 | + endSize = getDiskSpace(recording_prefixes[chosen_index], total, used); |
---|
362 | |
---|
363 | DBG_CALC_PARAM("CalcParams() -- A 2"); |
---|
364 | if (beginSize<0 || remoteSize<0 || endSize<0) |
---|
365 | @@ -221,7 +243,7 @@ |
---|
366 | * |
---|
367 | * Every "AutoExpireFrequency" minutes this will delete as many |
---|
368 | * files as needed to free "AutoExpireDiskThreshold" gigabytes of |
---|
369 | - * space on the filesystem containing "RecordFilePrefix". |
---|
370 | + * space on the filesystems containing "RecordFilePrefix". |
---|
371 | * |
---|
372 | * If this is run on the master backend this will also delete |
---|
373 | * programs exceeding the maximum number of episodes of that |
---|
374 | @@ -330,10 +352,12 @@ |
---|
375 | long long availFreeKB = 0; |
---|
376 | long long tKB, uKB; |
---|
377 | |
---|
378 | - if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0) |
---|
379 | + QStringList recording_prefixes = QStringList::split(",",record_file_prefix); |
---|
380 | + // only ever store live tv on first recording directory .. |
---|
381 | + if ((availFreeKB = getDiskSpace(recording_prefixes[0], tKB, uKB)) < 0) |
---|
382 | { |
---|
383 | QString msg = QString("ERROR: Could not calculate free space for %1.") |
---|
384 | - .arg(record_file_prefix); |
---|
385 | + .arg(recording_prefixes[0]); |
---|
386 | VERBOSE(VB_IMPORTANT, LOC + msg); |
---|
387 | gContext->LogEntry("mythbackend", LP_WARNING, |
---|
388 | "Autoexpire Recording", msg); |
---|
389 | @@ -343,7 +367,7 @@ |
---|
390 | VERBOSE(VB_FILE, LOC + QString("ExpireLiveTV(%1)").arg(type)); |
---|
391 | ClearExpireList(); |
---|
392 | FillDBOrdered(type); |
---|
393 | - SendDeleteMessages(availFreeKB, 0, true); |
---|
394 | + SendDeleteMessages(availFreeKB, 0, recording_prefixes[0], true); |
---|
395 | } |
---|
396 | } |
---|
397 | |
---|
398 | @@ -356,39 +380,47 @@ |
---|
399 | long long availFreeKB = 0; |
---|
400 | long long tKB, uKB; |
---|
401 | |
---|
402 | - if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0) |
---|
403 | + // loop through all our recording directories, checking for minimum |
---|
404 | + // space on each. trigger deletions if below that threshold.. |
---|
405 | + QStringList recording_prefixes = QStringList::split(",",record_file_prefix); |
---|
406 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
407 | { |
---|
408 | - QString msg = QString("ERROR: Could not calculate free space."); |
---|
409 | - VERBOSE(VB_IMPORTANT, LOC + msg); |
---|
410 | - gContext->LogEntry("mythbackend", LP_WARNING, |
---|
411 | - "Autoexpire Recording", msg); |
---|
412 | - } |
---|
413 | - else if (((size_t)availFreeKB) < desired_space) |
---|
414 | - { |
---|
415 | - VERBOSE(VB_FILE, LOC + |
---|
416 | - QString("Running autoexpire, we want %1 MB free, " |
---|
417 | - "but only have %2 MB.") |
---|
418 | - .arg(desired_space/1024).arg(availFreeKB/1024)); |
---|
419 | + if ((availFreeKB = getDiskSpace(recording_prefixes[index], tKB, uKB)) < 0) |
---|
420 | + { |
---|
421 | + QString msg = QString("ERROR: Could not calculate free space for %1.") |
---|
422 | + .arg(recording_prefixes[index]); |
---|
423 | + VERBOSE(VB_IMPORTANT, LOC + msg); |
---|
424 | + gContext->LogEntry("mythbackend", LP_WARNING, |
---|
425 | + "Autoexpire Recording", msg); |
---|
426 | + } |
---|
427 | + else if (((size_t)availFreeKB) < desired_space) |
---|
428 | + { |
---|
429 | + VERBOSE(VB_FILE, LOC + |
---|
430 | + QString("Running autoexpire in %1, we want %2 MB free, " |
---|
431 | + "but only have %3 MB.") |
---|
432 | + .arg(recording_prefixes[index]) |
---|
433 | + .arg(desired_space/1024).arg(availFreeKB/1024)); |
---|
434 | |
---|
435 | - FillExpireList(); |
---|
436 | - SendDeleteMessages(availFreeKB, desired_space); |
---|
437 | + FillExpireList(); |
---|
438 | + SendDeleteMessages(availFreeKB, desired_space, recording_prefixes[index]); |
---|
439 | + } |
---|
440 | } |
---|
441 | } |
---|
442 | |
---|
443 | -/** \fn CheckFile(const ProgramInfo*, const QString&, const fsid_t&) |
---|
444 | +/** \fn CheckFile(const ProgramInfo*, QString&, const fsid_t&) |
---|
445 | * \brief Returns true iff file can be deleted. |
---|
446 | * |
---|
447 | * CheckFile makes sure the file exists and is stored on the same file |
---|
448 | * system as the recordfileprefix. |
---|
449 | * \param pginfo ProgramInfo for the program we wish to delete. |
---|
450 | - * \param recordfileprefix Path where new recordings are stored. |
---|
451 | + * \param dir Path where we are looking for files to remove from. |
---|
452 | * \param fsid Unique ID of recordfileprefix's filesystem. |
---|
453 | */ |
---|
454 | static bool CheckFile(const ProgramInfo *pginfo, |
---|
455 | - const QString &recordfileprefix, |
---|
456 | + QString &dir, |
---|
457 | const fsid_t& fsid) |
---|
458 | { |
---|
459 | - QString filename = pginfo->GetRecordFilename(recordfileprefix); |
---|
460 | + QString filename = pginfo->GetRecordFilename(dir); |
---|
461 | QFileInfo checkFile(filename); |
---|
462 | if (!checkFile.exists()) |
---|
463 | { |
---|
464 | @@ -402,7 +434,8 @@ |
---|
465 | gContext->LogEntry("mythbackend", LP_WARNING, |
---|
466 | "Autoexpire Recording", msg); |
---|
467 | } |
---|
468 | - else if (pginfo->hostname == gContext->GetHostName()) |
---|
469 | + else if ((pginfo->hostname == gContext->GetHostName()) && |
---|
470 | + (dir == gContext->GetSetting("RecordFilePrefix"))) |
---|
471 | { |
---|
472 | QString msg = |
---|
473 | QString("ERROR when trying to autoexpire file: %1. " |
---|
474 | @@ -427,36 +460,46 @@ |
---|
475 | return true; |
---|
476 | } |
---|
477 | |
---|
478 | -/** \fn AutoExpire::SendDeleteMessages(size_t, size_t, bool) |
---|
479 | +/** \fn AutoExpire::SendDeleteMessages(size_t, size_t, QString&, bool) |
---|
480 | * \brief This sends delete message to main event thread. |
---|
481 | */ |
---|
482 | void AutoExpire::SendDeleteMessages(size_t availFreeKB, size_t desiredFreeKB, |
---|
483 | - bool deleteAll) |
---|
484 | + QString &dir, bool deleteAll) |
---|
485 | { |
---|
486 | QString msg; |
---|
487 | - fsid_t fsid = UniqueFileSystemID(record_file_prefix); |
---|
488 | + fsid_t fsid = UniqueFileSystemID(dir); |
---|
489 | |
---|
490 | if (expire_list.size() == 0) |
---|
491 | { |
---|
492 | if ((!deleteAll) && |
---|
493 | (desiredFreeKB > 0) && |
---|
494 | (availFreeKB < desiredFreeKB)) |
---|
495 | - VERBOSE(VB_FILE, LOC + "SendDeleteMessages. WARNING: below free " |
---|
496 | - "disk space threshold, but nothing to expire~"); |
---|
497 | + { |
---|
498 | + QString msg = |
---|
499 | + QString("SendDeleteMessages. WARNING: below free " |
---|
500 | + "disk space threshold, but nothing to expire~ " |
---|
501 | + "(%1, %2 available, %3 desired)") |
---|
502 | + .arg(dir).arg(availFreeKB).arg(desiredFreeKB); |
---|
503 | + VERBOSE(VB_FILE, LOC + msg); |
---|
504 | + } |
---|
505 | else |
---|
506 | - VERBOSE(VB_FILE, LOC + "SendDeleteMessages. Nothing to expire."); |
---|
507 | - |
---|
508 | + { |
---|
509 | + QString msg = |
---|
510 | + QString("SendDeleteMessages. Nothing to expire. (%1)").arg(dir); |
---|
511 | + VERBOSE(VB_FILE, LOC + msg); |
---|
512 | + } |
---|
513 | return; |
---|
514 | } |
---|
515 | |
---|
516 | - VERBOSE(VB_FILE, LOC + "SendDeleteMessages, cycling through expire list."); |
---|
517 | + VERBOSE(VB_FILE, LOC + QString("SendDeleteMessages, cycling through " |
---|
518 | + "expire list (%1).").arg(dir)); |
---|
519 | pginfolist_t::iterator it = expire_list.begin(); |
---|
520 | while (it != expire_list.end() && |
---|
521 | (deleteAll || availFreeKB < desiredFreeKB)) |
---|
522 | { |
---|
523 | VERBOSE(VB_FILE, QString(" Checking %1 @ %2") |
---|
524 | .arg((*it)->chanid).arg((*it)->startts.toString())); |
---|
525 | - if (CheckFile(*it, record_file_prefix, fsid)) |
---|
526 | + if (CheckFile(*it, dir, fsid)) |
---|
527 | { |
---|
528 | // Print informative message |
---|
529 | QString titlestr = (*it)->title; |
---|
530 | @@ -475,9 +518,10 @@ |
---|
531 | } |
---|
532 | else |
---|
533 | msg += QString(", free space is too low (have %1 MBytes free " |
---|
534 | - ", but want %2 MBytes)") |
---|
535 | + ", but want %2 MBytes on %3)") |
---|
536 | .arg(availFreeKB/1024) |
---|
537 | - .arg(desiredFreeKB/1024); |
---|
538 | + .arg(desiredFreeKB/1024) |
---|
539 | + .arg(dir); |
---|
540 | |
---|
541 | if (print_verbose_messages & VB_IMPORTANT) |
---|
542 | VERBOSE(VB_IMPORTANT, msg); |
---|
543 | @@ -510,7 +554,7 @@ |
---|
544 | if (!deleteAll && availFreeKB < desiredFreeKB) |
---|
545 | { |
---|
546 | msg = QString("ERROR when trying to autoexpire files. " |
---|
547 | - "No recordings available to expire."); |
---|
548 | + "No recordings available to expire on %1.").arg(dir); |
---|
549 | VERBOSE(VB_IMPORTANT, LOC + msg); |
---|
550 | gContext->LogEntry("mythbackend", LP_WARNING, |
---|
551 | "Autoexpire Recording", msg); |
---|
552 | Index: programs/mythbackend/autoexpire.h |
---|
553 | =================================================================== |
---|
554 | --- programs/mythbackend/autoexpire.h (revision 11121) |
---|
555 | +++ programs/mythbackend/autoexpire.h (working copy) |
---|
556 | @@ -60,7 +60,7 @@ |
---|
557 | |
---|
558 | void FillDBOrdered(int expMethod, bool allHosts = false); |
---|
559 | void SendDeleteMessages(size_t availFreeKB, size_t desiredFreeKB, |
---|
560 | - bool deleteAll = false); |
---|
561 | + QString &dir, bool deleteAll = false); |
---|
562 | void ClearExpireList(void); |
---|
563 | void Sleep(int sleepTime); |
---|
564 | void WaitForPendingTruncates(void); |
---|
565 | Index: programs/mythbackend/encoderlink.cpp |
---|
566 | =================================================================== |
---|
567 | --- programs/mythbackend/encoderlink.cpp (revision 11121) |
---|
568 | +++ programs/mythbackend/encoderlink.cpp (working copy) |
---|
569 | @@ -243,7 +243,21 @@ |
---|
570 | if (!use_cache) |
---|
571 | { |
---|
572 | if (local) |
---|
573 | - freeDiskSpaceKB = getDiskSpace(recordfileprefix, totalKB, usedKB); |
---|
574 | + { |
---|
575 | + // since we can record to multiple mount points and always choose |
---|
576 | + // the directory with the most free space, return just the space |
---|
577 | + // for that one mount point |
---|
578 | + long long cur_free_space; |
---|
579 | + freeDiskSpaceKB = -1; |
---|
580 | + QStringList recording_prefixes = QStringList::split(",",recordfileprefix); |
---|
581 | + for (unsigned int index = 0; index < recording_prefixes.size(); ++index) |
---|
582 | + { |
---|
583 | + cur_free_space = getDiskSpace(recording_prefixes[index], totalKB, usedKB); |
---|
584 | + |
---|
585 | + if (cur_free_space > freeDiskSpaceKB) |
---|
586 | + freeDiskSpaceKB = cur_free_space; |
---|
587 | + } |
---|
588 | + } |
---|
589 | else if (sock) |
---|
590 | { |
---|
591 | sock->GetFreeDiskSpace(totalKB, usedKB); |
---|
592 | Index: contrib/mythrename.pl |
---|
593 | =================================================================== |
---|
594 | --- contrib/mythrename.pl (revision 11121) |
---|
595 | +++ contrib/mythrename.pl (working copy) |
---|
596 | @@ -26,7 +26,7 @@ |
---|
597 | # Some variables we'll use here |
---|
598 | our ($dest, $format, $usage, $underscores, $live); |
---|
599 | our ($dformat, $dseparator, $dreplacement, $separator, $replacement); |
---|
600 | - our ($db_host, $db_user, $db_name, $db_pass, $video_dir, $verbose); |
---|
601 | + our ($db_host, $db_user, $db_name, $db_pass, $video_dirs, $verbose); |
---|
602 | our ($hostname, $dbh, $sh, $sh2, $q, $q2, $count); |
---|
603 | |
---|
604 | # Default filename format |
---|
605 | @@ -233,16 +233,19 @@ |
---|
606 | $q = 'SELECT data FROM settings WHERE value="RecordFilePrefix" AND hostname=?'; |
---|
607 | $sh = $dbh->prepare($q); |
---|
608 | $sh->execute($hostname) or die "Could not execute ($q): $!\n\n"; |
---|
609 | - ($video_dir) = $sh->fetchrow_array; |
---|
610 | + ($video_dirs) = $sh->fetchrow_array; |
---|
611 | $sh->finish; |
---|
612 | - die "This host not configured for myth.\n(No RecordFilePrefix defined for $hostname in the settings table.)\n\n" unless ($video_dir); |
---|
613 | - die "Recordings directory $video_dir doesn't exist!\n\n" unless (-d $video_dir); |
---|
614 | - $video_dir =~ s/\/+$//; |
---|
615 | + die "This host not configured for myth.\n(No RecordFilePrefix defined for $hostname in the settings table.)\n\n" unless ($video_dirs); |
---|
616 | + $video_dirs =~ s/\/+$//; |
---|
617 | + @video_dir = split(/,/,$video_dirs); |
---|
618 | + foreach $dir (@video_dir) { |
---|
619 | + die "Recordings directory $dir doesn't exist!\n\n" unless (-d $dir); |
---|
620 | + } |
---|
621 | |
---|
622 | # Link destination |
---|
623 | if (defined($dest)) { |
---|
624 | # Double-check the destination |
---|
625 | - $dest ||= "$video_dir/show_names"; |
---|
626 | + $dest ||= $video_dir[0]."/show_names"; |
---|
627 | # Alert the user |
---|
628 | vprint("Link destination directory: $dest"); |
---|
629 | # Create nonexistent paths |
---|
630 | @@ -280,7 +283,15 @@ |
---|
631 | while (my $ref = $sh->fetchrow_hashref()) { |
---|
632 | my %info = %{$ref}; |
---|
633 | die "This script requires mythtv >= 0.19\n" unless ($info{'basename'}); |
---|
634 | - next unless (-e "$video_dir/".$info{'basename'}); |
---|
635 | + |
---|
636 | + $found_dir = ""; |
---|
637 | + foreach $dir (@video_dir) { |
---|
638 | + if (-e $dir."/".$info{'basename'}) { |
---|
639 | + $found_dir = $dir; |
---|
640 | + } |
---|
641 | + } |
---|
642 | + next unless ($found_dir ne ""); |
---|
643 | + |
---|
644 | # Default times |
---|
645 | my ($syear, $smonth, $sday, $shour, $sminute, $ssecond) = $info{'starttime'} =~ /(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/; |
---|
646 | my ($eyear, $emonth, $eday, $ehour, $eminute, $esecond) = $info{'endtime'} =~ /(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/; |
---|
647 | @@ -400,17 +411,17 @@ |
---|
648 | mkpath($directory, 0, 0755) |
---|
649 | or die "Failed to create $directory: $!\n"; |
---|
650 | } |
---|
651 | - symlink "$video_dir/".$info{'basename'}, "$dest/$name" |
---|
652 | + symlink "$found_dir/".$info{'basename'}, "$dest/$name" |
---|
653 | or die "Can't create symlink $dest/$name: $!\n"; |
---|
654 | vprint("$dest/$name"); |
---|
655 | } |
---|
656 | # Rename the file, but only if it's a real file |
---|
657 | - elsif (-f "$video_dir/".$info{'basename'}) { |
---|
658 | + elsif (-f "$found_dir/".$info{'basename'}) { |
---|
659 | if ($info{'basename'} ne $name.$suffix) { |
---|
660 | # Check for duplicates |
---|
661 | - if (-e "$video_dir/$name$suffix") { |
---|
662 | + if (-e "$found_dir/$name$suffix") { |
---|
663 | $count = 2; |
---|
664 | - while (-e "$video_dir/$name.$count$suffix") { |
---|
665 | + while (-e "$found_dir/$name.$count$suffix") { |
---|
666 | $count++; |
---|
667 | } |
---|
668 | $name .= ".$count"; |
---|
669 | @@ -419,7 +430,7 @@ |
---|
670 | # Update the database |
---|
671 | my $rows = $sh2->execute($name, $info{'chanid'}, $info{'starttime'}); |
---|
672 | die "Couldn't update basename in database for ".$info{'basename'}.": ($q2)\n" unless ($rows == 1); |
---|
673 | - my $ret = rename "$video_dir/".$info{'basename'}, "$video_dir/$name"; |
---|
674 | + my $ret = rename "$found_dir/".$info{'basename'}, "$found_dir/$name"; |
---|
675 | # Rename failed -- Move the database back to how it was (man, do I miss transactions) |
---|
676 | if (!$ret) { |
---|
677 | $rows = $sh2->execute($info{'basename'}, $info{'chanid'}, $info{'starttime'}); |
---|
678 | Index: contrib/myth.rebuilddatabase.pl |
---|
679 | =================================================================== |
---|
680 | --- contrib/myth.rebuilddatabase.pl (revision 11121) |
---|
681 | +++ contrib/myth.rebuilddatabase.pl (working copy) |
---|
682 | @@ -210,7 +210,7 @@ |
---|
683 | } |
---|
684 | |
---|
685 | # remove trailing slash |
---|
686 | -$dir =~ s/\/$//; |
---|
687 | +# $dir =~ s/\/$//; |
---|
688 | |
---|
689 | if ($show_existing) { |
---|
690 | $q = "select title, subtitle, starttime, endtime, chanid from recorded order by starttime"; |
---|
691 | @@ -250,7 +250,7 @@ |
---|
692 | print "your database to see if the exist. If they do not, you will be prompted\n"; |
---|
693 | print "for a title and subtitle of the entry, and a record will be created.\n\n"; |
---|
694 | |
---|
695 | -my @files = $file ? ($dir . "/" . $file) : glob("$dir/*.$ext"); |
---|
696 | +my @files = $file ? ($dir . "/" . $file) : glob("{$dir}/*.$ext"); |
---|
697 | print "@files\n"; |
---|
698 | |
---|
699 | foreach my $show (@files) { |
---|