mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The new class cUnbufferedFile is used for the recording files to avoid thrashing the file system cache
This commit is contained in:
parent
998e3bd2c7
commit
697261c981
@ -1520,3 +1520,6 @@ Nicolas Huillard <nhuillard@e-dition.fr>
|
||||
|
||||
Patrick Fischer <patrick_fischer@gmx.de>
|
||||
for reporting an error in the cFilter example in PLUGINS.html
|
||||
|
||||
Ralf Müller <ralf@bj-ig.de>
|
||||
for a patch that was used to implement cUnbufferedFile
|
||||
|
4
HISTORY
4
HISTORY
@ -3886,7 +3886,7 @@ Video Disk Recorder Revision History
|
||||
- The 'sub-title' and 'bottom text' in the CAM menu can now consist of several lines.
|
||||
- Improved the CAM enquiry menu.
|
||||
|
||||
2005-10-30: Version 1.3.35
|
||||
2005-10-31: Version 1.3.35
|
||||
|
||||
- Updated 'sources.conf' (thanks to Philip Prindeville).
|
||||
- Now using daemon() instead of fork() to run VDR in daemon mode (thanks to
|
||||
@ -3910,3 +3910,5 @@ Video Disk Recorder Revision History
|
||||
- Updated the Greek OSD texts (thanks to Dimitrios Dimitrakos).
|
||||
- Updated the French OSD texts (thanks to Nicolas Huillard).
|
||||
- Fixed the cFilter example in PLUGINS.html (reported by Patrick Fischer).
|
||||
- The new class cUnbufferedFile is used for the recording files to avoid
|
||||
trashing the file system cache (based on a patch by Ralf Müller).
|
||||
|
12
cutter.c
12
cutter.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: cutter.c 1.10 2005/08/14 10:51:54 kls Exp $
|
||||
* $Id: cutter.c 1.11 2005/10/31 12:26:44 kls Exp $
|
||||
*/
|
||||
|
||||
#include "cutter.h"
|
||||
@ -18,7 +18,7 @@
|
||||
class cCuttingThread : public cThread {
|
||||
private:
|
||||
const char *error;
|
||||
int fromFile, toFile;
|
||||
cUnbufferedFile *fromFile, *toFile;
|
||||
cFileName *fromFileName, *toFileName;
|
||||
cIndexFile *fromIndex, *toIndex;
|
||||
cMarks fromMarks, toMarks;
|
||||
@ -34,7 +34,7 @@ cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
|
||||
:cThread("video cutting")
|
||||
{
|
||||
error = NULL;
|
||||
fromFile = toFile = -1;
|
||||
fromFile = toFile = NULL;
|
||||
fromFileName = toFileName = NULL;
|
||||
fromIndex = toIndex = NULL;
|
||||
if (fromMarks.Load(FromFileName) && fromMarks.Count()) {
|
||||
@ -64,7 +64,7 @@ void cCuttingThread::Action(void)
|
||||
if (Mark) {
|
||||
fromFile = fromFileName->Open();
|
||||
toFile = toFileName->Open();
|
||||
if (fromFile < 0 || toFile < 0)
|
||||
if (!fromFile || !toFile)
|
||||
return;
|
||||
int Index = Mark->position;
|
||||
Mark = fromMarks.Next(Mark);
|
||||
@ -92,7 +92,7 @@ void cCuttingThread::Action(void)
|
||||
fromFile = fromFileName->SetOffset(FileNumber, FileOffset);
|
||||
CurrentFileNumber = FileNumber;
|
||||
}
|
||||
if (fromFile >= 0) {
|
||||
if (fromFile) {
|
||||
int len = ReadFrame(fromFile, buffer, Length, sizeof(buffer));
|
||||
if (len < 0) {
|
||||
error = "ReadFrame";
|
||||
@ -131,7 +131,7 @@ void cCuttingThread::Action(void)
|
||||
cutIn = false;
|
||||
}
|
||||
}
|
||||
if (safe_write(toFile, buffer, Length) < 0) {
|
||||
if (toFile->Write(buffer, Length) < 0) {
|
||||
error = "safe_write";
|
||||
break;
|
||||
}
|
||||
|
30
dvbplayer.c
30
dvbplayer.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbplayer.c 1.40 2005/08/29 15:43:30 kls Exp $
|
||||
* $Id: dvbplayer.c 1.41 2005/10/31 12:33:48 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbplayer.h"
|
||||
@ -74,7 +74,7 @@ int cBackTrace::Get(bool Forward)
|
||||
|
||||
class cNonBlockingFileReader : public cThread {
|
||||
private:
|
||||
int f;
|
||||
cUnbufferedFile *f;
|
||||
uchar *buffer;
|
||||
int wanted;
|
||||
int length;
|
||||
@ -86,14 +86,14 @@ public:
|
||||
cNonBlockingFileReader(void);
|
||||
~cNonBlockingFileReader();
|
||||
void Clear(void);
|
||||
int Read(int FileHandle, uchar *Buffer, int Length);
|
||||
int Read(cUnbufferedFile *File, uchar *Buffer, int Length);
|
||||
bool Reading(void) { return buffer; }
|
||||
};
|
||||
|
||||
cNonBlockingFileReader::cNonBlockingFileReader(void)
|
||||
:cThread("non blocking file reader")
|
||||
{
|
||||
f = -1;
|
||||
f = NULL;
|
||||
buffer = NULL;
|
||||
wanted = length = 0;
|
||||
hasData = false;
|
||||
@ -110,7 +110,7 @@ cNonBlockingFileReader::~cNonBlockingFileReader()
|
||||
void cNonBlockingFileReader::Clear(void)
|
||||
{
|
||||
Lock();
|
||||
f = -1;
|
||||
f = NULL;
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
wanted = length = 0;
|
||||
@ -119,7 +119,7 @@ void cNonBlockingFileReader::Clear(void)
|
||||
newSet.Signal();
|
||||
}
|
||||
|
||||
int cNonBlockingFileReader::Read(int FileHandle, uchar *Buffer, int Length)
|
||||
int cNonBlockingFileReader::Read(cUnbufferedFile *File, uchar *Buffer, int Length)
|
||||
{
|
||||
if (hasData && buffer) {
|
||||
if (buffer != Buffer) {
|
||||
@ -131,7 +131,7 @@ int cNonBlockingFileReader::Read(int FileHandle, uchar *Buffer, int Length)
|
||||
return length;
|
||||
}
|
||||
if (!buffer) {
|
||||
f = FileHandle;
|
||||
f = File;
|
||||
buffer = Buffer;
|
||||
wanted = Length;
|
||||
length = 0;
|
||||
@ -146,8 +146,8 @@ void cNonBlockingFileReader::Action(void)
|
||||
{
|
||||
while (Running()) {
|
||||
Lock();
|
||||
if (!hasData && f >= 0 && buffer) {
|
||||
int r = safe_read(f, buffer + length, wanted - length);
|
||||
if (!hasData && f && buffer) {
|
||||
int r = f->Read(buffer + length, wanted - length);
|
||||
if (r >= 0) {
|
||||
length += r;
|
||||
if (!r || length == wanted) // r == 0 means EOF
|
||||
@ -181,7 +181,7 @@ private:
|
||||
cBackTrace *backTrace;
|
||||
cFileName *fileName;
|
||||
cIndexFile *index;
|
||||
int replayFile;
|
||||
cUnbufferedFile *replayFile;
|
||||
bool eof;
|
||||
bool firstPacket;
|
||||
ePlayModes playMode;
|
||||
@ -237,7 +237,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
|
||||
isyslog("replay %s", FileName);
|
||||
fileName = new cFileName(FileName, false);
|
||||
replayFile = fileName->Open();
|
||||
if (replayFile < 0)
|
||||
if (!replayFile)
|
||||
return;
|
||||
ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE);
|
||||
// Create the index file:
|
||||
@ -302,10 +302,10 @@ bool cDvbPlayer::NextFile(uchar FileNumber, int FileOffset)
|
||||
{
|
||||
if (FileNumber > 0)
|
||||
replayFile = fileName->SetOffset(FileNumber, FileOffset);
|
||||
else if (replayFile >= 0 && eof)
|
||||
else if (replayFile && eof)
|
||||
replayFile = fileName->NextFile();
|
||||
eof = false;
|
||||
return replayFile >= 0;
|
||||
return replayFile != NULL;
|
||||
}
|
||||
|
||||
int cDvbPlayer::Resume(void)
|
||||
@ -342,7 +342,7 @@ bool cDvbPlayer::Save(void)
|
||||
void cDvbPlayer::Activate(bool On)
|
||||
{
|
||||
if (On) {
|
||||
if (replayFile >= 0)
|
||||
if (replayFile)
|
||||
Start();
|
||||
}
|
||||
else
|
||||
@ -376,7 +376,7 @@ void cDvbPlayer::Action(void)
|
||||
// Read the next frame from the file:
|
||||
|
||||
if (playMode != pmStill && playMode != pmPause) {
|
||||
if (!readFrame && (replayFile >= 0 || readIndex >= 0)) {
|
||||
if (!readFrame && (replayFile || readIndex >= 0)) {
|
||||
if (!nonBlockingFileReader->Reading()) {
|
||||
if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
|
||||
uchar FileNumber;
|
||||
|
12
recorder.c
12
recorder.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recorder.c 1.15 2005/08/14 10:53:28 kls Exp $
|
||||
* $Id: recorder.c 1.16 2005/10/31 12:35:29 kls Exp $
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
@ -28,7 +28,7 @@ private:
|
||||
cIndexFile *index;
|
||||
uchar pictureType;
|
||||
int fileSize;
|
||||
int recordFile;
|
||||
cUnbufferedFile *recordFile;
|
||||
time_t lastDiskSpaceCheck;
|
||||
bool RunningLowOnDiskSpace(void);
|
||||
bool NextFile(void);
|
||||
@ -50,7 +50,7 @@ cFileWriter::cFileWriter(const char *FileName, cRemux *Remux)
|
||||
lastDiskSpaceCheck = time(NULL);
|
||||
fileName = new cFileName(FileName, true);
|
||||
recordFile = fileName->Open();
|
||||
if (recordFile < 0)
|
||||
if (!recordFile)
|
||||
return;
|
||||
// Create the index file:
|
||||
index = new cIndexFile(FileName, true);
|
||||
@ -81,13 +81,13 @@ bool cFileWriter::RunningLowOnDiskSpace(void)
|
||||
|
||||
bool cFileWriter::NextFile(void)
|
||||
{
|
||||
if (recordFile >= 0 && pictureType == I_FRAME) { // every file shall start with an I_FRAME
|
||||
if (recordFile && pictureType == I_FRAME) { // every file shall start with an I_FRAME
|
||||
if (fileSize > MEGABYTE(Setup.MaxVideoFileSize) || RunningLowOnDiskSpace()) {
|
||||
recordFile = fileName->NextFile();
|
||||
fileSize = 0;
|
||||
}
|
||||
}
|
||||
return recordFile >= 0;
|
||||
return recordFile != NULL;
|
||||
}
|
||||
|
||||
void cFileWriter::Action(void)
|
||||
@ -102,7 +102,7 @@ void cFileWriter::Action(void)
|
||||
if (NextFile()) {
|
||||
if (index && pictureType != NO_PICTURE)
|
||||
index->Write(pictureType, fileName->Number(), fileSize);
|
||||
if (safe_write(recordFile, p, Count) < 0) {
|
||||
if (recordFile->Write(p, Count) < 0) {
|
||||
LOG_ERROR_STR(fileName->Name());
|
||||
break;
|
||||
}
|
||||
|
38
recording.c
38
recording.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.c 1.121 2005/10/09 13:09:51 kls Exp $
|
||||
* $Id: recording.c 1.122 2005/10/31 12:27:58 kls Exp $
|
||||
*/
|
||||
|
||||
#include "recording.h"
|
||||
@ -1258,7 +1258,7 @@ int cIndexFile::Get(uchar FileNumber, int FileOffset)
|
||||
|
||||
cFileName::cFileName(const char *FileName, bool Record, bool Blocking)
|
||||
{
|
||||
file = -1;
|
||||
file = NULL;
|
||||
fileNumber = 0;
|
||||
record = Record;
|
||||
blocking = Blocking;
|
||||
@ -1279,21 +1279,21 @@ cFileName::~cFileName()
|
||||
free(fileName);
|
||||
}
|
||||
|
||||
int cFileName::Open(void)
|
||||
cUnbufferedFile *cFileName::Open(void)
|
||||
{
|
||||
if (file < 0) {
|
||||
if (!file) {
|
||||
int BlockingFlag = blocking ? 0 : O_NONBLOCK;
|
||||
if (record) {
|
||||
dsyslog("recording to '%s'", fileName);
|
||||
file = OpenVideoFile(fileName, O_RDWR | O_CREAT | BlockingFlag);
|
||||
if (file < 0)
|
||||
if (!file)
|
||||
LOG_ERROR_STR(fileName);
|
||||
}
|
||||
else {
|
||||
if (access(fileName, R_OK) == 0) {
|
||||
dsyslog("playing '%s'", fileName);
|
||||
file = open(fileName, O_RDONLY | BlockingFlag);
|
||||
if (file < 0)
|
||||
file = cUnbufferedFile::Create(fileName, O_RDONLY | BlockingFlag);
|
||||
if (!file)
|
||||
LOG_ERROR_STR(fileName);
|
||||
}
|
||||
else if (errno != ENOENT)
|
||||
@ -1305,14 +1305,14 @@ int cFileName::Open(void)
|
||||
|
||||
void cFileName::Close(void)
|
||||
{
|
||||
if (file >= 0) {
|
||||
if ((record && CloseVideoFile(file) < 0) || (!record && close(file) < 0))
|
||||
if (file) {
|
||||
if ((record && CloseVideoFile(file) < 0) || (!record && file->Close() < 0))
|
||||
LOG_ERROR_STR(fileName);
|
||||
file = -1;
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int cFileName::SetOffset(int Number, int Offset)
|
||||
cUnbufferedFile *cFileName::SetOffset(int Number, int Offset)
|
||||
{
|
||||
if (fileNumber != Number)
|
||||
Close();
|
||||
@ -1337,23 +1337,23 @@ int cFileName::SetOffset(int Number, int Offset)
|
||||
}
|
||||
else if (errno != ENOENT) { // something serious has happened
|
||||
LOG_ERROR_STR(fileName);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
// found a non existing file suffix
|
||||
}
|
||||
if (Open() >= 0) {
|
||||
if (!record && Offset >= 0 && lseek(file, Offset, SEEK_SET) != Offset) {
|
||||
if (!record && Offset >= 0 && file->Seek(Offset, SEEK_SET) != Offset) {
|
||||
LOG_ERROR_STR(fileName);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
esyslog("ERROR: max number of files (%d) exceeded", MAXFILESPERRECORDING);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cFileName::NextFile(void)
|
||||
cUnbufferedFile *cFileName::NextFile(void)
|
||||
{
|
||||
return SetOffset(fileNumber + 1);
|
||||
}
|
||||
@ -1387,7 +1387,7 @@ int SecondsToFrames(int Seconds)
|
||||
|
||||
// --- ReadFrame -------------------------------------------------------------
|
||||
|
||||
int ReadFrame(int f, uchar *b, int Length, int Max)
|
||||
int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max)
|
||||
{
|
||||
if (Length == -1)
|
||||
Length = Max; // this means we read up to EOF (see cIndex)
|
||||
@ -1395,10 +1395,8 @@ int ReadFrame(int f, uchar *b, int Length, int Max)
|
||||
esyslog("ERROR: frame larger than buffer (%d > %d)", Length, Max);
|
||||
Length = Max;
|
||||
}
|
||||
int r = safe_read(f, b, Length);
|
||||
int r = f->Read(b, Length);
|
||||
if (r < 0)
|
||||
LOG_ERROR;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
12
recording.h
12
recording.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.h 1.45 2005/10/01 10:24:41 kls Exp $
|
||||
* $Id: recording.h 1.46 2005/10/31 12:27:12 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RECORDING_H
|
||||
@ -203,7 +203,7 @@ public:
|
||||
|
||||
class cFileName {
|
||||
private:
|
||||
int file;
|
||||
cUnbufferedFile *file;
|
||||
int fileNumber;
|
||||
char *fileName, *pFileNumber;
|
||||
bool record;
|
||||
@ -213,10 +213,10 @@ public:
|
||||
~cFileName();
|
||||
const char *Name(void) { return fileName; }
|
||||
int Number(void) { return fileNumber; }
|
||||
int Open(void);
|
||||
cUnbufferedFile *Open(void);
|
||||
void Close(void);
|
||||
int SetOffset(int Number, int Offset = 0);
|
||||
int NextFile(void);
|
||||
cUnbufferedFile *SetOffset(int Number, int Offset = 0);
|
||||
cUnbufferedFile *NextFile(void);
|
||||
};
|
||||
|
||||
cString IndexToHMSF(int Index, bool WithFrame = false);
|
||||
@ -226,7 +226,7 @@ int HMSFToIndex(const char *HMSF);
|
||||
int SecondsToFrames(int Seconds); //XXX+ ->player???
|
||||
// Returns the number of frames corresponding to the given number of seconds.
|
||||
|
||||
int ReadFrame(int f, uchar *b, int Length, int Max);
|
||||
int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max);
|
||||
|
||||
char *ExchangeChars(char *s, bool ToFileSystem);
|
||||
// Exchanges the characters in the given string to or from a file system
|
||||
|
125
tools.c
125
tools.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.c 1.99 2005/09/25 12:56:06 kls Exp $
|
||||
* $Id: tools.c 1.100 2005/10/31 12:56:15 kls Exp $
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
@ -836,6 +836,129 @@ bool cSafeFile::Close(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
// --- cUnbufferedFile -------------------------------------------------------
|
||||
|
||||
#define READ_AHEAD MEGABYTE(2)
|
||||
#define WRITE_BUFFER MEGABYTE(10)
|
||||
|
||||
cUnbufferedFile::cUnbufferedFile(void)
|
||||
{
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
cUnbufferedFile::~cUnbufferedFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
int cUnbufferedFile::Open(const char *FileName, int Flags, mode_t Mode)
|
||||
{
|
||||
Close();
|
||||
fd = open(FileName, Flags, Mode);
|
||||
begin = end = ahead = -1;
|
||||
written = 0;
|
||||
return fd;
|
||||
}
|
||||
|
||||
int cUnbufferedFile::Close(void)
|
||||
{
|
||||
if (fd >= 0) {
|
||||
if (ahead > end)
|
||||
end = ahead;
|
||||
if (begin >= 0 && end > begin) {
|
||||
//dsyslog("close buffer: %d (flush: %d bytes, %ld-%ld)", fd, written, begin, end);
|
||||
if (written)
|
||||
fdatasync(fd);
|
||||
posix_fadvise(fd, begin, end - begin, POSIX_FADV_DONTNEED);
|
||||
}
|
||||
begin = end = ahead = -1;
|
||||
written = 0;
|
||||
}
|
||||
int OldFd = fd;
|
||||
fd = -1;
|
||||
return close(OldFd);
|
||||
}
|
||||
|
||||
off_t cUnbufferedFile::Seek(off_t Offset, int Whence)
|
||||
{
|
||||
if (fd >= 0)
|
||||
return lseek(fd, Offset, Whence);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t cUnbufferedFile::Read(void *Data, size_t Size)
|
||||
{
|
||||
if (fd >= 0) {
|
||||
off_t pos = lseek(fd, 0, SEEK_CUR);
|
||||
// jump forward - adjust end position
|
||||
if (pos > end)
|
||||
end = pos;
|
||||
// after adjusting end - don't clear more than previously requested
|
||||
if (end > ahead)
|
||||
end = ahead;
|
||||
// jump backward - drop read ahead of previous run
|
||||
if (pos < begin)
|
||||
end = ahead;
|
||||
if (begin >= 0 && end > begin)
|
||||
posix_fadvise(fd, begin - KILOBYTE(200), end - begin + KILOBYTE(200), POSIX_FADV_DONTNEED);//XXX macros/parameters???
|
||||
begin = pos;
|
||||
ssize_t bytesRead = safe_read(fd, Data, Size);
|
||||
if (bytesRead > 0) {
|
||||
pos += bytesRead;
|
||||
end = pos;
|
||||
// this seems to trigger a non blocking read - this
|
||||
// may or may not have been finished when we will be called next time.
|
||||
// If it is not finished we can't release the not yet filled buffers.
|
||||
// So this is commented out till we find a better solution.
|
||||
//posix_fadvise(fd, pos, READ_AHEAD, POSIX_FADV_WILLNEED);
|
||||
ahead = pos + READ_AHEAD;
|
||||
}
|
||||
else
|
||||
end = pos;
|
||||
return bytesRead;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t cUnbufferedFile::Write(const void *Data, size_t Size)
|
||||
{
|
||||
if (fd >=0) {
|
||||
off_t pos = lseek(fd, 0, SEEK_CUR);
|
||||
ssize_t bytesWritten = safe_write(fd, Data, Size);
|
||||
if (bytesWritten >= 0) {
|
||||
written += bytesWritten;
|
||||
if (begin >= 0) {
|
||||
if (pos < begin)
|
||||
begin = pos;
|
||||
}
|
||||
else
|
||||
begin = pos;
|
||||
if (pos + bytesWritten > end)
|
||||
end = pos + bytesWritten;
|
||||
if (written > WRITE_BUFFER) {
|
||||
//dsyslog("flush buffer: %d (%d bytes, %ld-%ld)", fd, written, begin, end);
|
||||
fdatasync(fd);
|
||||
if (begin >= 0 && end > begin)
|
||||
posix_fadvise(fd, begin, end - begin, POSIX_FADV_DONTNEED);
|
||||
begin = end = -1;
|
||||
written = 0;
|
||||
}
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
cUnbufferedFile *cUnbufferedFile::Create(const char *FileName, int Flags, mode_t Mode)
|
||||
{
|
||||
cUnbufferedFile *File = new cUnbufferedFile;
|
||||
if (File->Open(FileName, Flags, Mode) < 0) {
|
||||
delete File;
|
||||
File = NULL;
|
||||
}
|
||||
return File;
|
||||
}
|
||||
|
||||
// --- cLockFile -------------------------------------------------------------
|
||||
|
||||
#define LOCKFILENAME ".lock-vdr"
|
||||
|
23
tools.h
23
tools.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.h 1.80 2005/10/09 11:13:06 kls Exp $
|
||||
* $Id: tools.h 1.81 2005/10/31 12:54:36 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TOOLS_H
|
||||
@ -198,6 +198,27 @@ public:
|
||||
bool Close(void);
|
||||
};
|
||||
|
||||
/// cUnbufferedFile is used for large files that are mainly written or read
|
||||
/// in a streaming manner, and thus should not be cached.
|
||||
|
||||
class cUnbufferedFile {
|
||||
private:
|
||||
int fd;
|
||||
off_t begin;
|
||||
off_t end;
|
||||
off_t ahead;
|
||||
ssize_t written;
|
||||
public:
|
||||
cUnbufferedFile(void);
|
||||
~cUnbufferedFile();
|
||||
int Open(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE);
|
||||
int Close(void);
|
||||
off_t Seek(off_t Offset, int Whence);
|
||||
ssize_t Read(void *Data, size_t Size);
|
||||
ssize_t Write(const void *Data, size_t Size);
|
||||
static cUnbufferedFile *Create(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE);
|
||||
};
|
||||
|
||||
class cLockFile {
|
||||
private:
|
||||
char *fileName;
|
||||
|
21
videodir.c
21
videodir.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: videodir.c 1.12 2005/08/06 09:53:21 kls Exp $
|
||||
* $Id: videodir.c 1.13 2005/10/31 12:07:41 kls Exp $
|
||||
*/
|
||||
|
||||
#include "videodir.h"
|
||||
@ -102,7 +102,7 @@ const char *cVideoDirectory::Adjust(const char *FileName)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int OpenVideoFile(const char *FileName, int Flags)
|
||||
cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags)
|
||||
{
|
||||
const char *ActualFileName = FileName;
|
||||
|
||||
@ -110,7 +110,7 @@ int OpenVideoFile(const char *FileName, int Flags)
|
||||
if (strstr(FileName, VideoDirectory) != FileName) {
|
||||
esyslog("ERROR: %s not in %s", FileName, VideoDirectory);
|
||||
errno = ENOENT; // must set 'errno' - any ideas for a better value?
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
// Are we going to create a new file?
|
||||
if ((Flags & O_CREAT) != 0) {
|
||||
@ -128,25 +128,26 @@ int OpenVideoFile(const char *FileName, int Flags)
|
||||
if (Dir.Stored()) {
|
||||
ActualFileName = Dir.Adjust(FileName);
|
||||
if (!MakeDirs(ActualFileName, false))
|
||||
return -1; // errno has been set by MakeDirs()
|
||||
return NULL; // errno has been set by MakeDirs()
|
||||
if (symlink(ActualFileName, FileName) < 0) {
|
||||
LOG_ERROR_STR(FileName);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
ActualFileName = strdup(ActualFileName); // must survive Dir!
|
||||
}
|
||||
}
|
||||
}
|
||||
int Result = open(ActualFileName, Flags, DEFFILEMODE);
|
||||
cUnbufferedFile *File = cUnbufferedFile::Create(ActualFileName, Flags, DEFFILEMODE);
|
||||
if (ActualFileName != FileName)
|
||||
free((char *)ActualFileName);
|
||||
return Result;
|
||||
return File;
|
||||
}
|
||||
|
||||
int CloseVideoFile(int FileHandle)
|
||||
int CloseVideoFile(cUnbufferedFile *File)
|
||||
{
|
||||
// just in case we ever decide to do something special when closing the file!
|
||||
return close(FileHandle);
|
||||
int Result = File->Close();
|
||||
delete File;
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool RenameVideoFile(const char *OldName, const char *NewName)
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: videodir.h 1.5 2004/12/26 11:52:56 kls Exp $
|
||||
* $Id: videodir.h 1.6 2005/10/31 11:50:23 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __VIDEODIR_H
|
||||
@ -15,8 +15,8 @@
|
||||
|
||||
extern const char *VideoDirectory;
|
||||
|
||||
int OpenVideoFile(const char *FileName, int Flags);
|
||||
int CloseVideoFile(int FileHandle);
|
||||
cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags);
|
||||
int CloseVideoFile(cUnbufferedFile *File);
|
||||
bool RenameVideoFile(const char *OldName, const char *NewName);
|
||||
bool RemoveVideoFile(const char *FileName);
|
||||
bool VideoFileSpaceAvailable(int SizeMB);
|
||||
|
Loading…
Reference in New Issue
Block a user