1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/*
* Copyright (C) 2011-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#pragma once
// FileNFS.h: interface for the CNFSFile class.
#include "IFile.h"
#include "URL.h"
#include "threads/CriticalSection.h"
#include <chrono>
#include <list>
#include <map>
struct nfs_stat_64;
class CNfsConnection : public CCriticalSection
{
public:
struct keepAliveStruct
{
std::string exportPath;
std::chrono::time_point<std::chrono::steady_clock> refreshTime;
};
typedef std::map<struct nfsfh *, struct keepAliveStruct> tFileKeepAliveMap;
struct contextTimeout
{
struct nfs_context *pContext;
std::chrono::time_point<std::chrono::steady_clock> lastAccessedTime;
};
typedef std::map<std::string, struct contextTimeout> tOpenContextMap;
CNfsConnection();
~CNfsConnection();
bool Connect(const CURL &url, std::string &relativePath);
struct nfs_context *GetNfsContext() {return m_pNfsContext;}
uint64_t GetMaxReadChunkSize() {return m_readChunkSize;}
uint64_t GetMaxWriteChunkSize() {return m_writeChunkSize;}
std::list<std::string> GetExportList(const CURL &url);
//this functions splits the url into the exportpath (feed to mount) and the rest of the path
//relative to the mounted export
bool splitUrlIntoExportAndPath(const CURL& url, std::string &exportPath, std::string &relativePath, std::list<std::string> &exportList);
bool splitUrlIntoExportAndPath(const CURL& url, std::string &exportPath, std::string &relativePath);
//special stat which uses its own context
//needed for getting intervolume symlinks to work
int stat(const CURL& url, nfs_stat_64* statbuff);
void AddActiveConnection();
void AddIdleConnection();
void CheckIfIdle();
void Deinit();
//adds the filehandle to the keep alive list or resets
//the timeout for this filehandle if already in list
void resetKeepAlive(const std::string& _exportPath, struct nfsfh* _pFileHandle);
//removes file handle from keep alive list
void removeFromKeepAliveList(struct nfsfh *_pFileHandle);
const std::string& GetConnectedIp() const {return m_resolvedHostName;}
const std::string& GetConnectedExport() const {return m_exportPath;}
const std::string GetContextMapId() const {return m_hostName + m_exportPath;}
private:
enum class ContextStatus
{
INVALID,
NEW,
CACHED
};
struct nfs_context *m_pNfsContext;//current nfs context
std::string m_exportPath;//current connected export path
std::string m_hostName;//current connected host
std::string m_resolvedHostName;//current connected host - as ip
uint64_t m_readChunkSize = 0;//current read chunksize of connected server
uint64_t m_writeChunkSize = 0;//current write chunksize of connected server
int m_OpenConnections = 0; //number of open connections
std::chrono::time_point<std::chrono::steady_clock> m_IdleTimeout;
tFileKeepAliveMap m_KeepAliveTimeouts;//mapping filehandles to its idle timeout
tOpenContextMap m_openContextMap;//unique map for tracking all open contexts
std::chrono::time_point<std::chrono::steady_clock>
m_lastAccessedTime; //last access time for m_pNfsContext
std::list<std::string> m_exportList;//list of exported paths of current connected servers
CCriticalSection keepAliveLock;
CCriticalSection openContextLock;
void clearMembers();
struct nfs_context *getContextFromMap(const std::string &exportname, bool forceCacheHit = false);
// get context for given export and add to open contexts map - sets m_pNfsContext (may return an already mounted cached context)
ContextStatus getContextForExport(const std::string& exportname);
void destroyOpenContexts();
void destroyContext(const std::string &exportName);
void resolveHost(const CURL &url);//resolve hostname by dnslookup
void keepAlive(const std::string& _exportPath, struct nfsfh* _pFileHandle);
static void setOptions(struct nfs_context* context);
};
extern CNfsConnection gNfsConnection;
namespace XFILE
{
class CNFSFile : public IFile
{
public:
CNFSFile();
~CNFSFile() override;
void Close() override;
int64_t Seek(int64_t iFilePosition, int iWhence = SEEK_SET) override;
ssize_t Read(void* lpBuf, size_t uiBufSize) override;
bool Open(const CURL& url) override;
bool Exists(const CURL& url) override;
int Stat(const CURL& url, struct __stat64* buffer) override;
int Stat(struct __stat64* buffer) override;
int64_t GetLength() override;
int64_t GetPosition() override;
ssize_t Write(const void* lpBuf, size_t uiBufSize) override;
int Truncate(int64_t iSize) override;
//implement iocontrol for seek_possible for preventing the stat in File class for
//getting this info ...
int IoControl(EIoControl request, void* param) override
{
return request == IOCTRL_SEEK_POSSIBLE ? 1 : -1;
}
int GetChunkSize() override {return static_cast<int>(gNfsConnection.GetMaxReadChunkSize());}
bool OpenForWrite(const CURL& url, bool bOverWrite = false) override;
bool Delete(const CURL& url) override;
bool Rename(const CURL& url, const CURL& urlnew) override;
protected:
CURL m_url;
bool IsValidFile(const std::string& strFileName);
int64_t m_fileSize = 0;
struct nfsfh *m_pFileHandle;
struct nfs_context *m_pNfsContext;//current nfs context
std::string m_exportPath;
};
}
|