1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "utility.h"
16
17 #include <errno.h>
18 #include <unistd.h>
19
20 #include <thread>
21
22 #include <android-base/logging.h>
23
24 using namespace std::literals;
25
26 namespace android {
27 namespace dm {
28
WaitForCondition(const std::function<WaitResult ()> & condition,const std::chrono::milliseconds & timeout_ms)29 bool WaitForCondition(const std::function<WaitResult()>& condition,
30 const std::chrono::milliseconds& timeout_ms) {
31 auto start_time = std::chrono::steady_clock::now();
32 while (true) {
33 auto result = condition();
34 if (result == WaitResult::Done) return true;
35 if (result == WaitResult::Fail) return false;
36
37 std::this_thread::sleep_for(20ms);
38
39 auto now = std::chrono::steady_clock::now();
40 auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
41 if (time_elapsed > timeout_ms) return false;
42 }
43 }
44
WaitForFile(const std::string & path,const std::chrono::milliseconds & timeout_ms)45 bool WaitForFile(const std::string& path, const std::chrono::milliseconds& timeout_ms) {
46 auto condition = [&]() -> WaitResult {
47 // If the file exists but returns EPERM or something, we consider the
48 // condition met.
49 if (access(path.c_str(), F_OK) != 0) {
50 if (errno == ENOENT) {
51 return WaitResult::Wait;
52 }
53 PLOG(ERROR) << "access failed: " << path;
54 return WaitResult::Fail;
55 }
56 return WaitResult::Done;
57 };
58 return WaitForCondition(condition, timeout_ms);
59 }
60
WaitForFileDeleted(const std::string & path,const std::chrono::milliseconds & timeout_ms)61 bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds& timeout_ms) {
62 auto condition = [&]() -> WaitResult {
63 if (access(path.c_str(), F_OK) == 0) {
64 return WaitResult::Wait;
65 }
66 if (errno != ENOENT) {
67 PLOG(ERROR) << "access failed: " << path;
68 return WaitResult::Fail;
69 }
70 return WaitResult::Done;
71 };
72 return WaitForCondition(condition, timeout_ms);
73 }
74
75 } // namespace dm
76 } // namespace android
77