Limit filesize for Timeshift on eMMC (<2GBytes)
authorsmlee <smlee@dev3>
Mon, 21 Nov 2016 09:21:53 +0000 (18:21 +0900)
committersmlee <smlee@dev3>
Mon, 21 Nov 2016 09:21:53 +0000 (18:21 +0900)
lib/base/filepush.cpp
lib/base/filepush.h
lib/dvb/dvb.cpp
lib/dvb/pmt.cpp
lib/dvb/pmt.h
lib/python/Screens/InfoBarGenerics.py
lib/service/servicedvb.cpp

index eb80914..5de9ef2 100644 (file)
@@ -1,12 +1,24 @@
 #include <lib/base/filepush.h>
 #include <lib/base/eerror.h>
 #include <lib/base/filepush.h>
 #include <lib/base/eerror.h>
+#include <lib/base/nconfig.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/vfs.h>
+#if 0
+#include <dirent.h>
+#else
+#include <sys/types.h>
+#endif
 
 #define PVR_COMMIT 1
 
 
 #define PVR_COMMIT 1
 
+#define MAJORSD_       8
+#define MAJORMMCBLK    179
+#define LIMIT_FILESIZE_NOHDD   2*1024*1024*1024LL      // 2GBytes
+
 //FILE *f = fopen("/log.ts", "wb");
 //FILE *f = fopen("/log.ts", "wb");
+static bool g_is_diskfull = false;
 
 eFilePushThread::eFilePushThread(int io_prio_class, int io_prio_level, int blocksize)
        :prio_class(io_prio_class), prio(io_prio_level), m_messagepump(eApp, 0)
 
 eFilePushThread::eFilePushThread(int io_prio_class, int io_prio_level, int blocksize)
        :prio_class(io_prio_class), prio(io_prio_level), m_messagepump(eApp, 0)
@@ -19,6 +31,7 @@ eFilePushThread::eFilePushThread(int io_prio_class, int io_prio_level, int block
        flush();
        enablePVRCommit(0);
        CONNECT(m_messagepump.recv_msg, eFilePushThread::recvEvent);
        flush();
        enablePVRCommit(0);
        CONNECT(m_messagepump.recv_msg, eFilePushThread::recvEvent);
+       m_hdd_connected = false;
 }
 
 static void signal_handler(int x)
 }
 
 static void signal_handler(int x)
@@ -37,6 +50,39 @@ void eFilePushThread::thread()
        
        size_t written_since_last_sync = 0;
 
        
        size_t written_since_last_sync = 0;
 
+       std::string tspath;
+       if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1) {
+               eDebug("could not query ts path from config");
+       }
+       tspath.append("/");
+
+#if 0
+       DIR *tsdir_info;
+       struct dirent *tsdir_entry;
+       tsdir_info = opendir("/sys/block");
+       if (tsdir_info != NULL) {
+               m_hdd_connected = false;
+               while (tsdir_entry = readdir(tsdir_info)) {
+                       if (strncmp(tsdir_entry->d_name, "sd", 2) == 0) {
+                               eDebug("HDD found: %s", tsdir_entry->d_name);
+                               m_hdd_connected = true;
+                               break;
+                       }
+               }
+       }
+#else
+       struct stat tspath_st;
+       if (stat(tspath.c_str(), &tspath_st) == 0) {
+               if (major(tspath_st.st_dev) == MAJORSD_) {
+                       eDebug("Timeshift location on HDD!");
+                       m_hdd_connected = true;
+               } else if (major(tspath_st.st_dev) == MAJORMMCBLK) {
+                       eDebug("Timeshift location on eMMC!");
+                       m_hdd_connected = false;
+               }
+       }
+#endif
+
        eDebug("FILEPUSH THREAD START");
        
                /* we set the signal to not restart syscalls, so we can detect our signal. */
        eDebug("FILEPUSH THREAD START");
        
                /* we set the signal to not restart syscalls, so we can detect our signal. */
@@ -110,6 +156,15 @@ void eFilePushThread::thread()
                                        continue;
                                eDebug("eFilePushThread WRITE ERROR");
                                sendEvent(evtWriteError);
                                        continue;
                                eDebug("eFilePushThread WRITE ERROR");
                                sendEvent(evtWriteError);
+
+                               struct statfs fs;
+                               if (statfs(tspath.c_str(), &fs) < 0) {
+                                       eDebug("statfs failed!");
+                               }
+                               if ((off_t)fs.f_bavail < 1) {
+                                       eDebug("not enough diskspace for timeshift!");
+                                       g_is_diskfull = true;
+                               }
                                break;
                                // ... we would stop the thread
                        }
                                break;
                                // ... we would stop the thread
                        }
@@ -131,6 +186,19 @@ void eFilePushThread::thread()
                        continue;
                }
 
                        continue;
                }
 
+               if (!m_hdd_connected) {
+                       struct stat limit_filesize;
+                       if (fstat(m_fd_dest, &limit_filesize) == 0) {
+                               if (limit_filesize.st_size > LIMIT_FILESIZE_NOHDD) {
+                                       eDebug("eFilePushThread %lld > %lld LIMIT FILESIZE", limit_filesize.st_size, LIMIT_FILESIZE_NOHDD);
+                                       sendEvent(evtWriteError);
+
+                                       g_is_diskfull = true;
+                                       break;
+                               }
+                       }
+               }
+
                        /* now fill our buffer. */
                        
                if (m_sg && !current_span_remaining)
                        /* now fill our buffer. */
                        
                if (m_sg && !current_span_remaining)
@@ -218,6 +286,11 @@ void eFilePushThread::thread()
                                current_span_remaining -= m_buf_end;
                }
 //             printf("FILEPUSH: read %d bytes\n", m_buf_end);
                                current_span_remaining -= m_buf_end;
                }
 //             printf("FILEPUSH: read %d bytes\n", m_buf_end);
+
+               if (g_is_diskfull) {
+                       sendEvent(evtUser+3);
+                       g_is_diskfull = false;
+               }
        }
        fdatasync(m_fd_dest);
 
        }
        fdatasync(m_fd_dest);
 
index a4457f6..3fb051e 100644 (file)
@@ -63,6 +63,7 @@ private:
        ePtr<iTsSource> m_source;
 
        eFixedMessagePump<int> m_messagepump;
        ePtr<iTsSource> m_source;
 
        eFixedMessagePump<int> m_messagepump;
+       bool m_hdd_connected;
 
        void recvEvent(const int &evt);
 };
 
        void recvEvent(const int &evt);
 };
index 0c36b7c..012a834 100755 (executable)
@@ -1426,6 +1426,10 @@ void eDVBChannel::pvrEvent(int event)
                eDebug("SOF");
                m_event(this, evtSOF);
                break;
                eDebug("SOF");
                m_event(this, evtSOF);
                break;
+       case eFilePushThread::evtUser+3: /* limit space */
+               eDebug("Too large file");
+               m_event(this, evtFailed+3);
+               break;
        }
 }
 
        }
 }
 
index 5132b38..e6c1d2c 100644 (file)
@@ -106,6 +106,9 @@ void eDVBServicePMTHandler::channelEvent(iDVBChannel *channel, int event)
        case iDVBChannel::evtSOF:
                serviceEvent(eventSOF);
                break;
        case iDVBChannel::evtSOF:
                serviceEvent(eventSOF);
                break;
+       case iDVBChannel::evtFailed+3:
+               serviceEvent(eventNoDiskSpace);
+               break;
        default:
                break;
        }
        default:
                break;
        }
index b2fc68f..eb4f593 100644 (file)
@@ -189,6 +189,7 @@ public:
                eventHBBTVInfo, /* HBBTV information was detected in the AIT */
                
                eventMisconfiguration, // a channel was not found in any list, or no frontend was found which could provide this channel
                eventHBBTVInfo, /* HBBTV information was detected in the AIT */
                
                eventMisconfiguration, // a channel was not found in any list, or no frontend was found which could provide this channel
+               eventNoDiskSpace,  // no disk space available
        };
 #ifndef SWIG
        Signal1<void,int> serviceEvent;
        };
 #ifndef SWIG
        Signal1<void,int> serviceEvent;
index 5a556c0..a6d25d5 100755 (executable)
@@ -1204,7 +1204,8 @@ class InfoBarTimeshift:
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
                                iPlayableService.evStart: self.__serviceStarted,
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
                                iPlayableService.evStart: self.__serviceStarted,
-                               iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
+                               iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
+                               iPlayableService.evUser+3: self.__lowDiskspaceMessage
                        })
 
        def getTimeshift(self):
                        })
 
        def getTimeshift(self):
@@ -1308,6 +1309,9 @@ class InfoBarTimeshift:
                self.timeshift_enabled = False
                self.__seekableStatusChanged()
 
                self.timeshift_enabled = False
                self.__seekableStatusChanged()
 
+       def __lowDiskspaceMessage(self):
+               Notifications.AddPopup(text = _("Write error. Not enough space for writing.\n"), type = MessageBox.TYPE_ERROR, timeout = 0, id = "DiskFullMessage")
+
 from Screens.PiPSetup import PiPSetup
 
 class InfoBarExtensions:
 from Screens.PiPSetup import PiPSetup
 
 class InfoBarExtensions:
index c3abb81..2bd6998 100755 (executable)
@@ -1169,6 +1169,10 @@ void eDVBServicePlay::serviceEventTimeshift(int event)
                        }
                }
                break;
                        }
                }
                break;
+       case eDVBServicePMTHandler::eventNoDiskSpace:
+               eDebug("No space!");
+               m_event((iPlayableService*)this, evUser+3);
+               break;
        }
 }
 
        }
 }