OSDN Git Service

Bump version.
[mutilities/MUtilities.git] / src / DirLocker.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2019 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::next_rand_str())));
68                                         if(m_lockFile->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Unbuffered))
69                                         {
70                                                 if(m_lockFile->write(testData) >= testData.size())
71                                                 {
72                                                         if(m_lockFile->error() == QFile::NoError)
73                                                         {
74                                                                 okay = true;
75                                                                 break;
76                                                         }
77                                                 }
78                                                 m_lockFile->remove();
79                                         }
80                                 }
81                                 if(!okay)
82                                 {
83                                         throw DirLockException("Locking has failed!");
84                                 }
85                         }
86
87                         ~DirLock(void)
88                         {
89                                 bool okay = false;
90                                 if(!m_lockFile.isNull())
91                                 {
92                                         for(int i = 0; i < 16; i++)
93                                         {
94                                                 if(m_lockFile->remove() || (!m_lockFile->exists()))
95                                                 {
96                                                         okay = true;
97                                                         break;
98                                                 }
99                                                 OS::sleep_ms(125);
100                                         }
101                                 }
102                                 if(!okay)
103                                 {
104                                         qWarning("DirLock: The lock file could not be removed!");
105                                 }
106                         }
107
108                         inline const QString &getPath(void) const
109                         {
110                                 return m_dirPath;
111                         }
112
113                 private:
114                         static const char *const TEST_DATA;
115                         const QString m_dirPath;
116                         QScopedPointer<QFile> m_lockFile;
117                 };
118
119                 const char *const DirLock::TEST_DATA = "7QtDxPWotHGQYv1xHyQHFKjTB5u5VYKHE20NMDAgLRYoy16CZN7mEYijbjCJpORnoBbtHCzqyy1a6BLCMMiTUZpLzgjg4qnN505egUBqk3wMhPsYjFpkng9i37mWd1iF";
120         }
121 }