Ticket #4242: myth_IOMultiplierV2_r15966.diff
File myth_IOMultiplierV2_r15966.diff, 29.1 KB (added by , 16 years ago) |
---|
-
libs/libmythtv/ThreadedFileWriter.cpp
23 23 #define LOC_ERR QString("TFW, Error: ") 24 24 25 25 const uint ThreadedFileWriter::TFW_DEF_BUF_SIZE = 2*1024*1024; 26 const uint ThreadedFileWriter::TFW_MAX_WRITE_SIZE = TFW_DEF_BUF_SIZE / 4; 27 const uint ThreadedFileWriter::TFW_MIN_WRITE_SIZE = TFW_DEF_BUF_SIZE / 32; 26 const uint ThreadedFileWriter::TFW_MAX_WRITE_SIZE = TFW_DEF_BUF_SIZE / 27 (128 / (2<<(5-1))); 28 const uint ThreadedFileWriter::TFW_MIN_WRITE_SIZE = TFW_DEF_BUF_SIZE / 29 (1024 / (2<<(5-1))); 28 30 29 31 /** \class ThreadedFileWriter 30 32 * \brief This class supports the writing of recordings to disk. … … 114 116 * \brief Creates a threaded file writer. 115 117 */ 116 118 ThreadedFileWriter::ThreadedFileWriter(const QString &fname, 117 int pflags, mode_t pmode) : 119 int pflags, mode_t pmode, 120 uint io_mult) : 118 121 // file stuff 119 122 filename(QDeepCopy<QString>(fname)), flags(pflags), 120 123 mode(pmode), fd(-1), … … 126 129 rpos(0), wpos(0), 127 130 written(0), 128 131 // buffer 129 buf(NULL), tfw_buf_size(0) 132 buf(NULL), tfw_buf_size(0), 133 io_multiplier(io_mult) 130 134 { 131 135 } 132 136 … … 151 155 bzero(buf, TFW_DEF_BUF_SIZE + 64); 152 156 153 157 tfw_buf_size = TFW_DEF_BUF_SIZE; 154 tfw_min_write_size = TFW_MIN_WRITE_SIZE; 158 159 tfw_min_write_size = TFW_DEF_BUF_SIZE / (1024 / (2<<(io_multiplier - 1))); 160 tfw_max_write_size = TFW_DEF_BUF_SIZE / (128 / (2<<(io_multiplier - 1))); 161 162 VERBOSE(VB_RECORD, LOC + QString("Using io multiplier %1, " 163 "min/max = %2/%3") 164 .arg(io_multiplier) 165 .arg(tfw_min_write_size) 166 .arg(tfw_max_write_size)); 167 155 168 pthread_create(&writer, NULL, boot_writer, this); 156 169 pthread_create(&syncer, NULL, boot_syncer, this); 157 170 return true; … … 367 380 buffer is valid, and we try to write all of it at once which 368 381 takes a long time. During this time, the other thread fills up 369 382 the 10% that was free... */ 370 size = (size > TFW_MAX_WRITE_SIZE) ? TFW_MAX_WRITE_SIZE: size;383 size = (size > tfw_max_write_size) ? tfw_max_write_size : size; 371 384 372 385 bool write_ok; 373 386 if (ignore_writes) -
libs/libmythtv/dbcheck.cpp
14 14 #define MINIMUM_DBMS_VERSION 5 15 15 16 16 /// This is the DB schema version expected by the running MythTV instance. 17 const QString currentDatabaseVersion = "121 1";17 const QString currentDatabaseVersion = "1212"; 18 18 19 19 static bool UpdateDBVersionNumber(const QString &newnumber); 20 20 static bool performActualUpdate(const QString updates[], QString version, … … 3521 3521 return false; 3522 3522 } 3523 3523 3524 if (dbver == "1211") 3525 { 3526 const QString updates[] = { 3527 "ALTER TABLE storagegroup ADD COLUMN io_multiplier TINYINT(1) NULL; ", 3528 "" 3529 }; 3530 if (!performActualUpdate(updates, "1211", dbver)) 3531 return false; 3532 } 3533 3524 3534 //"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22 3525 3535 //"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22 3526 3536 //"ALTER TABLE recordedmarkup DROP COLUMN offset;" in 0.22 -
libs/libmythtv/RingBuffer.cpp
47 47 48 48 const uint RingBuffer::kBufferSize = 3 * 1024 * 1024; 49 49 50 #define CHUNK 32768 /*readblocksize increments */50 #define DEF_CHUNK 32768 /* default readblocksize increments */ 51 51 52 52 #define PNG_MIN_SIZE 20 /* header plus one empty chunk */ 53 53 #define NUV_MIN_SIZE 204 /* header size? */ … … 86 86 */ 87 87 RingBuffer::RingBuffer(const QString &lfilename, 88 88 bool write, bool readahead, 89 uint read_retries )89 uint read_retries, uint io_multiplier) 90 90 : filename(QDeepCopy<QString>(lfilename)), 91 91 tfw(NULL), fd2(-1), 92 92 writemode(false), … … 101 101 readsallowed(false), wantseek(false), setswitchtonext(false), 102 102 rawbitrate(4000), playspeed(1.0f), 103 103 fill_threshold(65536), fill_min(-1), 104 readblocksize( CHUNK),wanttoread(0),104 readblocksize(DEF_CHUNK), wanttoread(0), 105 105 numfailures(0), commserror(false), 106 106 dvdPriv(NULL), oldfile(false), 107 107 livetvchain(NULL), ignoreliveeof(false), … … 109 109 { 110 110 pthread_rwlock_init(&rwlock, NULL); 111 111 112 if ((io_multiplier > 5) || (io_multiplier < 2)) 113 { 114 VERBOSE(VB_IMPORTANT, LOC + QString("Read/Write multiplier value of %1 is " 115 "out of range, setting to the default value %2.") 116 .arg(io_multiplier).arg(StorageGroup::DEF_IO_MULTIPLIER)); 117 io_multiplier = StorageGroup::DEF_IO_MULTIPLIER; 118 } 119 112 120 if (write) 113 121 { 114 122 tfw = new ThreadedFileWriter( 115 filename, O_WRONLY|O_TRUNC|O_CREAT|O_LARGEFILE, 0644); 123 filename, O_WRONLY|O_TRUNC|O_CREAT|O_LARGEFILE, 0644, 124 io_multiplier); 116 125 117 126 if (!tfw->Open()) 118 127 { … … 123 132 return; 124 133 } 125 134 135 read_chunk_size = (2<<(io_multiplier - 1)) * 1024; 136 max_read_size = 640 / (32 / (2<<(io_multiplier - 1))) * 1024; 137 138 VERBOSE(VB_GENERAL, LOC + QString("Using io multiplier %1, chunk/max = " 139 "%2/%3") 140 .arg(io_multiplier) 141 .arg(read_chunk_size) 142 .arg(max_read_size)); 143 126 144 if (read_retries != (uint)-1) 127 145 OpenFile(filename, read_retries); 128 146 } … … 537 555 pthread_rwlock_wrlock(&rwlock); 538 556 wantseek = false; 539 557 readsallowed = false; 540 readblocksize = CHUNK;558 readblocksize = read_chunk_size; 541 559 542 560 // loop without sleeping if the buffered data is less than this 543 fill_threshold = CHUNK* 2;561 fill_threshold = read_chunk_size * 2; 544 562 fill_min = 1; 545 563 546 564 #ifdef USING_FRONTEND … … 612 630 void RingBuffer::ResetReadAhead(long long newinternal) 613 631 { 614 632 readAheadLock.lock(); 615 readblocksize = CHUNK;633 readblocksize = read_chunk_size; 616 634 rbrpos = 0; 617 635 rbwpos = 0; 618 636 internalreadpos = newinternal; … … 726 744 727 745 struct timeval lastread, now; 728 746 gettimeofday(&lastread, NULL); 729 const int KB640 = 640*1024;730 747 int readtimeavg = 300; 731 748 int readinterval; 732 749 733 750 pausereadthread = false; 734 751 735 readAheadBuffer = new char[kBufferSize + KB640];752 readAheadBuffer = new char[kBufferSize + max_read_size]; 736 753 737 754 ResetReadAhead(0); 738 755 totfree = ReadBufFree(); … … 783 800 784 801 readtimeavg = (readtimeavg * 9 + readinterval) / 10; 785 802 786 if (readtimeavg < 200 && readblocksize < KB640)803 if (readtimeavg < 200 && readblocksize < max_read_size) 787 804 { 788 readblocksize += CHUNK;805 readblocksize += read_chunk_size; 789 806 //VERBOSE(VB_PLAYBACK, 790 807 // QString("Avg read interval was %1 msec. %2K block size") 791 808 // .arg(readtimeavg).arg(readblocksize/1024)); 792 809 readtimeavg = 300; 793 810 } 794 else if (readtimeavg > 400 && readblocksize > CHUNK)811 else if (readtimeavg > 400 && readblocksize > read_chunk_size) 795 812 { 796 readblocksize -= CHUNK;813 readblocksize -= read_chunk_size; 797 814 //VERBOSE(VB_PLAYBACK, 798 815 // QString("Avg read interval was %1 msec. %2K block size") 799 816 // .arg(readtimeavg).arg(readblocksize/1024)); -
libs/libmythtv/tv_play.cpp
44 44 #include "datadirect.h" 45 45 #include "sourceutil.h" 46 46 #include "cardutil.h" 47 #include "storagegroup.h" 47 48 #include "util-osx-cocoa.h" 48 49 #include "compat.h" 49 50 … … 1501 1502 { 1502 1503 QString playbackURL = playbackinfo->GetPlaybackURL(); 1503 1504 1505 StorageGroup sgroup(playbackinfo->storagegroup, 1506 playbackinfo->hostname); 1507 1508 QString dirname = 1509 sgroup.FindRecordingDir(playbackinfo->GetRecordBasename()); 1510 1511 uint io_multiplier = sgroup.ioMultiplier(dirname); 1512 1504 1513 tvchain->SetProgram(playbackinfo); 1505 1514 1506 1515 bool opennow = (tvchain->GetCardType(-1) != "DUMMY"); 1507 1516 prbuffer = new RingBuffer(playbackURL, false, true, 1508 opennow ? 12 : (uint)-1); 1517 opennow ? 12 : (uint)-1, 1518 io_multiplier); 1509 1519 prbuffer->SetLiveMode(tvchain); 1510 1520 } 1511 1521 … … 1563 1573 playbackURL = playbackinfo->GetPlaybackURL( 1564 1574 desiredNextState != kState_WatchingRecording); 1565 1575 1566 prbuffer = new RingBuffer(playbackURL, false); 1576 StorageGroup sgroup(playbackinfo->storagegroup, 1577 playbackinfo->hostname); 1578 1579 QString dirname = 1580 sgroup.FindRecordingDir(playbackinfo->GetRecordBasename()); 1581 1582 uint io_multiplier = sgroup.ioMultiplier(dirname); 1583 1584 prbuffer = new RingBuffer(playbackURL, false, true, 12, io_multiplier); 1567 1585 if (prbuffer->IsOpen()) 1568 1586 { 1569 1587 gContext->DisableScreensaver(); … … 3805 3823 { 3806 3824 QString playbackURL = playbackinfo->GetPlaybackURL(); 3807 3825 3826 StorageGroup sgroup(playbackinfo->storagegroup, 3827 playbackinfo->hostname); 3828 3829 QString dirname = 3830 sgroup.FindRecordingDir(playbackinfo->GetRecordBasename()); 3831 3832 uint io_multiplier = sgroup.ioMultiplier(dirname); 3833 3808 3834 piptvchain->SetProgram(playbackinfo); 3809 piprbuffer = new RingBuffer(playbackURL, false); 3835 piprbuffer = new RingBuffer(playbackURL, false, true, 12, 3836 io_multiplier); 3810 3837 piprbuffer->SetLiveMode(piptvchain); 3811 3838 } 3812 3839 … … 4557 4584 { 4558 4585 QString playbackURL = playbackinfo->GetPlaybackURL(); 4559 4586 4587 StorageGroup sgroup(playbackinfo->storagegroup, 4588 playbackinfo->hostname); 4589 4590 QString dirname = 4591 sgroup.FindRecordingDir(playbackinfo->GetRecordBasename()); 4592 4593 uint io_multiplier = sgroup.ioMultiplier(dirname); 4594 4560 4595 tvchain->SetProgram(playbackinfo); 4561 prbuffer = new RingBuffer(playbackURL, false); 4596 prbuffer = new RingBuffer(playbackURL, false, true, 12, 4597 io_multiplier); 4562 4598 prbuffer->SetLiveMode(tvchain); 4563 4599 } 4564 4600 -
libs/libmythtv/RingBuffer.h
13 13 } 14 14 15 15 #include "mythexp.h" 16 #include "storagegroup.h" 16 17 17 18 class RemoteFile; 18 19 class RemoteEncoder; … … 24 25 { 25 26 public: 26 27 RingBuffer(const QString &lfilename, bool write, 27 bool usereadahead = true, uint read_retries = 12/*6*/); 28 bool usereadahead = true, uint read_retries = 12/*6*/, 29 uint io_multiplier = StorageGroup::DEF_IO_MULTIPLIER); 28 30 ~RingBuffer(); 29 31 30 32 // Sets … … 126 128 long long readpos; 127 129 long long writepos; 128 130 131 uint read_chunk_size; 132 uint max_read_size; 133 129 134 bool stopreads; 130 135 131 136 mutable pthread_rwlock_t rwlock; … … 155 160 float playspeed; 156 161 int fill_threshold; 157 162 int fill_min; 158 intreadblocksize;163 uint readblocksize; 159 164 160 165 QWaitCondition pauseWait; 161 166 -
libs/libmythtv/tv_rec.cpp
14 14 #include <qapplication.h> 15 15 #include <qsqldatabase.h> 16 16 #include <qsocket.h> 17 #include <qfileinfo.h> 17 18 18 19 // MythTV headers 19 20 #include "mythconfig.h" … … 3931 3932 3932 3933 if (lastTuningRequest.flags & kFlagRecording) 3933 3934 { 3934 SetRingBuffer(new RingBuffer(rec->GetFileName(), true)); 3935 StorageGroup sgroup(rec->storagegroup, gContext->GetHostName()); 3936 QString filename = rec->GetFileName(); 3937 QString dirname = QFileInfo(filename).dirPath(true); 3938 uint io_multiplier = sgroup.ioMultiplier(dirname); 3939 3940 SetRingBuffer(new RingBuffer(filename, true, true, 12, 3941 io_multiplier)); 3935 3942 if (!ringBuffer->IsOpen()) 3936 3943 { 3937 3944 VERBOSE(VB_IMPORTANT, LOC_ERR + 3938 3945 QString("RingBuffer '%1' not open...") 3939 .arg( rec->GetFileName()));3946 .arg(filename)); 3940 3947 SetRingBuffer(NULL); 3941 3948 ClearFlags(kFlagPendingActions); 3942 3949 goto err_ret; … … 4303 4310 MythEvent me(QString("QUERY_NEXT_LIVETV_DIR %1").arg(cardid)); 4304 4311 gContext->dispatch(me); 4305 4312 4313 StorageGroup sgroup(prog->storagegroup, gContext->GetHostName()); 4314 4306 4315 if (WaitForNextLiveTVDir()) 4307 4316 { 4308 4317 QMutexLocker lock(&nextLiveTVDirLock); 4309 4318 prog->pathname = nextLiveTVDir; 4310 4319 } 4311 4320 else 4312 {4313 StorageGroup sgroup("LiveTV", gContext->GetHostName());4314 4321 prog->pathname = sgroup.FindNextDirMostFree(); 4315 }4316 4322 4317 4323 StartedRecording(prog); 4318 4324 4319 *rb = new RingBuffer(prog->GetFileName(), true); 4325 QString filename = prog->GetFileName(); 4326 QString dirname = QFileInfo(filename).dirPath(true); 4327 4328 uint io_multiplier = sgroup.ioMultiplier(dirname); 4329 4330 *rb = new RingBuffer(filename, true, true, 12, io_multiplier); 4320 4331 if (!(*rb)->IsOpen()) 4321 4332 { 4322 4333 VERBOSE(VB_IMPORTANT, LOC_ERR + 4323 4334 QString("RingBuffer '%1' not open...") 4324 .arg( prog->GetFileName()));4335 .arg(filename)); 4325 4336 4326 4337 delete *rb; 4327 4338 delete prog; -
libs/libmythtv/ThreadedFileWriter.h
7 7 #include <qwaitcondition.h> 8 8 #include <qstring.h> 9 9 10 #include "storagegroup.h" 11 10 12 class ThreadedFileWriter 11 13 { 12 14 public: 13 ThreadedFileWriter(const QString &fname, int flags, mode_t mode); 15 ThreadedFileWriter(const QString &fname, int flags, mode_t mode, 16 uint io_mult = StorageGroup::DEF_IO_MULTIPLIER); 14 17 ~ThreadedFileWriter(); 15 18 16 19 bool Open(void); … … 40 43 int flags; 41 44 mode_t mode; 42 45 int fd; 46 uint io_multiplier; 43 47 44 48 // state 45 49 bool no_writes; … … 48 52 bool in_dtor; 49 53 bool ignore_writes; 50 54 long long tfw_min_write_size; 55 long long tfw_max_write_size; 51 56 52 57 // buffer position state 53 58 uint rpos; ///< points to end of data written to disk -
libs/libmyth/storagegroup.cpp
19 19 << "DB Backups" 20 20 ; 21 21 22 DirectoryConfig::DirectoryConfig(QString &dir, uint &io_multiplier) 23 { 24 ConfigurationGroup* group = new VerticalConfigurationGroup(false, false); 25 26 if (dir.isEmpty()) 27 group->setLabel(QObject::tr("Add new directory")); 28 else 29 group->setLabel(QObject::tr("Settings for directory: ") + dir); 30 31 group->addChild(new DirectoryPathSetting(dir)); 32 group->addChild(new ioMultiplierSetting(io_multiplier)); 33 34 addChild(group); 35 } 36 37 22 38 /****************************************************************************/ 23 39 24 40 /** \brief StorageGroup constructor. … … 314 330 return QDeepCopy<QStringList>(groups); 315 331 } 316 332 333 uint StorageGroup::ioMultiplier(QString dirname) 334 { 335 if (dirname.isEmpty() || m_groupname.isEmpty() || m_hostname.isEmpty()) 336 return StorageGroup::DEF_IO_MULTIPLIER; 337 338 if (dirname.right(1) != "/") 339 dirname.append("/"); 340 341 uint io_multiplier; 342 MSqlQuery query(MSqlQuery::InitCon()); 343 344 query.prepare("SELECT io_multiplier FROM storagegroup " 345 "WHERE groupname = :GROUP " 346 "AND hostname = :HOSTNAME " 347 "AND dirname = :DIRNAME;"); 348 query.bindValue(":GROUP", m_groupname); 349 query.bindValue(":HOSTNAME", m_hostname); 350 query.bindValue(":DIRNAME", dirname); 351 352 if (!query.exec() || !query.isActive()) 353 MythContext::DBError("StorageGroup::ioMultiplier()", query); 354 else if (!query.next()) 355 { 356 VERBOSE(VB_FILE, LOC + QString("Unable to find storage group %1 " 357 "for hostname %2, using default " 358 "io_multiplier of %3.") 359 .arg(m_groupname).arg(m_hostname) 360 .arg(StorageGroup::DEF_IO_MULTIPLIER)); 361 362 return StorageGroup::DEF_IO_MULTIPLIER; 363 } 364 365 io_multiplier = query.value(0).toUInt(); 366 367 if (!io_multiplier) 368 io_multiplier = StorageGroup::DEF_IO_MULTIPLIER; 369 370 return io_multiplier; 371 } 372 317 373 /****************************************************************************/ 318 374 typedef enum { 319 375 SGPopup_OK = 0, … … 385 441 386 442 if (name == "__CREATE_NEW_STORAGE_DIRECTORY__") 387 443 { 444 uint m_io_multiplier = StorageGroup::DEF_IO_MULTIPLIER; 388 445 name = ""; 389 SGPopupResult result = StorageGroupPopup::showPopup( 390 gContext->GetMainWindow(), 391 tr("Add Storage Group Directory"), 392 tr("Enter directory name or press SELECT to enter text via the " 393 "On Screen Keyboard"), name); 394 if (result == SGPopup_CANCEL) 446 447 DirectoryConfig config(name, m_io_multiplier); 448 449 if (config.exec() != MythDialog::Accepted) 395 450 return; 396 451 397 452 if (name.right(1) != "/") 398 453 name.append("/"); 399 454 400 455 MSqlQuery query(MSqlQuery::InitCon()); 401 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) " 402 "VALUES (:NAME, :HOSTNAME, :DIRNAME);"); 456 query.prepare("INSERT INTO storagegroup (groupname, hostname, " 457 "dirname, io_multiplier) " 458 "VALUES (:NAME, :HOSTNAME, :DIRNAME, :IO_MULTIPLIER);"); 403 459 query.bindValue(":NAME", m_group.utf8()); 404 460 query.bindValue(":DIRNAME", name.utf8()); 461 query.bindValue(":IO_MULTIPLIER", m_io_multiplier); 405 462 query.bindValue(":HOSTNAME", gContext->GetHostName()); 406 463 if (!query.exec()) 407 464 MythContext::DBError("StorageGroupEditor::open", query); 408 465 else 409 466 lastValue = name; 410 467 } else { 411 SGPopupResult result = StorageGroupPopup::showPopup( 412 gContext->GetMainWindow(), 413 tr("Edit Storage Group Directory"), 414 tr("Enter directory name or press SELECT to enter text via the " 415 "On Screen Keyboard"), name); 416 if (result == SGPopup_CANCEL) 468 uint m_io_multiplier = multiplier_map[name]; 469 470 if (!m_io_multiplier) 471 m_io_multiplier = StorageGroup::DEF_IO_MULTIPLIER; 472 473 DirectoryConfig config(name, m_io_multiplier); 474 475 if (config.exec() != MythDialog::Accepted) 417 476 return; 418 477 419 478 if (name.right(1) != "/") … … 431 490 if (!query.exec()) 432 491 MythContext::DBError("StorageGroupEditor::open", query); 433 492 434 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) " 435 "VALUES (:NAME, :HOSTNAME, :DIRNAME);"); 493 query.prepare("INSERT INTO storagegroup (groupname, hostname, " 494 "dirname, io_multiplier) " 495 "VALUES (:NAME, :HOSTNAME, :DIRNAME, :IO_MULTIPLIER);"); 436 496 query.bindValue(":NAME", m_group.utf8()); 437 497 query.bindValue(":DIRNAME", name.utf8()); 498 query.bindValue(":IO_MULTIPLIER", m_io_multiplier); 438 499 query.bindValue(":HOSTNAME", gContext->GetHostName()); 439 500 if (!query.exec()) 440 501 MythContext::DBError("StorageGroupEditor::open", query); … … 482 543 483 544 void StorageGroupEditor::load(void) { 484 545 listbox->clearSelections(); 546 multiplier_map.clear(); 485 547 486 548 MSqlQuery query(MSqlQuery::InitCon()); 487 query.prepare("SELECT dirname, i d FROM storagegroup "549 query.prepare("SELECT dirname, io_multiplier, id FROM storagegroup " 488 550 "WHERE groupname = :NAME AND hostname = :HOSTNAME " 489 551 "ORDER BY id;"); 490 552 query.bindValue(":NAME", m_group.utf8()); … … 502 564 first = false; 503 565 } 504 566 listbox->addSelection(query.value(0).toString()); 567 multiplier_map[query.value(0).toString()] = query.value(1).toUInt(); 505 568 } 506 569 } 507 570 … … 528 591 return dialog; 529 592 } 530 593 594 531 595 /****************************************************************************/ 532 596 533 597 StorageGroupListEditor::StorageGroupListEditor(void) : -
libs/libmyth/storagegroup.h
3 3 4 4 #include <qstringlist.h> 5 5 #include <qdeepcopy.h> 6 #include <qmap.h> 6 7 7 8 #include "libmyth/settings.h" 8 9 #include "libmyth/mythwidgets.h" 9 10 11 class DirectoryPathSetting : public LineEditSetting, public Storage 12 { 13 public: 14 DirectoryPathSetting(QString &dir) : 15 LineEditSetting(this), m_dir(dir) 16 { 17 setLabel(QObject::tr("Directory Path")); 18 QString help = QObject::tr("Specify the path to add to this " 19 "storage group."); 20 setHelpText(help); 21 } 22 23 virtual void load(void) 24 { 25 setValue(m_dir); 26 } 27 28 virtual void save(void) 29 { 30 m_dir = getValue(); 31 } 32 33 private: 34 QString &m_dir; 35 }; 36 37 class ioMultiplierSetting : public SpinBoxSetting, public Storage 38 { 39 public: 40 ioMultiplierSetting(uint &io_multiplier) : 41 SpinBoxSetting(this, 2, 5, 1), m_io_multiplier(io_multiplier) 42 { 43 setLabel(QObject::tr("Read/Write Buffer")); 44 QString help = QObject::tr("Specify the amount of buffering to " 45 "use for this directory. Default 5. " 46 "Use caution when adjusting this."); 47 setHelpText(help); 48 } 49 50 virtual void load(void) 51 { 52 setValue(m_io_multiplier); 53 } 54 55 virtual void save(void) 56 { 57 m_io_multiplier = getValue().toUInt(); 58 } 59 60 private: 61 uint &m_io_multiplier; 62 }; 63 64 class DirectoryConfig : public QObject, public ConfigurationWizard 65 { 66 public: 67 DirectoryConfig(QString &dir, uint &io_multiplier); 68 }; 69 70 10 71 class MPUBLIC StorageGroup: public ConfigurationWizard 11 72 { 12 73 public: … … 33 94 34 95 static QStringList getRecordingsGroups(void); 35 96 97 uint ioMultiplier(QString dirname); 98 99 static const uint DEF_IO_MULTIPLIER = 5; 100 36 101 private: 37 102 QString m_groupname; 38 103 QString m_hostname; 39 104 QStringList m_dirlist; 105 uint io_multiplier; 40 106 }; 41 107 42 108 class MPUBLIC StorageGroupEditor : … … 57 123 void doDelete(void); 58 124 59 125 protected: 126 void editDirectory(QString &dir, uint &io_multiplier); 127 60 128 QString m_group; 61 129 ListBoxSetting *listbox; 62 130 QString lastValue; 131 QMap<QString, uint> multiplier_map; 63 132 }; 64 133 65 134 class MPUBLIC StorageGroupListEditor : -
programs/mythbackend/mainserver.h
142 142 FileTransfer *getFileTransferByID(int id); 143 143 FileTransfer *getFileTransferBySock(MythSocket *socket); 144 144 145 QString LocalFilePath(QUrl &url );145 QString LocalFilePath(QUrl &url, uint &io_multiplier); 146 146 147 147 static void *SpawnDeleteThread(void *param); 148 148 void DoDeleteThread(const DeleteStruct *ds); -
programs/mythbackend/filetransfer.cpp
14 14 #include "libmyth/mythsocket.h" 15 15 16 16 FileTransfer::FileTransfer(QString &filename, MythSocket *remote, 17 bool usereadahead, int retries ) :17 bool usereadahead, int retries, uint io_mult) : 18 18 readthreadlive(true), 19 rbuffer(new RingBuffer(filename, false, usereadahead, retries )),19 rbuffer(new RingBuffer(filename, false, usereadahead, retries, io_mult)), 20 20 sock(remote), ateof(false), refCount(0) 21 21 { 22 22 } 23 23 24 FileTransfer::FileTransfer(QString &filename, MythSocket *remote) 24 FileTransfer::FileTransfer(QString &filename, MythSocket *remote, 25 uint io_mult) 25 26 { 26 rbuffer = new RingBuffer(filename, false );27 rbuffer = new RingBuffer(filename, false, true, 12, io_mult); 27 28 sock = remote; 28 29 readthreadlive = true; 29 30 ateof = false; -
programs/mythbackend/mainserver.cpp
1007 1007 VERBOSE(VB_IMPORTANT, QString("adding: %1 as a remote file transfer") 1008 1008 .arg(commands[2])); 1009 1009 QUrl qurl = slist[1]; 1010 QString filename = LocalFilePath(qurl);1010 uint io_multiplier = 0; 1011 1011 1012 QString filename = LocalFilePath(qurl, io_multiplier); 1013 1012 1014 FileTransfer *ft = NULL; 1013 1015 bool usereadahead = true; 1014 1016 int retries = -1; … … 1019 1021 } 1020 1022 1021 1023 if (retries >= 0) 1022 ft = new FileTransfer(filename, socket, usereadahead, retries); 1024 ft = new FileTransfer(filename, socket, usereadahead, retries, 1025 io_multiplier); 1023 1026 else 1024 ft = new FileTransfer(filename, socket );1027 ft = new FileTransfer(filename, socket, io_multiplier); 1025 1028 1026 1029 sockListLock.lock(); 1027 1030 fileTransferList.push_back(ft); … … 4233 4236 delete chain; 4234 4237 } 4235 4238 4236 QString MainServer::LocalFilePath(QUrl &url )4239 QString MainServer::LocalFilePath(QUrl &url, uint &io_multiplier) 4237 4240 { 4238 4241 QString lpath = url.path(); 4239 4242 4243 io_multiplier = StorageGroup::DEF_IO_MULTIPLIER; 4244 4240 4245 if (lpath.section('/', -2, -2) == "channels") 4241 4246 { 4242 4247 // This must be an icon request. Check channel.icon to be safe. … … 4270 4275 ProgramInfo *pginfo = ProgramInfo::GetProgramFromBasename(fpath); 4271 4276 if (pginfo) 4272 4277 { 4278 StorageGroup sgroup(pginfo->storagegroup, gContext->GetHostName()); 4279 QString dirname = 4280 sgroup.FindRecordingDir(pginfo->GetRecordBasename()); 4281 io_multiplier = sgroup.ioMultiplier(dirname); 4273 4282 QString pburl = GetPlaybackURL(pginfo); 4274 4283 if (pburl.left(1) == "/") 4275 4284 { … … 4292 4301 lpath = QFileInfo(lpath).fileName(); 4293 4302 StorageGroup sgroup; 4294 4303 QString tmpFile = sgroup.FindRecordingFile(lpath); 4304 QString tmpPath = QFileInfo(tmpFile).dirPath(true); 4305 io_multiplier = sgroup.ioMultiplier(tmpPath); 4295 4306 if (!tmpFile.isEmpty()) 4296 4307 { 4297 4308 lpath = tmpFile; -
programs/mythbackend/filetransfer.h
12 12 #include <qstring.h> 13 13 #include <qmutex.h> 14 14 15 #include "storagegroup.h" 16 15 17 class RingBuffer; 16 18 class MythSocket; 17 19 … … 20 22 friend class QObject; // quiet OSX gcc warning 21 23 22 24 public: 23 FileTransfer(QString &filename, MythSocket *remote);24 25 FileTransfer(QString &filename, MythSocket *remote, 25 bool usereadahead, int retries); 26 uint io_mult = StorageGroup::DEF_IO_MULTIPLIER); 27 FileTransfer(QString &filename, MythSocket *remote, bool usereadahead, 28 int retries, uint io_mult = StorageGroup::DEF_IO_MULTIPLIER); 26 29 27 30 MythSocket *getSocket() { return sock; } 28 31