OSDN Git Service

Added the copy_file() function + some improvements to directory clean-up code.
[mutilities/MUtilities.git] / src / DirLocker.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
21
22 #pragma once
23
24 //MUtils
25 #include <MUtils/Global.h>
26
27 //StdLib
28 #include <stdexcept>
29
30 //Qt
31 #include <QString>
32 #include <QFile>
33
34 ///////////////////////////////////////////////////////////////////////////////
35 // Directory Locker
36 ///////////////////////////////////////////////////////////////////////////////
37
38 namespace MUtils
39 {
40         namespace Internal
41         {
42                 class DirLockException : public std::runtime_error
43                 {
44                 public:
45                         DirLockException(const char *const message)
46                         :
47                                 std::runtime_error(message)
48                         {
49                         }
50                 };
51
52                 class DirLock
53                 {
54                 public:
55                         DirLock(const QString dirPath)
56                         :
57                                 m_dirPath(dirPath)
58                         {
59                                 bool okay = false;
60                                 const QByteArray testData = QByteArray(TEST_DATA);
61                                 if(m_dirPath.isEmpty())
62                                 {
63                                         throw DirLockException("Path must not be empty!");
64                                 }
65                                 for(int i = 0; i < 32; i++)
66                                 {
67                                         m_lockFile.reset(new QFile(QString("%1/~%2.lck").arg(m_dirPath, MUtils::rand_str())));
68                                         if(m_lockFile->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Unbuffered))
69                                         {
70                                                 if(m_lockFile->write(testData) >= testData.size())
71                                                 {
72                                                         okay = true;
73                                                         break;
74                                                 }
75                                                 m_lockFile->remove();
76                                         }
77                                 }
78                                 if(!okay)
79                                 {
80                                         throw DirLockException("Locking has failed!");
81                                 }
82                         }
83
84                         ~DirLock(void)
85                         {
86                                 bool okay = false;
87                                 if(!m_lockFile.isNull())
88                                 {
89                                         for(int i = 0; i < 16; i++)
90                                         {
91                                                 if(m_lockFile->remove())
92                                                 {
93                                                         break;
94                                                 }
95                                                 OS::sleep_ms(125);
96                                         }
97                                         m_lockFile.reset(NULL);
98                                 }
99                                 for(int i = 0; i < 16; i++)
100                                 {
101                                         if(MUtils::remove_directory(m_dirPath, true))
102                                         {
103                                                 okay = true;
104                                                 break;
105                                         }
106                                         OS::sleep_ms(125);
107                                 }
108                                 if(!okay)
109                                 {
110                                         OS::system_message_wrn(L"Directory Lock", L"Warning: Not all temporary files could be removed!");
111                                 }
112                         }
113
114                         inline const QString &getPath(void) const
115                         {
116                                 return m_dirPath;
117                         }
118
119                 private:
120                         static const char *const TEST_DATA;
121                         const QString m_dirPath;
122                         QScopedPointer<QFile> m_lockFile;
123                 };
124
125                 const char *const DirLock::TEST_DATA = "7QtDxPWotHGQYv1xHyQHFKjTB5u5VYKHE20NMDAgLRYoy16CZN7mEYijbjCJpORnoBbtHCzqyy1a6BLCMMiTUZpLzgjg4qnN505egUBqk3wMhPsYjFpkng9i37mWd1iF";
126         }
127 }