1 // 2 // This file is part of the aMule Project. 3 // 4 // Copyright (c) 2008-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 5 // Copyright (c) 2008-2011 Stu Redman ( sturedman@amule.org ) 6 // 7 // Any parts of this program derived from the xMule, lMule or eMule project, 8 // or contributed by third-party developers are copyrighted by their 9 // respective authors. 10 // 11 // This program is free software; you can redistribute it and/or modify 12 // it under the terms of the GNU General Public License as published by 13 // the Free Software Foundation; either version 2 of the License, or 14 // (at your option) any later version. 15 // 16 // This program is distributed in the hope that it will be useful, 17 // but WITHOUT ANY WARRANTY; without even the implied warranty of 18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 // GNU General Public License for more details. 20 // 21 // You should have received a copy of the GNU General Public License 22 // along with this program; if not, write to the Free Software 23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24 // 25 26 #include "FileAutoClose.h" 27 #include "GetTickCount.h" // for TheTime 28 #include "Logger.h" // Needed for AddDebugLogLineN 29 30 31 static const uint32 ReleaseTime = 600; // close file after 10 minutes of not being used 32 33 CFileAutoClose::CFileAutoClose() 34 : m_mode(CFile::read), 35 m_autoClosed(false), 36 m_locked(0), 37 m_size(0), 38 m_lastAccess(TheTime) 39 {} 40 41 CFileAutoClose::CFileAutoClose(const CPath& path, CFile::OpenMode mode) 42 { 43 Open(path, mode); 44 } 45 46 bool CFileAutoClose::Open(const CPath& path, CFile::OpenMode mode) 47 { 48 m_mode = mode; 49 m_autoClosed = false; 50 m_locked = 0; 51 m_size = 0; 52 m_lastAccess = TheTime; 53 return m_file.Open(path, mode); 54 } 55 56 bool CFileAutoClose::Create(const CPath& path, bool overwrite) 57 { 58 m_mode = CFile::write; 59 m_autoClosed = false; 60 m_lastAccess = TheTime; 61 return m_file.Create(path, overwrite); 62 } 63 64 bool CFileAutoClose::Close() 65 { 66 bool state = m_autoClosed ? true : m_file.Close(); 67 m_autoClosed = false; 68 return state; 69 } 70 71 uint64 CFileAutoClose::GetLength() const 72 { 73 return m_autoClosed ? m_size : m_file.GetLength(); 74 } 75 76 bool CFileAutoClose::SetLength(uint64 newLength) 77 { 78 Reopen(); 79 return m_file.SetLength(newLength); 80 } GetBuffer()81 82 const CPath& CFileAutoClose::GetFilePath() const 83 { 84 return m_file.GetFilePath(); 85 } 86 87 bool CFileAutoClose::IsOpened() const 88 { 89 return m_autoClosed || m_file.IsOpened(); 90 } 91 92 void CFileAutoClose::ReadAt(void* buffer, uint64 offset, size_t count) 93 { 94 Reopen(); 95 m_file.Seek(offset); 96 m_file.Read(buffer, count); 97 } 98 99 void CFileAutoClose::WriteAt(const void* buffer, uint64 offset, size_t count) 100 { 101 Reopen(); 102 m_file.Seek(offset); 103 m_file.Write(buffer, count); 104 } 105 106 bool CFileAutoClose::Eof() 107 { 108 Reopen(); 109 return m_file.Eof(); 110 } 111 112 int CFileAutoClose::fd() 113 { 114 Reopen(); 115 m_locked++; 116 return m_file.fd(); 117 } 118 119 void CFileAutoClose::Unlock() 120 { 121 if (m_locked) { 122 m_locked--; 123 } 124 } 125 126 void CFileAutoClose::Reopen() 127 { 128 if (m_autoClosed) { 129 AddDebugLogLineN(logCFile, wxT("Reopen AutoClosed file ") + GetFilePath().GetPrintable()); 130 m_file.Reopen(m_mode); // throws on failure 131 // On open error m_autoClosed stays true, so if the app tries again 132 // it opens and throws again. 133 // Otherwise it would assert on an operation on a closed file and probably die. 134 m_autoClosed = false; 135 } 136 m_lastAccess = TheTime; 137 } 138 139 bool CFileAutoClose::Release(bool now) 140 { 141 if (!m_autoClosed 142 && (now || TheTime - m_lastAccess >= ReleaseTime) 143 && !m_locked 144 && m_file.IsOpened()) { 145 m_autoClosed = true; 146 m_size = m_file.GetLength(); 147 m_file.Close(); 148 AddDebugLogLineN(logCFile, wxT("AutoClosed file ") + GetFilePath().GetPrintable() 149 + (now ? wxT("(immediately)") : wxT("(timed)"))); 150 } 151 return m_autoClosed; 152 } 153 154 // File_checked_for_headers 155