Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Priority based selection of video dirs (patch)



Hi,
now that I've got a second disk for recording I was unhappy with
the current sheme vdr uses to select in which video dir a file is
stored.

I build a patch which implements a priority based selection
sheme. You should create a file called "priority.vdr" in every
video dir. The file must contain a single line "Priority = x",
where x is a number between -1000 and 1000. If the file is not
found, a priority of 0 is assumed.

When selecting a dir, the dir with the highest priority which
have atleast 2*MaxVideoFileSize free space is selected. If there
a more than one dir with the same priority, the dir with the
fewest free space is selected.

This way high priority dirs are filed completely before moving to
lower priority dirs.

If all dirs have less than 2*MaxVideoFileSize free space, the old
selection sheme is used, that means the dir which have most free
space is selected.

It is wise to give your video0 dir a low priority to leave space
for the index files there.

I must admit that I throw this piece of code together quickly and it's
not very well tested at all. So be carefull.

Any fixes and suggestions welcome.



diff -urN vdr-1.0.0pre4-orig/videodir.c vdr-1.0.0pre4-prio-dirs/videodir.c
--- vdr-1.0.0pre4-orig/videodir.c	Sun Jan 27 13:37:26 2002
+++ vdr-1.0.0pre4-prio-dirs/videodir.c	Sat Mar 23 17:57:16 2002
@@ -17,91 +17,171 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include "tools.h"
+#include "config.h"
 
 const char *VideoDirectory = "/video";
 
-class cVideoDirectory {
+// --- cDir -------------------------------------------------------------------
+
+#define PRIORITY_FILE "priority.vdr"
+
+class cDir : public cListObject {
 private:
-  char *name, *stored, *adjusted;
-  int length, number, digits;
+  char *name;
+  int priority;
+  int freeMB, usedMB;
+  bool isBase;
+public:
+  cDir(const char *Name, bool IsBase=false);
+  ~cDir();
+  int Priority(void) { return priority; }
+  const char *Name(void) { return name; }
+  bool IsBase(void) { return isBase; }
+  int FreeMB(void) { return freeMB; }
+  int UsedMB(void) { return usedMB; }
+  };
+
+cDir::cDir(const char *Name, bool IsBase)
+{
+  name=strdup(Name);
+  isBase=IsBase;
+  priority=0;
+  FILE *f=fopen(AddDirectory(name,PRIORITY_FILE),"r");
+  if(f) {
+    char buff[64];
+    if(fgets(buff,sizeof(buff),f)>0) {
+      char *p=strchr(buff,'=');
+      if(p) {
+        *p=0;
+        char *Name =compactspace(buff);
+        char *Value=compactspace(p+1);
+        if(*Name && *Value && !strcasecmp(Name,"Priority"))
+          priority=atoi(Value);
+        }
+      }
+    fclose(f);
+    }
+  freeMB=FreeDiskSpaceMB(name,&usedMB);
+  //printf("added dir=%s with pri=%d free=%d used=%d\n",name,priority,freeMB,usedMB);
+}
+
+cDir::~cDir()
+{
+  delete name;
+}
+
+// --- cVideoDirectory --------------------------------------------------------
+  
+class cVideoDirectory : public cList<cDir> {
+private:
+  char *adjusted;
+  cDir *current;
 public:
   cVideoDirectory(void);
   ~cVideoDirectory();
+  void Scan(void);
   int FreeMB(int *UsedMB = NULL);
-  const char *Name(void) { return name ? name : VideoDirectory; }
-  const char *Stored(void) { return stored; }
-  int Length(void) { return length; }
-  bool IsDistributed(void) { return name != NULL; }
+  const char *Name(void) { return current->Name(); }
+  bool IsDistributed(void) { return Count()>1; }
   bool Next(void);
-  void Store(void);
   const char *Adjust(const char *FileName);
+  bool BestMatch(int minfree);
   };
 
 cVideoDirectory::cVideoDirectory(void)
 {
-  length = strlen(VideoDirectory);
-  name = (VideoDirectory[length - 1] == '0') ? strdup(VideoDirectory) : NULL;
-  stored = adjusted = NULL;
-  number = -1;
-  digits = 0;
+  adjusted = NULL;
+  Scan();
+  current=First();
 }
 
 cVideoDirectory::~cVideoDirectory()
 {
-  delete name;
-  delete stored;
   delete adjusted;
 }
 
-int cVideoDirectory::FreeMB(int *UsedMB)
+void cVideoDirectory::Scan(void)
 {
-  return FreeDiskSpaceMB(name ? name : VideoDirectory, UsedMB);
+  Clear();
+  char *name=strdup(VideoDirectory);
+  if(name) {
+    cDir *dir=new cDir(name,true);
+    Add(dir);
+
+    char *pos=name+strlen(name)-1;
+    if(*pos=='0') {
+      int digits=0;
+      while(pos!=name && isdigit(*pos)) { digits++; pos--; }
+      int num=atoi(++pos);
+      if(num==0) {    // base video directory must end with zero
+        while(1) {
+          num++;
+          char buf[16];
+          if(sprintf(buf,"%0*d",digits,num)==digits) {
+            strcpy(pos,buf);
+            if(!DirectoryOk(name)) break;
+            dir=new cDir(name);
+            Add(dir);
+            }
+          else break;
+          }
+        }
+      }
+    delete name;
+/*
+    dir=First();
+    while(dir) {
+      printf("directory name=%s pri=%d\n",dir->Name(),dir->Priority());
+      dir=cList<cDir>::Next(dir);
+      }
+*/
+    }
+}
+
+bool cVideoDirectory::BestMatch(int minfree)
+{
+  cDir *cur, *best=0, *max;
+  cur=max=First();
+  while(cur) {
+    if(cur->FreeMB()>minfree) {
+      if(!best || cur->Priority()>best->Priority() || (cur->Priority()==best->Priority() && cur->FreeMB()<best->FreeMB()))
+        best=cur;
+      }
+    if(cur->FreeMB()>max->FreeMB())
+      max=cur;
+    cur=cList<cDir>::Next(cur);
+    }
+
+  if(best) current=best;
+  else current=max;
+  //printf("selected: name=%s free=%d %s %s\n",current->Name(),current->FreeMB(),current->IsBase()?"(Base)":"",best==current?"(Best)":"");
+  return current->IsBase();
 }
 
-bool cVideoDirectory::Next(void)
+int cVideoDirectory::FreeMB(int *UsedMB)
 {
-  if (name) {
-     if (number < 0) {
-        int l = length;
-        while (l-- > 0 && isdigit(name[l]))
-              ;
-        l++;
-        digits = length - l;
-        int n = atoi(&name[l]);
-        if (n == 0)
-           number = n;
-        else
-           return false; // base video directory must end with zero
-        }
-     if (++number > 0) {
-        char buf[16];
-        if (sprintf(buf, "%0*d", digits, number) == digits) {
-           strcpy(&name[length - digits], buf);
-           return DirectoryOk(name);
-           }
-        }
-     }
-  return false;
+  if(UsedMB) *UsedMB=current->UsedMB();
+  return current->FreeMB();
 }
 
-void cVideoDirectory::Store(void)
+bool cVideoDirectory::Next(void)
 {
-  if (name) {
-     delete stored;
-     stored = strdup(name);
+  if(current) {
+     current=cList<cDir>::Next(current);
+     return current!=0;
      }
+  return false;
 }
 
 const char *cVideoDirectory::Adjust(const char *FileName)
 {
-  if (stored) {
-     delete adjusted;
-     adjusted = strdup(FileName);
-     return strncpy(adjusted, stored, length);
-     }
-  return NULL;
+  delete adjusted;
+  adjusted = strdup(FileName);
+  return strncpy(adjusted, current->Name(), strlen(current->Name()));
 }
 
+// ----------------------------------------------------------------------------
+
 int OpenVideoFile(const char *FileName, int Flags)
 {
   const char *ActualFileName = FileName;
@@ -115,26 +195,15 @@
   // Are we going to create a new file?
   if ((Flags & O_CREAT) != 0) {
      cVideoDirectory Dir;
-     if (Dir.IsDistributed()) {
-        // Find the directory with the most free space:
-        int MaxFree = Dir.FreeMB();
-        while (Dir.Next()) {
-              int Free = FreeDiskSpaceMB(Dir.Name());
-              if (Free > MaxFree) {
-                 Dir.Store();
-                 MaxFree = Free;
-                 }
-              }
-        if (Dir.Stored()) {
-           ActualFileName = Dir.Adjust(FileName);
-           if (!MakeDirs(ActualFileName, false))
-              return -1; // errno has been set by MakeDirs()
-           if (symlink(ActualFileName, FileName) < 0) {
-              LOG_ERROR_STR(FileName);
-              return -1;
-              }
-           ActualFileName = strdup(ActualFileName); // must survive Dir!
+     if(!Dir.BestMatch(Setup.MaxVideoFileSize*2)) {
+        ActualFileName = Dir.Adjust(FileName);
+        if (!MakeDirs(ActualFileName, false))
+           return -1; // errno has been set by MakeDirs()
+        if (symlink(ActualFileName, FileName) < 0) {
+           LOG_ERROR_STR(FileName);
+           return -1;
            }
+        ActualFileName = strdup(ActualFileName); // must survive Dir!
         }
      }
   int Result = open(ActualFileName, Flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);


-- 
Stefan Huelswitt
huels@iname.com  | http://home.pages.de/~nathan



Home | Main Index | Thread Index