Пример #1
0
bool FileOps::CacheFile(void* destination, MythFile &source)
{
  unsigned long long totalLength = source.Length();
  unsigned long long totalRead = 0;

  const long buffersize = RCV_BUF_IMAGE_SIZE;
  char* buffer = new char[buffersize];

  while (totalRead < totalLength)
  {
    int bytes_read = source.Read(buffer, buffersize);
    if (bytes_read <= 0)
      break;

    totalRead += bytes_read;

    char *p = buffer;
    while (bytes_read > 0)
    {
      int bytes_written = XBMC->WriteFile(destination, p, bytes_read);
      if (bytes_written <= 0)
        break;

      bytes_read -= bytes_written;
      p += bytes_written;
    }
  }

  XBMC->CloseFile(destination);
  delete[] buffer;

  if (totalRead < totalLength)
    XBMC->Log(LOG_DEBUG, "%s: Failed to read all data: (%d/%d)", __FUNCTION__, totalRead, totalLength);

  return true;
}
Пример #2
0
bool FileOps::CacheFile(const CStdString &localFilename, MythFile &source)
{
  if (source.IsNull())
  {
    XBMC->Log(LOG_ERROR,"%s: NULL file provided", __FUNCTION__);
    return false;
  }

  if (source.Length() == 0)
  {
    XBMC->Log(LOG_ERROR,"%s: Empty file provided", __FUNCTION__);
    return false;
  }

  // Try to open the file. If it fails, check if we need to create the directory first.
  // This way we avoid checking if the directory exists every time.
  void *file;
  if (!(file = XBMC->OpenFileForWrite(localFilename.c_str(), true)))
  {
    CStdString cacheDirectory = GetDirectoryName(localFilename);
    if (XBMC->DirectoryExists(cacheDirectory.c_str()) || XBMC->CreateDirectory(cacheDirectory.c_str()))
    {
      if (g_bExtraDebug)
        XBMC->Log(LOG_DEBUG, "%s: Created cache directory: %s", __FUNCTION__, cacheDirectory.c_str());

      if (!(file = XBMC->OpenFileForWrite(localFilename.c_str(), true)))
      {
        XBMC->Log(LOG_ERROR, "%s: Failed to create cache file: %s", __FUNCTION__, localFilename.c_str());
        return false;
      }
    }
    else
    {
      XBMC->Log(LOG_ERROR, "%s: Failed to create cache directory: %s", __FUNCTION__, cacheDirectory.c_str());
      return false;
    }
  }

  unsigned long long totalLength = source.Length();
  unsigned long long totalRead = 0;

  const long buffersize = RCV_BUF_IMAGE_SIZE;
  char* buffer = new char[buffersize];

  while (totalRead < totalLength)
  {
    int bytes_read = source.Read(buffer, buffersize);
    if (bytes_read <= 0)
      break;

    totalRead += bytes_read;

    char *p = buffer;
    while (bytes_read > 0)
    {
      int bytes_written = XBMC->WriteFile(file, p, bytes_read);
      if (bytes_written <= 0)
        break;

      bytes_read -= bytes_written;
      p += bytes_written;
    }
  }

  XBMC->CloseFile(file);
  delete[] buffer;

  if (totalRead < totalLength)
  {
    XBMC->Log(LOG_DEBUG, "%s: Failed to read all data: %s (%d/%d)", __FUNCTION__, localFilename.c_str(), totalRead, totalLength);
  }

  return true;
}
Пример #3
0
void* FileOps::Process()
{
  XBMC->Log(LOG_DEBUG, "%s FileOps Thread Started", __FUNCTION__);

  std::list<FileOps::JobItem> jobQueueDelayed;

  while (!IsStopped())
  {
    // Wake this thread from time to time to clean the cache and recache empty files (delayed queue)
    // For caching new files, the tread is woken up by m_queueContent.Signal();
    m_queueContent.Wait(c_timeoutProcess * 1000);

    while (!m_jobQueue.empty() && !IsStopped())
    {
      Lock();
      FileOps::JobItem job = m_jobQueue.front();
      m_jobQueue.pop_front();
      Unlock();

      if (g_bExtraDebug)
        XBMC->Log(LOG_DEBUG,"%s Job fetched: local: %s, remote: %s, storagegroup: %s", __FUNCTION__, job.m_localFilename.c_str(), job.m_remoteFilename.c_str(), job.m_storageGroup.c_str());

      // Connect to the file and cache it to the local addon cache
      MythFile file = m_con.ConnectPath(job.m_remoteFilename, job.m_storageGroup);
      if (!file.IsNull() && file.Length() > 0)
      {
        if (CacheFile(job.m_localFilename.c_str(), file))
        {
          if (g_bExtraDebug)
            XBMC->Log(LOG_DEBUG, "%s File Cached: local: %s, remote: %s, type: %s", __FUNCTION__, job.m_localFilename.c_str(), job.m_remoteFilename.c_str(), job.m_storageGroup.c_str());
        }
        else
        {
          XBMC->Log(LOG_DEBUG, "%s Caching file failed: local: %s, remote: %s, type: %s", __FUNCTION__, job.m_localFilename.c_str(), job.m_remoteFilename.c_str(), job.m_storageGroup.c_str());
          if (XBMC->FileExists(job.m_localFilename.c_str(), true))
          {
            XBMC->DeleteFile(job.m_localFilename.c_str());
          }
        }
      }
      else
      {
        // Failed to open file for reading. Unfortunately it cannot be determined if this is a permanent or a temporary problem (new recording's preview hasn't been generated yet).
        // Increase the error count and retry to cache the file a few times
        if (file.IsNull())
        {
          XBMC->Log(LOG_ERROR, "%s Failed to read file: local: %s, remote: %s, type: %s", __FUNCTION__, job.m_localFilename.c_str(), job.m_remoteFilename.c_str(), job.m_storageGroup.c_str());
          job.m_errorCount += 1;
        }

        // File was empty (this happens usually for new recordings where the preview image hasn't been generated yet)
        // This is not an error, always try to recache the file
        else if (file.Length() == 0)
        {
          XBMC->Log(LOG_DEBUG, "%s File is empty: local: %s, remote: %s, type: %s", __FUNCTION__, job.m_localFilename.c_str(), job.m_remoteFilename.c_str(), job.m_storageGroup.c_str());
        }

        // Recache the file if it hasn't exceeded the maximum number of allowed attempts
        if (job.m_errorCount <= c_maximumAttemptsOnReadError)
        {
          XBMC->Log(LOG_DEBUG, "%s Delayed recache file: local: %s, remote: %s, type: %s", __FUNCTION__, job.m_localFilename.c_str(), job.m_remoteFilename.c_str(), job.m_storageGroup.c_str());
          jobQueueDelayed.push_back(job);
        }
      }
    }

    // Try to recache the currently empty files
    Lock();
    m_jobQueue.insert(m_jobQueue.end(), jobQueueDelayed.begin(), jobQueueDelayed.end());
    jobQueueDelayed.clear();
    Unlock();
  }

  XBMC->Log(LOG_DEBUG, "%s FileOps Thread Stopped", __FUNCTION__);
  return NULL;
}
Пример #4
0
CStdString fileOps::GetFileFromBackend ( CStdString filenameToGet, CStdString fromStorageGroup )
{
  XBMC->Log(LOG_DEBUG,"%s - Getting File via Myth Protocol - %s",
	    __FUNCTION__,filenameToGet.c_str());
  
  if (filenameToGet.Left(1).compare("/") != 0) 
  {
    filenameToGet = "/" + filenameToGet;
  }
  
  MythFile theFile;
  
  if (fromStorageGroup.CompareNoCase("channels")==0) 
  {
    CStdString chanFilename = "/channels" + filenameToGet;
    CStdString chanSG = "c";
    theFile=mythConP.ConnectPath((char*)chanFilename.c_str(),(char*)chanSG.c_str());
  }
  else 
  {
    theFile=mythConP.ConnectPath((char*)filenameToGet.c_str(),(char*)fromStorageGroup.c_str());
  }

  if (theFile.IsNull()) 
  {
    return "";
  }
  int theFilesLength = theFile.Duration();
  if (theFilesLength <= 0) 
  {
    return "";
  }
  
  CStdString writeFilePath = baseLocalCachepath + fromStorageGroup + filenameToGet;
  checkDirectory(writeFilePath,true);
  
  XFILE::CFile writeFile;
  if (writeFile.OpenForWrite(writeFilePath))
  {
    //char* theFileBuff = new char[theFilesLength];
    int totalRead = 0;
    while (totalRead < theFilesLength)
    {
      char* theFileTmpBuff = new char[theFilesLength];
      int readData = theFile.Read(theFileTmpBuff,theFilesLength-totalRead);
      if (readData <= 0)
      {
        break;
      }
      writeFile.Write((const void*)theFileTmpBuff,readData);
      /*char *filePntr = theFileBuff;
      if (totalRead > 0) {
        filePntr += (totalRead);
      }
      if (readData > (theFilesLength-totalRead)) {
        readData = (theFilesLength-totalRead);
      }
      memcpy((void*)filePntr,(void*)theFileTmpBuff,readData);
      */
      
      totalRead += readData;
    }
    writeFile.Close();
    if (totalRead < theFilesLength) 
    {
    XBMC->Log(LOG_DEBUG,"%s - Did not Read all data - %s - %d - %d",
	      __FUNCTION__,filenameToGet.c_str(),totalRead,theFilesLength);    
    }
    return writeFilePath;
  }
  else 
  {
    return "";
  }
  
}