已合并
lru增加锁,增加读写dfx #229
lru增加锁,增加读写dfx #229
已合并
ZhangRonan创建于 3月19日
6 个文件变更+47-25
@@ -83,13 +83,14 @@ bool AppDetailsRdbDataMgr::ExecWithTrans(TransCallback cb)
83}83}
84 84 
85bool AppDetailsRdbDataMgr::QueryDataByDomain(85bool AppDetailsRdbDataMgr::QueryDataByDomain(
86- const std::string& tableName, const std::string &domain, std::vector<AppDetailsRdbItem> &itemVec)86+ const std::string& tableName, const std::string& domain, std::vector<AppDetailsRdbItem>& itemVec)
87{87{
88 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call.");88 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call.");
89+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] QueryDataByDomain.");
89 NativeRdb::AbsRdbPredicates absRdbPred(tableName);90 NativeRdb::AbsRdbPredicates absRdbPred(tableName);
90 absRdbPred.EqualTo(DETAILS_DOMAIN, domain);91 absRdbPred.EqualTo(DETAILS_DOMAIN, domain);
91 std::vector<std::string> columns = {};92 std::vector<std::string> columns = {};
92- RdbForEachRetCb eachCb = [&itemVec](std::shared_ptr<AbsSharedResultSet> retSet)->bool {93+ RdbForEachRetCb eachCb = [&itemVec](std::shared_ptr<AbsSharedResultSet> retSet) -> bool {
93 AppDetailsRdbItem item;94 AppDetailsRdbItem item;
94 if (!item.GetRdbItem(retSet)) {95 if (!item.GetRdbItem(retSet)) {
95 return false;96 return false;
@@ -129,6 +130,7 @@ void AppDetailsRdbDataMgr::PostDelayCloseTask(int32_t delayTime)
129bool AppDetailsRdbDataMgr::InsertDataBatch(const std::string& tableName, std::vector<AppDetailsRdbItem>& infoVec)130bool AppDetailsRdbDataMgr::InsertDataBatch(const std::string& tableName, std::vector<AppDetailsRdbItem>& infoVec)
130{131{
131 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");132 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
133+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] InsertDataBatch.");
132 auto rdbStore = GetRdbStore();134 auto rdbStore = GetRdbStore();
133 if (!rdbStore) {135 if (!rdbStore) {
134 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");136 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
@@ -169,9 +171,10 @@ bool AppDetailsRdbDataMgr::CreateMetaData()
169 return true;171 return true;
170};172};
171 173 
172-bool AppDetailsRdbDataMgr::UpdateMetaData(std::vector<MetaItem> &itemVec)174+bool AppDetailsRdbDataMgr::UpdateMetaData(std::vector<MetaItem>& itemVec)
173{175{
174 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");176 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
177+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] UpdateMetaData.");
175 auto rdbStore = GetRdbStore();178 auto rdbStore = GetRdbStore();
176 if (!rdbStore) {179 if (!rdbStore) {
177 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");180 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
@@ -191,9 +194,10 @@ bool AppDetailsRdbDataMgr::UpdateMetaData(std::vector<MetaItem> &itemVec)
191 return true;194 return true;
192};195};
193 196 
194-bool AppDetailsRdbDataMgr::QueryMetaData(const std::string &tableName, MetaItem &info)197+bool AppDetailsRdbDataMgr::QueryMetaData(const std::string& tableName, MetaItem& info)
195{198{
196 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call.");199 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call.");
200+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] QueryMetaData.");
197 NativeRdb::AbsRdbPredicates absRdbPred(META_DATA);201 NativeRdb::AbsRdbPredicates absRdbPred(META_DATA);
198 absRdbPred.EqualTo(META_TABLE_NAME, tableName);202 absRdbPred.EqualTo(META_TABLE_NAME, tableName);
199 std::vector<std::string> columns = {};203 std::vector<std::string> columns = {};
@@ -203,7 +207,7 @@ bool AppDetailsRdbDataMgr::QueryMetaData(const std::string &tableName, MetaItem
203 return false;207 return false;
204 }208 }
205 std::vector<MetaItem> itemVec;209 std::vector<MetaItem> itemVec;
206- RdbForEachRetCb eachCb = [&itemVec](std::shared_ptr<AbsSharedResultSet> retSet)->bool {210+ RdbForEachRetCb eachCb = [&itemVec](std::shared_ptr<AbsSharedResultSet> retSet) -> bool {
207 MetaItem item;211 MetaItem item;
208 if (!item.GetRdbItem(retSet)) {212 if (!item.GetRdbItem(retSet)) {
209 return false;213 return false;
@@ -218,7 +222,7 @@ bool AppDetailsRdbDataMgr::QueryMetaData(const std::string &tableName, MetaItem
218 return false;222 return false;
219};223};
220 224 
221-bool AppDetailsRdbDataMgr::CreateTable(const std::string &tableName)225+bool AppDetailsRdbDataMgr::CreateTable(const std::string& tableName)
222{226{
223 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");227 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
224 std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName228 std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName
@@ -262,7 +266,7 @@ bool AppDetailsRdbDataMgr::CreateRegularIndex(const std::string& tableName, cons
262 return true;266 return true;
263};267};
264 268 
265-bool AppDetailsRdbDataMgr::DeleteTable(const std::string &tableName)269+bool AppDetailsRdbDataMgr::DeleteTable(const std::string& tableName)
266{270{
267 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "Called");271 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "Called");
268 std::string sql = "DROP TABLE IF EXISTS " + tableName + ";";272 std::string sql = "DROP TABLE IF EXISTS " + tableName + ";";
@@ -295,7 +299,7 @@ std::string AppDetailsRdbDataMgr::GetDbVersion()
295 return "";299 return "";
296};300};
297 301 
298-bool AppDetailsRdbDataMgr::RenameTable(const std::string &oldName, const std::string &newName)302+bool AppDetailsRdbDataMgr::RenameTable(const std::string& oldName, const std::string& newName)
299{303{
300 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");304 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
301 std::string sql = "ALTER TABLE " + oldName + " RENAME TO " + newName + ";";305 std::string sql = "ALTER TABLE " + oldName + " RENAME TO " + newName + ";";
@@ -349,6 +353,7 @@ bool AppDetailsRdbDataMgr::Query(const NativeRdb::AbsRdbPredicates& predicates,
349 const std::vector<std::string>& columns, RdbForEachRetCb cb)353 const std::vector<std::string>& columns, RdbForEachRetCb cb)
350{354{
351 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");355 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
356+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] Query.");
352 auto rdbStore = GetRdbStore();357 auto rdbStore = GetRdbStore();
353 if (!rdbStore) {358 if (!rdbStore) {
354 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdb store is null");359 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdb store is null");
@@ -359,10 +364,8 @@ bool AppDetailsRdbDataMgr::Query(const NativeRdb::AbsRdbPredicates& predicates,
359 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore query absSharedResultSet failed");364 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore query absSharedResultSet failed");
360 return false;365 return false;
361 }366 }
362- auto guard = std::unique_ptr<void, std::function<void(void*)>>(nullptr,367+ auto guard = std::unique_ptr<void, std::function<void(void*)>>(
363- [&](void*) {368+ nullptr, [&](void*) { absSharedResultSet->Close(); });
364- absSharedResultSet->Close();
365- });
366 if (!absSharedResultSet->HasBlock()) {369 if (!absSharedResultSet->HasBlock()) {
367 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "absSharedResultSet has no block");370 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "absSharedResultSet has no block");
368 return false;371 return false;
@@ -38,6 +38,7 @@ private:
38 std::atomic<size_t> maxCap_ = 10;38 std::atomic<size_t> maxCap_ = 10;
39 std::list<std::pair<K, V>> cache_;39 std::list<std::pair<K, V>> cache_;
40 std::unordered_map<K, typename std::list<std::pair<K, V>>::iterator> lruMap_;40 std::unordered_map<K, typename std::list<std::pair<K, V>>::iterator> lruMap_;
41+ std::mutex mutex_;
41};42};
42 43 
43template<typename K, typename V>44template<typename K, typename V>
@@ -49,6 +50,7 @@ bool LruCacheUtil<K, V>::SetMaxCap(size_t cap)
49template<typename K, typename V>50template<typename K, typename V>
50bool LruCacheUtil<K, V>::Get(const K& key, V& value)51bool LruCacheUtil<K, V>::Get(const K& key, V& value)
51{52{
53+ std::lock_guard<std::mutex> lock(mutex_);
52 if (lruMap_.find(key) == lruMap_.end()) {54 if (lruMap_.find(key) == lruMap_.end()) {
53 return false;55 return false;
54 }56 }
@@ -62,6 +64,7 @@ bool LruCacheUtil<K, V>::Get(const K& key, V& value)
62template<typename K, typename V>64template<typename K, typename V>
63void LruCacheUtil<K, V>::Put(const K& key, const V& value)65void LruCacheUtil<K, V>::Put(const K& key, const V& value)
64{66{
67+ std::lock_guard<std::mutex> lock(mutex_);
65 auto iter = lruMap_.find(key);68 auto iter = lruMap_.find(key);
66 if (iter != lruMap_.end()) {69 if (iter != lruMap_.end()) {
67 V val = lruMap_[key]->second;70 V val = lruMap_[key]->second;
@@ -82,6 +85,7 @@ void LruCacheUtil<K, V>::Put(const K& key, const V& value)
82template<typename K, typename V>85template<typename K, typename V>
83void LruCacheUtil<K, V>::Clear()86void LruCacheUtil<K, V>::Clear()
84{87{
88+ std::lock_guard<std::mutex> lock(mutex_);
85 cache_.clear();89 cache_.clear();
86 lruMap_.clear();90 lruMap_.clear();
87};91};
@@ -89,6 +93,7 @@ void LruCacheUtil<K, V>::Clear()
89template<typename K, typename V>93template<typename K, typename V>
90bool LruCacheUtil<K, V>::IsEmpty()94bool LruCacheUtil<K, V>::IsEmpty()
91{95{
96+ std::lock_guard<std::mutex> lock(mutex_);
92 return lruMap_.empty();97 return lruMap_.empty();
93};98};
94}99}
@@ -39,6 +39,8 @@ WhiteListConfigMgr::~WhiteListConfigMgr()
39}39}
40void WhiteListConfigMgr::LoadDefault()40void WhiteListConfigMgr::LoadDefault()
41{41{
42+ APP_DOMAIN_VERIFY_HILOGI(
43+ APP_DOMAIN_VERIFY_MODULE_COMMON, "[AppDomainVerifyIO] operation:read default whitelist");
42 preferences_ = GetPreference(DEFAULT_WHITE_LIST_PRE_PATH);44 preferences_ = GetPreference(DEFAULT_WHITE_LIST_PRE_PATH);
43 if (preferences_ == nullptr) {45 if (preferences_ == nullptr) {
44 UNIVERSAL_ERROR_EVENT(READ_DEFAULT_WHITE_LIST_FAULT);46 UNIVERSAL_ERROR_EVENT(READ_DEFAULT_WHITE_LIST_FAULT);
@@ -54,6 +56,8 @@ void WhiteListConfigMgr::LoadDefault()
54}56}
55void WhiteListConfigMgr::LoadDynamic()57void WhiteListConfigMgr::LoadDynamic()
56{58{
59+ APP_DOMAIN_VERIFY_HILOGI(
60+ APP_DOMAIN_VERIFY_MODULE_COMMON, "[AppDomainVerifyIO] operation:read dynamic whitelist");
57 preferences_ = GetPreference(DYNAMIC_WHITE_LIST_PRE_PATH);61 preferences_ = GetPreference(DYNAMIC_WHITE_LIST_PRE_PATH);
58 if (preferences_ == nullptr) {62 if (preferences_ == nullptr) {
59 UNIVERSAL_ERROR_EVENT(READ_DYNAMIC_WHITE_LIST_FAULT);63 UNIVERSAL_ERROR_EVENT(READ_DYNAMIC_WHITE_LIST_FAULT);
@@ -107,6 +111,8 @@ std::shared_ptr<NativePreferences::Preferences> WhiteListConfigMgr::GetPreferenc
107}111}
108bool WhiteListConfigMgr::Save()112bool WhiteListConfigMgr::Save()
109{113{
114+ APP_DOMAIN_VERIFY_HILOGI(
115+ APP_DOMAIN_VERIFY_MODULE_COMMON, "[AppDomainVerifyIO] operation:write dynamic whitelist");
110 APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MODULE_COMMON, "called");116 APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MODULE_COMMON, "called");
111 if (preferences_ == nullptr) {117 if (preferences_ == nullptr) {
112 APP_DOMAIN_VERIFY_HILOGW(APP_DOMAIN_VERIFY_MODULE_COMMON, "preferences null");118 APP_DOMAIN_VERIFY_HILOGW(APP_DOMAIN_VERIFY_MODULE_COMMON, "preferences null");
@@ -37,6 +37,7 @@ public:
37 AppDetailsDataMgr();37 AppDetailsDataMgr();
38 virtual ~AppDetailsDataMgr();38 virtual ~AppDetailsDataMgr();
39 int QueryAppDetailsWant(const std::string& url, AAFwk::Want& want, std::string& bundleName);39 int QueryAppDetailsWant(const std::string& url, AAFwk::Want& want, std::string& bundleName);
40+ 
40private:41private:
41 bool QueryAppDetailsWantByCache(const std::string& url, std::string& bundleName);42 bool QueryAppDetailsWantByCache(const std::string& url, std::string& bundleName);
42 bool QueryAppDetailsWantByRdb(const std::string& url, std::string& bundleName);43 bool QueryAppDetailsWantByRdb(const std::string& url, std::string& bundleName);
@@ -44,8 +45,9 @@ private:
44 std::shared_ptr<LruCacheUtil<std::string, std::string>> lruCache_;45 std::shared_ptr<LruCacheUtil<std::string, std::string>> lruCache_;
45 std::shared_ptr<AppDetailsRdbDataMgr> rdbMgr_;46 std::shared_ptr<AppDetailsRdbDataMgr> rdbMgr_;
46 std::shared_ptr<AppDetailsFilter> detailsFilter_;47 std::shared_ptr<AppDetailsFilter> detailsFilter_;
47- int64_t cacheBeginTime_ = 0;48+ int64_t cacheBeginTime_{0};
48- std::mutex agWantUrlMutex;49+ std::mutex cacheMutex_;
50+ std::mutex agWantUrlMutex_;
49 std::string agWantUrl_;51 std::string agWantUrl_;
50};52};
51} // namespace AppDomainVerify53} // namespace AppDomainVerify
@@ -41,7 +41,7 @@ AppDetailsDataMgr::AppDetailsDataMgr()
41 rdbMgr_ = std::make_shared<AppDetailsRdbDataMgr>(false);41 rdbMgr_ = std::make_shared<AppDetailsRdbDataMgr>(false);
42};42};
43 43 
44-AppDetailsDataMgr::~AppDetailsDataMgr(){};44+AppDetailsDataMgr::~AppDetailsDataMgr() {};
45 45 
46int AppDetailsDataMgr::QueryAppDetailsWant(const std::string& url, AAFwk::Want& want, std::string& bundleName)46int AppDetailsDataMgr::QueryAppDetailsWant(const std::string& url, AAFwk::Want& want, std::string& bundleName)
47{47{
@@ -68,15 +68,18 @@ bool AppDetailsDataMgr::QueryAppDetailsWantByCache(const std::string& url, std::
68{68{
69 int64_t currTime =69 int64_t currTime =
70 std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();70 std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();
71- if (currTime - cacheBeginTime_ > CACHE_TIME_S) {71+ {
72- cacheBeginTime_ = currTime;72+ std::lock_guard<std::mutex> lock(cacheMutex_);
73- lruCache_->Clear();73+ if (currTime - cacheBeginTime_ > CACHE_TIME_S) {
74- return false;74+ cacheBeginTime_ = currTime;
75- }75+ lruCache_->Clear();
76- std::string value;76+ return false;
77- if (lruCache_->Get(url, value)) {77+ }
78- bundleName = value;78+ std::string value;
79- return true;79+ if (lruCache_->Get(url, value)) {
80+ bundleName = value;
81+ return true;
82+ }
80 }83 }
81 return false;84 return false;
82};85};
@@ -118,7 +121,7 @@ bool AppDetailsDataMgr::QueryAppDetailsWantByRdb(const std::string& url, std::st
118void AppDetailsDataMgr::AddInfoToWant(AAFwk::Want& want, const std::string& bundleName)121void AppDetailsDataMgr::AddInfoToWant(AAFwk::Want& want, const std::string& bundleName)
119{122{
120 {123 {
121- std::lock_guard<std::mutex> lock(agWantUrlMutex);124+ std::lock_guard<std::mutex> lock(agWantUrlMutex_);
122 if (agWantUrl_.empty()) {125 if (agWantUrl_.empty()) {
123 MetaItem info;126 MetaItem info;
124 rdbMgr_->QueryMetaData(APP_DETAILS_TABLE, info);127 rdbMgr_->QueryMetaData(APP_DETAILS_TABLE, info);
@@ -64,6 +64,7 @@ AppDomainVerifyRdbDataManager::~AppDomainVerifyRdbDataManager()
64bool AppDomainVerifyRdbDataManager::InsertData(const RdbDataItem& rdbDataItem)64bool AppDomainVerifyRdbDataManager::InsertData(const RdbDataItem& rdbDataItem)
65{65{
66 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");66 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
67+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] InsertData.");
67 auto rdbStore = GetRdbStore();68 auto rdbStore = GetRdbStore();
68 if (!CheckRdbStoreExist(rdbStore)) {69 if (!CheckRdbStoreExist(rdbStore)) {
69 return false;70 return false;
@@ -108,6 +109,7 @@ bool AppDomainVerifyRdbDataManager::Query(const NativeRdb::AbsRdbPredicates& pre
108 if (!CheckRdbStoreExist(rdbStore)) {109 if (!CheckRdbStoreExist(rdbStore)) {
109 return false;110 return false;
110 }111 }
112+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] Query.");
111 auto absSharedResultSet = rdbStore->Query(predicates, columns);113 auto absSharedResultSet = rdbStore->Query(predicates, columns);
112 if (absSharedResultSet == nullptr) {114 if (absSharedResultSet == nullptr) {
113 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore query absSharedResultSet failed");115 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore query absSharedResultSet failed");
@@ -142,6 +144,7 @@ bool AppDomainVerifyRdbDataManager::Query(const NativeRdb::AbsRdbPredicates& pre
142bool AppDomainVerifyRdbDataManager::DeleteData(const std::string& bundleName)144bool AppDomainVerifyRdbDataManager::DeleteData(const std::string& bundleName)
143{145{
144 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");146 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
147+ APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "[AppDomainVerifyIO] DeleteData.");
145 auto rdbStore = GetRdbStore();148 auto rdbStore = GetRdbStore();
146 if (!CheckRdbStoreExist(rdbStore)) {149 if (!CheckRdbStoreExist(rdbStore)) {
147 return false;150 return false;