Ticket #3326: 3326-multimap-sched-v1.patch
File 3326-multimap-sched-v1.patch, 12.4 KB (added by , 18 years ago) |
---|
-
programs/mythbackend/scheduler.h
2 2 #define SCHEDULER_H_ 3 3 4 4 // C++ headers 5 #include <map> 5 6 #include <deque> 6 7 #include <vector> 7 8 using namespace std; … … 35 36 typedef RecList::iterator RecIter; 36 37 37 38 typedef vector<int> InputGroupList; 39 typedef QMap<int, RecList> CardListMap; 38 40 41 typedef multimap<uint64_t, ProgramInfo*> ConflictMap; 42 39 43 class Scheduler : public QObject 40 44 { 41 45 public: … … 77 81 void EnableScheduling(void) { schedulingEnabled = true; } 78 82 void GetNextLiveTVDir(int cardid); 79 83 84 // constants 85 static const int kConflictMapInterval; 86 static const int kConflictMapHalfInterval; 87 80 88 protected: 81 89 void RunScheduler(void); 82 90 static void *SchedulerThread(void *param); … … 100 108 void BuildListMaps(void); 101 109 void ClearListMaps(void); 102 110 111 bool IsConflicting(const ProgramInfo *p, const ProgramInfo *q, 112 bool openEnd) const; 113 103 114 bool IsSameProgram(const ProgramInfo *a, const ProgramInfo *b) const; 104 115 105 116 bool FindNextConflict(const RecList &cardlist, 106 117 const ProgramInfo *p, RecConstIter &iter, 107 118 bool openEnd = false) const; 108 const ProgramInfo *FindConflict(const QMap<int, RecList> &reclists, 109 const ProgramInfo *p, bool openEnd = false) const; 119 120 ProgramInfo *FindAnyConflict( 121 ConflictMap &map, const ProgramInfo *p, bool openend) const; 122 123 RecList FindAllConflicts( 124 ConflictMap &map, const ProgramInfo *p, bool openend) const; 125 110 126 void MarkOtherShowings(ProgramInfo *p); 111 127 void MarkShowingsList(RecList &showinglist, ProgramInfo *p); 112 128 void BackupRecStatus(void); … … 140 156 RecList reclist; 141 157 RecList worklist; 142 158 RecList retrylist; 143 QMap<int, RecList> cardlistmap;159 ConflictMap conflictmap; 144 160 QMap<int, RecList> recordidlistmap; 145 161 QMap<QString, RecList> titlelistmap; 146 162 QMap<int, InputGroupList> inputgroupmap; -
programs/mythbackend/scheduler.cpp
38 38 #define LOC QString("Scheduler: ") 39 39 #define LOC_ERR QString("Scheduler, Error: ") 40 40 41 const int Scheduler::kConflictMapInterval = 1920; 42 const int Scheduler::kConflictMapHalfInterval = 960; 43 41 44 Scheduler::Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList, 42 45 QString tmptable, Scheduler *master_sched) : 43 46 livetvTime(QDateTime()) … … 750 753 erase_nulls(worklist); 751 754 } 752 755 756 static uint insert(ConflictMap &cmap, const InputGroupList &input_groups, 757 ProgramInfo *p) 758 { 759 uint insert_cnt = 0; 760 uint64_t btimeX = min(p->recstartts.toTime_t(), 761 p->startts.toTime_t()); 762 uint64_t etimeX = max(p->recendts.toTime_t(), 763 p->endts.toTime_t()); 764 765 InputGroupList::const_iterator it = input_groups.begin(); 766 for (; it != input_groups.end(); ++it) 767 { 768 uint64_t btime = (((uint64_t)(*it)) << 32) + btimeX; 769 uint64_t etime = (((uint64_t)(*it)) << 32) + etimeX; 770 for (; btime < etime; btime += Scheduler::kConflictMapInterval) 771 { 772 cmap.insert(pair<uint64_t, ProgramInfo*>(btime, p)); 773 insert_cnt++; 774 } 775 cmap.insert(pair<uint64_t, ProgramInfo*>(etime, p)); 776 insert_cnt++; 777 } 778 779 return insert_cnt; 780 } 781 753 782 void Scheduler::BuildListMaps(void) 754 783 { 755 784 RecIter i = worklist.begin(); … … 760 789 p->recstatus == rsWillRecord || 761 790 p->recstatus == rsUnknown) 762 791 { 763 cardlistmap[p->cardid].push_back(p);792 insert(conflictmap, inputgroupmap[p->inputid], p); 764 793 titlelistmap[p->title].push_back(p); 765 794 recordidlistmap[p->recordid].push_back(p); 766 795 } … … 769 798 770 799 void Scheduler::ClearListMaps(void) 771 800 { 772 c ardlistmap.clear();801 conflictmap.clear(); 773 802 titlelistmap.clear(); 774 803 recordidlistmap.clear(); 775 VERBOSE(VB_IMPORTANT, "cache_is_same_program: "776 <<cache_is_same_program.size());777 804 cache_is_same_program.clear(); 778 805 } 779 806 807 bool Scheduler::IsConflicting( 808 const ProgramInfo *p, const ProgramInfo *q, bool openEnd) const 809 { 810 if (!Recording(q)) 811 return false; 812 813 if (p == q) 814 return false; 815 816 if (p->cardid != 0 && (p->cardid != q->cardid) && 817 !GetSharedInputGroup(p->inputid, q->inputid)) 818 { 819 return false; 820 } 821 822 if (openEnd && p->chanid != q->chanid) 823 { 824 if (p->recendts < q->recstartts || p->recstartts > q->recendts) 825 { 826 return false; 827 } 828 } 829 else 830 { 831 if (p->recendts <= q->recstartts || p->recstartts >= q->recendts) 832 { 833 return false; 834 } 835 } 836 837 // if two inputs are in the same input group we have a conflict 838 // unless the programs are on the same multiplex. 839 if (p->cardid && (p->cardid != q->cardid) && 840 GetSharedInputGroup(p->inputid, q->inputid) && 841 p->GetMplexID() && (p->GetMplexID() == q->GetMplexID())) 842 { 843 return false; 844 } 845 846 return true; 847 } 848 780 849 bool Scheduler::IsSameProgram( 781 850 const ProgramInfo *a, const ProgramInfo *b) const 782 851 { … … 799 868 RecConstIter &j, 800 869 bool openEnd) const 801 870 { 802 bool is_conflict_dbg = false;803 804 871 for ( ; j != cardlist.end(); j++) 805 872 { 806 const ProgramInfo *q = *j; 873 if (IsConflicting(p, *j, openEnd)) 874 return true; 875 } 807 876 808 if (p == q)809 continue; 877 return false; 878 } 810 879 811 if (!Recording(q)) 812 continue; 880 ProgramInfo *Scheduler::FindAnyConflict( 881 ConflictMap &cmap, const ProgramInfo *p, bool openend) const 882 { 883 QMap<ProgramInfo*,ProgramInfo*> dups; 884 uint64_t btimeX = p->recstartts.toTime_t() - kConflictMapHalfInterval - 30; 885 uint64_t etimeX = p->recendts.toTime_t() + kConflictMapHalfInterval + 30; 813 886 814 if (is_conflict_dbg) 815 cout << QString("\n comparing with '%1' ").arg(q->title); 887 const InputGroupList &ingrp = inputgroupmap[p->inputid]; 888 InputGroupList::const_iterator grpit = ingrp.begin(); 889 const ProgramInfo *last = NULL; 890 for (; grpit != ingrp.end(); ++grpit) 891 { 892 uint64_t btime = btimeX | (((uint64_t)*grpit) << 32); 893 ConflictMap::iterator beg = cmap.lower_bound(btime); 894 uint64_t etime = etimeX | (((uint64_t)*grpit) << 32); 895 ConflictMap::iterator end = cmap.upper_bound(etime); 816 896 817 if (p->cardid != 0 && (p->cardid != q->cardid) &&818 !GetSharedInputGroup(p->inputid, q->inputid))897 ConflictMap::iterator it = beg; 898 for (; it != end; ++it) 819 899 { 820 if (is_conflict_dbg) 821 cout << " cardid== "; 822 continue; 823 } 824 825 if (openEnd && p->chanid != q->chanid) 826 { 827 if (p->recendts < q->recstartts || p->recstartts > q->recendts) 828 { 829 if (is_conflict_dbg) 830 cout << " no-overlap "; 900 if ((it->second == last) || dups[it->second]) 831 901 continue; 832 } 902 last = dups[it->second] = it->second; 903 if (IsConflicting(p, it->second, openend)) 904 return it->second; 833 905 } 834 else835 {836 if (p->recendts <= q->recstartts || p->recstartts >= q->recendts)837 {838 if (is_conflict_dbg)839 cout << " no-overlap ";840 continue;841 }842 }843 844 if (is_conflict_dbg)845 cout << "\n" <<846 QString(" cardid's: %1, %2 ").arg(p->cardid).arg(q->cardid) +847 QString("Shared input group: %1 ")848 .arg(GetSharedInputGroup(p->inputid, q->inputid)) +849 QString("mplexid's: %1, %2")850 .arg(p->GetMplexID()).arg(q->GetMplexID());851 852 // if two inputs are in the same input group we have a conflict853 // unless the programs are on the same multiplex.854 if (p->cardid && (p->cardid != q->cardid) &&855 GetSharedInputGroup(p->inputid, q->inputid) &&856 p->GetMplexID() && (p->GetMplexID() == q->GetMplexID()))857 {858 continue;859 }860 861 if (is_conflict_dbg)862 cout << "\n Found conflict" << endl;863 864 return true;865 906 } 866 907 867 if (is_conflict_dbg) 868 cout << "\n No conflict" << endl; 869 870 return false; 908 return NULL; 871 909 } 872 910 873 const ProgramInfo *Scheduler::FindConflict( 874 const QMap<int, RecList> &reclists, 875 const ProgramInfo *p, 876 bool openend) const 911 RecList Scheduler::FindAllConflicts( 912 ConflictMap &cmap, const ProgramInfo *p, bool openend) const 877 913 { 878 bool is_conflict_dbg = false;914 RecList list; 879 915 880 QMap<int, RecList>::const_iterator it = reclists.begin(); 881 for (; it != reclists.end(); ++it) 916 QMap<ProgramInfo*,ProgramInfo*> dups; 917 uint64_t btimeX = p->recstartts.toTime_t() - kConflictMapHalfInterval - 30; 918 uint64_t etimeX = p->recendts.toTime_t() + kConflictMapHalfInterval + 30; 919 920 const InputGroupList &ingrp = inputgroupmap[p->inputid]; 921 InputGroupList::const_iterator grpit = ingrp.begin(); 922 const ProgramInfo *last = NULL; 923 for (; grpit != ingrp.end(); ++grpit) 882 924 { 883 if (is_conflict_dbg) 925 uint64_t btime = btimeX | (((uint64_t)*grpit) << 32); 926 ConflictMap::iterator beg = cmap.lower_bound(btime); 927 uint64_t etime = etimeX | (((uint64_t)*grpit) << 32); 928 ConflictMap::iterator end = cmap.upper_bound(etime); 929 930 ConflictMap::iterator it = beg; 931 for (; it != end; ++it) 884 932 { 885 cout << QString("Checking '%1' for conflicts on cardid %2")886 .arg(p->title).arg(it.key());887 }933 if ((it->second == last) || dups[it->second]) 934 continue; 935 last = dups[it->second] = it->second; 888 936 889 const RecList &cardlist = *it; 890 RecConstIter k = cardlist.begin(); 891 if (FindNextConflict(cardlist, p, k, openend)) 892 { 893 return *k; 937 const ProgramInfo *q = last; 938 if (openend && p->chanid != q->chanid) 939 { 940 if (p->recendts < q->recstartts || p->recstartts > q->recendts) 941 continue; 942 } 943 else 944 { 945 if (p->recendts <= q->recstartts || 946 p->recstartts >= q->recendts) 947 continue; 948 } 949 950 if (IsConflicting(p, it->second, openend)) 951 list.push_back(it->second); 894 952 } 895 953 } 896 954 897 return NULL;955 return list; 898 956 } 899 957 900 958 void Scheduler::MarkOtherShowings(ProgramInfo *p) … … 1051 1109 } 1052 1110 } 1053 1111 1054 const ProgramInfo *conflict = Find Conflict(cardlistmap, q);1112 const ProgramInfo *conflict = FindAnyConflict(conflictmap, q, false); 1055 1113 if (conflict) 1056 1114 { 1057 1115 PrintRec(conflict, " !"); … … 1100 1158 MarkOtherShowings(p); 1101 1159 else if (p->recstatus == rsUnknown) 1102 1160 { 1103 const ProgramInfo *conflict = FindConflict(cardlistmap, p, openEnd); 1161 const ProgramInfo *conflict = 1162 FindAnyConflict(conflictmap, p, openEnd); 1163 1104 1164 if (!conflict) 1105 1165 { 1106 1166 p->recstatus = rsWillRecord; … … 1160 1220 if (move_this) 1161 1221 MarkOtherShowings(p); 1162 1222 1163 RecList c ardlist;1164 QMap<int, RecList>::const_iterator it = cardlistmap.begin();1165 for (; it != cardlistmap.end(); ++it)1223 RecList conflicts = FindAllConflicts(conflictmap, p, false); 1224 RecList::iterator k = conflicts.begin(); 1225 for (; k != conflicts.end(); ++k) 1166 1226 { 1167 RecConstIter it2 = (*it).begin();1168 for (; it2 != (*it).end(); ++it2)1169 cardlist.push_back(*it2);1170 }1171 1172 RecConstIter k = cardlist.begin();1173 for ( ; FindNextConflict(cardlist, p, k); k++)1174 {1175 1227 if ((p->recpriority < (*k)->recpriority && !schedMoveHigher && 1176 1228 move_this) || !TryAnotherShowing(*k, !move_this)) 1177 1229 {