Ticket #5746: file_placement.2.patch

File file_placement.2.patch, 8.0 KB (added by John.R.Fulton@…, 11 years ago)
  • scheduler.cpp

     
    44#include <qregexp.h>
    55#include <qstring.h>
    66#include <qdatetime.h>
     7#include <qfile.h>
    78
    89#include <iostream>
    910#include <algorithm>
     
    35143515
    35153516    // This code could probably be expanded to check the actual bitrate the
    35163517    // recording will record at for analog broadcasts that are encoded locally.
     3518    // maxSizeKB is 1/3 larger than required as this is what the auto expire
     3519    // uses
    35173520    EncoderLink *nexttv = (*m_tvList)[pginfo->cardid];
    35183521    long long maxByterate = nexttv->GetMaxBitrate() / 8;
    3519     long long maxSizeKB = maxByterate *
     3522    long long maxSizeKB = (maxByterate + maxByterate/3) *
    35203523                          pginfo->recstartts.secsTo(pginfo->recendts) / 1024;
    35213524
    35223525    // Loop though looking for a directory to put the file in.  The first time
     
    35243527    // can't find a directory that way we loop through and pick the first good
    35253528    // one from the list no matter how much free space it has.  We assume that
    35263529    // something will have to be expired for us to finish the recording.
    3527     for (unsigned int pass = 1; pass <= 2; pass++)
     3530    // pass 1: try to fit onto an existing file system with enought free space
     3531    // pass 2: fit onto the file system with the lowest priority files to be expired
     3532    //         this is used only with multiple file systems
     3533    //         Estimates are made by simulating each expiry until one of
     3534    //         the file  systems has enough sapce to fit the new file.
     3535    // pass 3: fit onto the first file system that will take it with lowest
     3536    //         priority files on this file system expired
     3537    for (unsigned int pass = 1; pass <= 3; pass++)
    35283538    {
    35293539        bool foundDir = false;
    3530         for (fslistit = fsInfoList.begin();
    3531             fslistit != fsInfoList.end(); fslistit++)
     3540
     3541        if (pass == 2 && expirer && fsInfoList.size()>1)
    35323542        {
    3533             long long desiredSpaceKB = 0;
    3534             FileSystemInfo *fs = *fslistit;
    3535             if (expirer)
    3536                 desiredSpaceKB = expirer->GetDesiredSpace(fs->fsID);
     3543            // setup a container of remaing space for all the file systems
     3544            QMap <int , long long> remainingSpaceKB;
     3545            for (fslistit = fsInfoList.begin();
     3546                fslistit != fsInfoList.end(); fslistit++)
     3547            {
     3548                     remainingSpaceKB[(*fslistit)->fsID] = (*fslistit)->freeSpaceKB;
     3549            }
    35373550
    3538             if ((fs->hostname == pginfo->hostname) &&
    3539                 (dirlist.contains(fs->directory)) &&
    3540                 ((pass == 2) ||
    3541                  (fs->freeSpaceKB > (desiredSpaceKB + maxSizeKB))))
     3551            // get list of expirable programs
     3552            pginfolist_t expiring;
     3553            expirer->GetAllExpiring(expiring);
     3554
     3555            for(pginfolist_t::iterator it=expiring.begin();
     3556                it != expiring.end(); it++)
    35423557            {
    3543                 pginfo->pathname = fs->directory;
    3544                 fsID = fs->fsID;
    35453558
    3546                 if (pass == 1)
    3547                     VERBOSE(VB_FILE, QString("'%1' will record in '%2' which "
    3548                             "has %3 MiB free. This recording could use a max "
    3549                             "of %4 MiB and the AutoExpirer wants to keep %5 "
    3550                             "MiB free.")
    3551                             .arg(pginfo->title).arg(pginfo->pathname)
    3552                             .arg(fs->freeSpaceKB / 1024).arg(maxSizeKB / 1024)
    3553                             .arg(desiredSpaceKB / 1024));
    3554                 else
    3555                     VERBOSE(VB_FILE, QString("'%1' will record in '%2' "
     3559                // find the filesystem its on
     3560                FileSystemInfo *fs=NULL;
     3561                for (fslistit = fsInfoList.begin();
     3562                    fslistit != fsInfoList.end(); fslistit++)
     3563                {
     3564                    QString filename = (*fslistit)->directory + "/" + (*it)->pathname;
     3565                    QFile checkFile(filename);
     3566
     3567                    if (checkFile.exists())
     3568                    {
     3569                        fs = *fslistit;
     3570                        break;
     3571                    }
     3572
     3573                }   
     3574
     3575                if (fs == NULL)
     3576                {
     3577                    VERBOSE(VB_IMPORTANT, QString("Unable to match '%1'"
     3578                            " to any file system. "
     3579                            " Ignoring it.")
     3580                            .arg((*it)->pathname));
     3581                    continue;
     3582                }
     3583                   
     3584
     3585                // add this files size to the remaing free space
     3586                remainingSpaceKB[fs->fsID] += (*it)->filesize / 1024;
     3587               
     3588                // check if we have enough space for new file
     3589                long long desiredSpaceKB = expirer->GetDesiredSpace(fs->fsID);
     3590
     3591                if (remainingSpaceKB[fs->fsID] > (desiredSpaceKB + maxSizeKB))
     3592                {
     3593                    pginfo->pathname = fs->directory;
     3594                    fsID = fs->fsID;
     3595
     3596                    VERBOSE(VB_FILE, QString("pass 2: '%1' will record in '%2' "
    35563597                            "although there is only %3 MiB free and the "
    35573598                            "AutoExpirer wants at least %4 MiB.  Something "
    35583599                            "will have to be deleted or expired in order for "
     
    35613602                            .arg(fs->freeSpaceKB / 1024)
    35623603                            .arg(desiredSpaceKB / 1024));
    35633604
    3564                 foundDir = true;
    3565                 break;
     3605                    foundDir = true;
     3606                    break;
     3607                }
    35663608            }
     3609 
     3610            // clean up this list - can't call CleanExpireList as it's private
     3611            ProgramInfo *pginfo = NULL;
     3612            while (expiring.size() > 0)
     3613            {
     3614                pginfo = expiring.back();
     3615                expiring.pop_back();
     3616                delete pginfo;
     3617            }
     3618
    35673619        }
     3620        else //  passes 1 & 3
     3621        {
     3622            for (fslistit = fsInfoList.begin();
     3623                fslistit != fsInfoList.end(); fslistit++)
     3624            {
     3625                long long desiredSpaceKB = 0;
     3626                FileSystemInfo *fs = *fslistit;
     3627                if (expirer)
     3628                    desiredSpaceKB = expirer->GetDesiredSpace(fs->fsID);
    35683629
     3630                if ((fs->hostname == pginfo->hostname) &&
     3631                    (dirlist.contains(fs->directory)) &&
     3632                    ((pass == 3) ||
     3633                     (fs->freeSpaceKB > (desiredSpaceKB + maxSizeKB))))
     3634                {
     3635                    pginfo->pathname = fs->directory;
     3636                    fsID = fs->fsID;
     3637
     3638                    if (pass == 1)
     3639                        VERBOSE(VB_FILE, QString("pass 1: '%1' will record in '%2' which "
     3640                                "has %3 MB free. This recording could use a max "
     3641                                "of %4 MB and the AutoExpirer wants to keep %5 "
     3642                                "MiB free.")
     3643                                .arg(pginfo->title).arg(pginfo->pathname)
     3644                                .arg(fs->freeSpaceKB / 1024).arg(maxSizeKB / 1024)
     3645                                .arg(desiredSpaceKB / 1024));
     3646                    else
     3647                        VERBOSE(VB_FILE, QString("pass 3: '%1' will record in '%2' "
     3648                                "although there is only %3 MB free and the "
     3649                                "AutoExpirer wants at least %4 MB.  Something "
     3650                                "will have to be deleted or expired in order for "
     3651                                "this recording to complete successfully.")
     3652                                .arg(pginfo->title).arg(pginfo->pathname)
     3653                                .arg(fs->freeSpaceKB / 1024)
     3654                                .arg(desiredSpaceKB / 1024));
     3655
     3656                    foundDir = true;
     3657                    break;
     3658                }
     3659            }
     3660        }
     3661
    35693662        if (foundDir)
    35703663            break;
    35713664    }