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