comparison OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp @ 5737:2fe77dfe0466

rewrote FileSystemStorage::Create knowing that we should not check the return value of boost::file_system::create_directories and that it throws on errors we were detecting manually
author Alain Mazy <am@orthanc.team>
date Thu, 01 Aug 2024 19:44:48 +0200
parents 264d84c1936a
children
comparison
equal deleted inserted replaced
5736:264d84c1936a 5737:2fe77dfe0466
137 // Extremely unlikely case: This Uuid has already been created 137 // Extremely unlikely case: This Uuid has already been created
138 // in the past. 138 // in the past.
139 throw OrthancException(ErrorCode_InternalError, "This file UUID already exists"); 139 throw OrthancException(ErrorCode_InternalError, "This file UUID already exists");
140 } 140 }
141 141
142 // In very unlikely case (but we've seen it !), 2 threads might enter this same piece 142 // In very unlikely cases, a thread could be deleting a
143 // of code and both try to create the same directory or a thread could be deleting a
144 // directory while another thread needs it -> introduce 3 retries at 1 ms interval 143 // directory while another thread needs it -> introduce 3 retries at 1 ms interval
145 int retryCount = 0; 144 int retryCount = 0;
146 const int maxRetryCount = 3; 145 const int maxRetryCount = 3;
147 146
148 while (retryCount < maxRetryCount) 147 while (retryCount < maxRetryCount)
153 boost::this_thread::sleep(boost::posix_time::milliseconds(2 * retryCount + (rand() % 10))); 152 boost::this_thread::sleep(boost::posix_time::milliseconds(2 * retryCount + (rand() % 10)));
154 LOG(INFO) << "Retrying to create attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type) 153 LOG(INFO) << "Retrying to create attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type)
155 << "\" type"; 154 << "\" type";
156 } 155 }
157 156
158 if (boost::filesystem::exists(path.parent_path())) 157 try
159 { 158 {
160 if (!boost::filesystem::is_directory(path.parent_path())) 159 boost::filesystem::create_directories(path.parent_path()); // the function ensures that the directory exists or throws
160 }
161 catch (boost::filesystem::filesystem_error& er)
162 {
163 if (er.code() == boost::system::errc::file_exists // the last element of the parent_path is a file
164 || er.code() == boost::system::errc::not_a_directory) // one of the element of the parent_path is not a directory
161 { 165 {
162 throw OrthancException(ErrorCode_DirectoryOverFile); // no need to retry this error 166 throw OrthancException(ErrorCode_DirectoryOverFile, "One of the element of the path is a file"); // no need to retry this error
163 } 167 }
164 } 168
165 else 169 // ignore other errors and retry
166 {
167 if (!boost::filesystem::create_directories(path.parent_path()))
168 {
169 if (retryCount >= maxRetryCount)
170 {
171 throw OrthancException(ErrorCode_FileStorageCannotWrite);
172 }
173
174 continue; // retry
175 }
176 } 170 }
177 171
178 try 172 try
179 { 173 {
180 SystemToolbox::WriteFile(content, size, path.string(), fsyncOnWrite_); 174 SystemToolbox::WriteFile(content, size, path.string(), fsyncOnWrite_);