* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WRITE_CONTROLLER_H
#define WRITE_CONTROLLER_H
#include <list>
#include <mutex>
#include <sys/time.h>
#include <unordered_map>
namespace OHOS {
namespace HiviewDFX {
static constexpr uint64_t INVALID_TIME_STAMP = 0;
static constexpr size_t DEFAULT_CACHE_CAPACITY = 30;
static constexpr size_t HISYSEVENT_DEFAULT_PERIOD = 5;
static constexpr size_t HISYSEVENT_DEFAULT_THRESHOLD = 100;
using ControlParam = struct {
size_t period;
size_t threshold;
};
using CallerInfo = struct {
const char* func;
int64_t line;
uint64_t timeStamp;
};
template<typename K, typename V, size_t capacity = DEFAULT_CACHE_CAPACITY>
class LruCache {
public:
V Get(K key)
{
V v;
if (key2Index.count(key) == 0) {
return v;
}
Modify(key);
return key2Index[key].value;
}
void Put(K key, V value)
{
if (key2Index.count(key) > 0) {
key2Index[key].value = value;
Modify(key);
return;
}
if (keyCache.size() == capacity) {
key2Index.erase(keyCache.back());
keyCache.pop_back();
}
keyCache.push_front(key);
key2Index[key] = {
.iter = keyCache.cbegin(),
.value = value
};
}
private:
template<typename K_, typename V_>
struct CacheNode {
typename std::list<K_>::const_iterator iter;
V_ value;
};
private:
void Modify(K key)
{
keyCache.splice(keyCache.begin(), keyCache, key2Index[key].iter);
key2Index[key].iter = keyCache.cbegin();
}
private:
std::unordered_map<K, CacheNode<K, V>> key2Index;
std::list<K> keyCache;
};
class WriteController {
public:
uint64_t GetCurrentTimeMills();
uint64_t CheckLimitWritingEvent(const ControlParam& param, const char* domain, const char* eventName,
const CallerInfo& callerInfo);
uint64_t CheckLimitWritingEvent(const ControlParam& param, const char* domain, const char* eventName,
const char* func, int64_t line);
private:
struct EventLimitStat {
size_t count;
uint64_t begin;
public:
EventLimitStat()
{
count = 0;
begin = INVALID_TIME_STAMP;
}
public:
bool IsValid()
{
return count > 0;
}
};
private:
uint64_t ConcatenateInfoAsKey(const char* eventName, const char* func, int64_t line) const;
private:
std::mutex lmtMutex;
LruCache<uint64_t, EventLimitStat> lruCache;
};
}
}
#endif