未验证 提交 ad4a1c38 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

Merge pull request #23 from longdafeng/issue22

fixed 22, reimplement b+ tree
---
Language: Cpp
# BasedOnStyle: LLVM
SortIncludes: false
AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
DerivePointerAlignment: false
PointerAlignment: Right
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 120
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerBinding: true
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 200
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
PointerBindsToType: true
Cpp11BracedListStyle: true
Standard: Auto
IndentWidth: 2
TabWidth: 4
UseTab: Never
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
IndentFunctionDeclarationAfterType: true
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterControlStatementKeyword: true
SpaceBeforeAssignmentOperators: true
SpacesBeforeTrailingComments: 2
ContinuationIndentWidth: 4
CommentPragmas: '^lint'
MacroBlockBegin: "
END_CATCH_ERROR$"
...
./deps/libevent/*
./deps/googletest/*
./deps/jsoncpp/*
build/*
cmake-build-*/*
.vscode/*
.DS_Store
.idea
compile_commands.json
./.name
./miniob.iml
./vcs.xml
./workspace.xml
./modules.xml
......@@ -226,6 +226,9 @@ char *hex_to_bin(const char *s, char *bin_buff, int *dest_len) {
}
bool is_blank(const char *s) {
if (s == nullptr) {
return true;
}
while (*s != '\0') {
if (!isspace(*s)) {
return false;
......
......@@ -162,6 +162,11 @@ class LoggerFactory {
extern Log *g_log;
#ifndef __FILE_NAME__
#define __FILE_NAME__ (strrchr(__FILE__,'/')?strrchr(__FILE__,'/')+1:__FILE__)
#endif
#define LOG_HEAD(prefix, level) \
if (common::g_log) { \
time_t now_time; \
......@@ -175,17 +180,17 @@ extern Log *g_log;
common::g_log->rotate(p->tm_year + 1900, p->tm_mon + 1, p->tm_mday); \
} \
snprintf(prefix, sizeof(prefix), "[%s %s %s %s %u]>>", sz_head, \
(common::g_log)->prefix_msg(level), __FILE__, \
(common::g_log)->prefix_msg(level), __FILE_NAME__, \
__FUNCTION__, (u32_t)__LINE__); \
}
#define LOG_OUTPUT(level, fmt, ...) \
do { \
using namespace common; \
if (g_log && g_log->check_output(level, __FILE__)) { \
if (g_log && g_log->check_output(level, __FILE_NAME__)) { \
char prefix[ONE_KILO] = {0}; \
LOG_HEAD(prefix, level); \
g_log->output(level, __FILE__, prefix, fmt, ##__VA_ARGS__); \
g_log->output(level, __FILE_NAME__, prefix, fmt, ##__VA_ARGS__); \
} \
} while (0)
......
/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Longda on 2022/1/28.
//
#include "common/mm/mem_pool.h"
namespace common {
int MemPoolItem::init(int item_size, bool dynamic, int pool_num, int item_num_per_pool)
{
if (pools.empty() == false) {
LOG_WARN("Memory pool has been initialized, but still begin to be initialized, this->name:%s.", this->name.c_str());
return 0;
}
if (item_size <= 0 || pool_num <= 0 || item_num_per_pool <= 0) {
LOG_ERROR("Invalid arguments, item_size:%d, pool_num:%d, item_num_per_pool:%d, this->name:%s.",
item_size,
pool_num,
item_num_per_pool,
this->name.c_str());
return -1;
}
this->item_size = item_size;
this->item_num_per_pool = item_num_per_pool;
// in order to init memory pool, enable dynamic here
this->dynamic = true;
for (int i = 0; i < pool_num; i++) {
if (extend() < 0) {
cleanup();
return -1;
}
}
this->dynamic = dynamic;
LOG_INFO("Extend one pool, this->size:%d, item_size:%d, item_num_per_pool:%d, this->name:%s.",
this->size,
item_size,
item_num_per_pool,
this->name.c_str());
return 0;
}
void MemPoolItem::cleanup()
{
if (pools.empty() == true) {
LOG_WARN("Begin to do cleanup, but there is no memory pool, this->name:%s!", this->name.c_str());
return;
}
MUTEX_LOCK(&this->mutex);
used.clear();
frees.clear();
this->size = 0;
for (std::list<void *>::iterator iter = pools.begin(); iter != pools.end(); iter++) {
void *pool = *iter;
::free(pool);
}
pools.clear();
MUTEX_UNLOCK(&this->mutex);
LOG_INFO("Successfully do cleanup, this->name:%s.", this->name.c_str());
}
int MemPoolItem::extend()
{
if (this->dynamic == false) {
LOG_ERROR("Disable dynamic extend memory pool, but begin to extend, this->name:%s", this->name.c_str());
return -1;
}
MUTEX_LOCK(&this->mutex);
void *pool = malloc(item_num_per_pool * item_size);
if (pool == nullptr) {
MUTEX_UNLOCK(&this->mutex);
LOG_ERROR("Failed to extend memory pool, this->size:%d, item_num_per_pool:%d, this->name:%s.",
this->size,
item_num_per_pool,
this->name.c_str());
return -1;
}
pools.push_back(pool);
this->size += item_num_per_pool;
for (int i = 0; i < item_num_per_pool; i++) {
char *item = (char *)pool + i * item_size;
frees.push_back((void *)item);
}
MUTEX_UNLOCK(&this->mutex);
LOG_INFO("Extend one pool, this->size:%d, item_size:%d, item_num_per_pool:%d, this->name:%s.",
this->size,
item_size,
item_num_per_pool,
this->name.c_str());
return 0;
}
void *MemPoolItem::alloc()
{
MUTEX_LOCK(&this->mutex);
if (frees.empty() == true) {
if (this->dynamic == false) {
MUTEX_UNLOCK(&this->mutex);
return nullptr;
}
if (extend() < 0) {
MUTEX_UNLOCK(&this->mutex);
return nullptr;
}
}
void *buffer = frees.front();
frees.pop_front();
used.insert(buffer);
MUTEX_UNLOCK(&this->mutex);
memset(buffer, 0, sizeof(item_size));
return buffer;
}
void MemPoolItem::free(void *buf)
{
MUTEX_LOCK(&this->mutex);
size_t num = used.erase(buf);
if (num == 0) {
MUTEX_UNLOCK(&this->mutex);
LOG_WARN("No entry of %p in %s.", buf, this->name.c_str());
return;
}
frees.push_back(buf);
MUTEX_UNLOCK(&this->mutex);
return; // TODO for test
}
} // namespace common
\ No newline at end of file
/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Longda on 2010
//
#ifndef __COMMON_MM_MPOOL_H__
#define __COMMON_MM_MPOOL_H__
#include <queue>
#include <list>
#include <set>
#include <string>
#include <sstream>
#include "common/lang/mutex.h"
#include "common/log/log.h"
#include "common/os/os.h"
namespace common {
#define DEFAULT_ITEM_NUM_PER_POOL 128
#define DEFAULT_POOL_NUM 1
typedef bool (*match)(void *item, void *input_arg);
template <class T>
class MemPool {
public:
MemPool(const char *tag) : name(tag)
{
this->size = 0;
pthread_mutexattr_t mutexatr;
pthread_mutexattr_init(&mutexatr);
pthread_mutexattr_settype(&mutexatr, PTHREAD_MUTEX_RECURSIVE);
MUTEX_INIT(&mutex, &mutexatr);
}
virtual ~MemPool()
{
MUTEX_DESTROY(&mutex);
}
/**
* init memory pool, the major job is to alloc memory for memory pool
* @param pool_num, memory pool's number
* @param item_num_per_pool, how many items per pool.
* @return
*/
virtual int init(
bool dynamic = true, int pool_num = DEFAULT_POOL_NUM, int item_num_per_pool = DEFAULT_ITEM_NUM_PER_POOL) = 0;
/**
* Do cleanup job for memory pool
*/
virtual void cleanup() = 0;
/**
* If dynamic has been set, extend current memory pool,
*/
virtual int extend() = 0;
/**
* Alloc one frame from memory Pool
* @return
*/
virtual T *alloc() = 0;
/**
* Free one item, the resouce will return to memory Pool
* @param item
*/
virtual void free(T *item) = 0;
/**
* Find first used item which match the function of "func"
* @return
*/
virtual T *find(match func, void *arg) = 0;
/**
* Find used item which match the function of "func"
*/
virtual std::list<T *> find_all(match func, void *arg) = 0;
/**
* Mark the item has been changed;
*/
virtual void mark_modified(T *item) = 0;
/**
* Print the MemPool status
* @return
*/
virtual std::string to_string() = 0;
const std::string get_name() const
{
return name;
}
bool is_dynamic() const
{
return dynamic;
}
int get_size() const
{
return size;
}
protected:
pthread_mutex_t mutex;
int size;
bool dynamic;
std::string name;
};
/**
* MemoryPoolSimple is a simple Memory Pool manager,
*/
template <class T>
class MemPoolSimple : public MemPool<T> {
public:
MemPoolSimple(const char *tag) : MemPool<T>(tag)
{}
virtual ~MemPoolSimple()
{
cleanup();
}
/**
* init memory pool, the major job is to alloc memory for memory pool
* @param pool_num, memory pool's number
* @param item_num_per_pool, how many items per pool.
* @return
*/
int init(bool dynamic = true, int pool_num = DEFAULT_POOL_NUM, int item_num_per_pool = DEFAULT_ITEM_NUM_PER_POOL);
/**
* Do cleanup job for memory pool
*/
void cleanup();
/**
* If dynamic has been set, extend current memory pool,
*/
int extend();
/**
* Alloc one frame from memory Pool
* @return
*/
T *alloc();
/**
* Free one item, the resouce will return to memory Pool
* @param item
*/
void free(T *item);
/**
* Find first used item which match the function of "func"
* @return
*/
T *find(match func, void *arg);
/**
* Find used item which match the function of "func"
*/
std::list<T *> find_all(match func, void *arg);
/**
* Mark the item has been changed;
*/
void mark_modified(T *item);
/**
* Print the MemPool status
* @return
*/
std::string to_string();
int get_item_num_per_pool() const
{
return item_num_per_pool;
}
int get_used_num()
{
MUTEX_LOCK(&this->mutex);
auto num = used.size();
MUTEX_UNLOCK(&this->mutex);
return num;
}
protected:
std::list<T *> pools;
std::list<T *> lru_used;
std::set<T *> used;
std::list<T *> frees;
int item_num_per_pool;
};
template <class T>
int MemPoolSimple<T>::init(bool dynamic, int pool_num, int item_num_per_pool)
{
if (pools.empty() == false) {
LOG_WARN("Memory pool has been initialized, but still begin to be initialized, this->name:%s.", this->name.c_str());
return 0;
}
if (pool_num <= 0 || item_num_per_pool <= 0) {
LOG_ERROR("Invalid arguments, pool_num:%d, item_num_per_pool:%d, this->name:%s.",
pool_num,
item_num_per_pool,
this->name.c_str());
return -1;
}
this->item_num_per_pool = item_num_per_pool;
// in order to init memory pool, enable dynamic here
this->dynamic = true;
for (int i = 0; i < pool_num; i++) {
if (extend() < 0) {
cleanup();
return -1;
}
}
this->dynamic = dynamic;
LOG_INFO("Extend one pool, this->size:%d, item_num_per_pool:%d, this->name:%s.",
this->size,
item_num_per_pool,
this->name.c_str());
return 0;
}
template <class T>
void MemPoolSimple<T>::cleanup()
{
if (pools.empty() == true) {
LOG_WARN("Begin to do cleanup, but there is no memory pool, this->name:%s!", this->name.c_str());
return;
}
MUTEX_LOCK(&this->mutex);
lru_used.clear();
used.clear();
frees.clear();
this->size = 0;
for (typename std::list<T *>::iterator iter = pools.begin(); iter != pools.end(); iter++) {
T *pool = *iter;
delete[] pool;
}
pools.clear();
MUTEX_UNLOCK(&this->mutex);
LOG_INFO("Successfully do cleanup, this->name:%s.", this->name.c_str());
}
template <class T>
int MemPoolSimple<T>::extend()
{
if (this->dynamic == false) {
LOG_ERROR("Disable dynamic extend memory pool, but begin to extend, this->name:%s", this->name.c_str());
return -1;
}
MUTEX_LOCK(&this->mutex);
T *pool = new T[item_num_per_pool];
if (pool == nullptr) {
MUTEX_UNLOCK(&this->mutex);
LOG_ERROR("Failed to extend memory pool, this->size:%d, item_num_per_pool:%d, this->name:%s.",
this->size,
item_num_per_pool,
this->name.c_str());
return -1;
}
pools.push_back(pool);
this->size += item_num_per_pool;
for (int i = 0; i < item_num_per_pool; i++) {
frees.push_back(pool + i);
}
MUTEX_UNLOCK(&this->mutex);
LOG_INFO("Extend one pool, this->size:%d, item_num_per_pool:%d, this->name:%s.",
this->size,
item_num_per_pool,
this->name.c_str());
return 0;
}
template <class T>
T *MemPoolSimple<T>::alloc()
{
MUTEX_LOCK(&this->mutex);
if (frees.empty() == true) {
if (this->dynamic == false) {
MUTEX_UNLOCK(&this->mutex);
return nullptr;
}
if (extend() < 0) {
MUTEX_UNLOCK(&this->mutex);
return nullptr;
}
}
T *buffer = frees.front();
frees.pop_front();
used.insert(buffer);
lru_used.push_back(buffer);
MUTEX_UNLOCK(&this->mutex);
return buffer;
}
template <class T>
void MemPoolSimple<T>::free(T *buf)
{
MUTEX_LOCK(&this->mutex);
size_t num = used.erase(buf);
if (num == 0) {
MUTEX_UNLOCK(&this->mutex);
LOG_WARN("No entry of %p in %s.", buf, this->name.c_str());
print_stacktrace();
return;
}
lru_used.remove(buf);
frees.push_back(buf);
MUTEX_UNLOCK(&this->mutex);
return; // TODO for test
}
template <class T>
T *MemPoolSimple<T>::find(match func, void *arg)
{
T *buffer = nullptr;
MUTEX_LOCK(&this->mutex);
for (typename std::list<T *>::iterator it = lru_used.begin(); it != lru_used.end(); ++it) {
T *item = *it;
if ((*func)(item, arg) == false) {
continue;
}
buffer = item;
break;
}
MUTEX_UNLOCK(&this->mutex);
return buffer;
}
template <class T>
std::list<T *> MemPoolSimple<T>::find_all(match func, void *arg)
{
std::list<T *> ret;
MUTEX_LOCK(&this->mutex);
for (typename std::list<T *>::iterator it = lru_used.begin(); it != lru_used.end(); ++it) {
T *item = *it;
if ((*func)(item, arg) == false) {
continue;
}
ret.push_back(item);
}
MUTEX_UNLOCK(&this->mutex);
return ret;
}
template <class T>
void MemPoolSimple<T>::mark_modified(T *buf)
{
MUTEX_LOCK(&this->mutex);
if (used.find(buf) == used.end()) {
MUTEX_UNLOCK(&this->mutex);
LOG_WARN("No entry of %p in %s.", buf, this->name.c_str());
return;
}
lru_used.remove(buf);
lru_used.push_back(buf);
MUTEX_UNLOCK(&this->mutex);
return;
}
template <class T>
std::string MemPoolSimple<T>::to_string()
{
std::stringstream ss;
ss << "name:" << this->name << ","
<< "dyanmic:" << this->dynamic << ","
<< "size:" << this->size << ","
<< "pool_size:" << this->pools.size() << ","
<< "used_size:" << this->used.size() << ","
<< "free_size:" << this->frees.size();
return ss.str();
}
class MemPoolItem {
public:
MemPoolItem(const char *tag) : name(tag)
{
this->size = 0;
pthread_mutexattr_t mutexatr;
pthread_mutexattr_init(&mutexatr);
pthread_mutexattr_settype(&mutexatr, PTHREAD_MUTEX_RECURSIVE);
MUTEX_INIT(&mutex, &mutexatr);
}
virtual ~MemPoolItem()
{
cleanup();
MUTEX_DESTROY(&mutex);
}
/**
* init memory pool, the major job is to alloc memory for memory pool
* @param pool_num, memory pool's number
* @param item_num_per_pool, how many items per pool.
* @return
*/
int init(int item_size, bool dynamic = true, int pool_num = DEFAULT_POOL_NUM,
int item_num_per_pool = DEFAULT_ITEM_NUM_PER_POOL);
/**
* Do cleanup job for memory pool
*/
void cleanup();
/**
* If dynamic has been set, extend current memory pool,
*/
int extend();
/**
* Alloc one frame from memory Pool
* @return
*/
void *alloc();
/**
* Free one item, the resouce will return to memory Pool
* @param item
*/
void free(void *item);
/**
* Check whether this item has been used before.
* @param item
* @return
*/
bool is_used(void *item)
{
MUTEX_LOCK(&mutex);
auto it = used.find(item);
MUTEX_UNLOCK(&mutex);
return it != used.end();
}
std::string to_string()
{
std::stringstream ss;
ss << "name:" << this->name << ","
<< "dyanmic:" << this->dynamic << ","
<< "size:" << this->size << ","
<< "pool_size:" << this->pools.size() << ","
<< "used_size:" << this->used.size() << ","
<< "free_size:" << this->frees.size();
return ss.str();
}
const std::string get_name() const
{
return name;
}
bool is_dynamic() const
{
return dynamic;
}
int get_size() const
{
return size;
}
int get_item_size() const
{
return item_size;
}
int get_item_num_per_pool() const
{
return item_num_per_pool;
}
int get_used_num()
{
MUTEX_LOCK(&mutex);
auto num = used.size();
MUTEX_UNLOCK(&mutex);
return num;
}
protected:
pthread_mutex_t mutex;
std::string name;
bool dynamic;
int size;
int item_size;
int item_num_per_pool;
std::list<void *> pools;
std::set<void *> used;
std::list<void *> frees;
};
} // namespace common
#endif /* __COMMON_MM_MPOOL_H__ */
/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Longda on 2010
//
#ifndef __COMMON_MM_MPOOL_H__
#define __COMMON_MM_MPOOL_H__
#include <queue>
#include "common/lang/mutex.h"
#include "common/log/log.h"
namespace common {
#define CLMPOOL_DEFAULT_ADDSIZE 16
template<class T>
class MemPool {
public:
MemPool() : mQueue(), mAddSize(CLMPOOL_DEFAULT_ADDSIZE) {
MUTEX_INIT(&mLock, NULL);
}
~MemPool() {
MUTEX_LOCK(&mLock);
while (mQueue.empty() == false) {
T *item = mQueue.front();
mQueue.pop();
delete item;
}
MUTEX_UNLOCK(&mLock);
MUTEX_DESTROY(&mLock);
}
int add(int addSize) {
int ret = 0;
MUTEX_LOCK(&mLock);
for (int i = 0; i < addSize; i++) {
T *item = new T();
if (item == NULL) {
ret = -1;
break;
}
mQueue.push(item);
}
MUTEX_UNLOCK(&mLock);
return ret;
}
int init(int initSize) { return add(initSize); }
T *get() {
T *ret = NULL;
MUTEX_LOCK(&mLock);
if (mQueue.empty() == true) {
add(mAddSize);
}
if (mQueue.empty() == false) {
ret = mQueue.front();
mQueue.pop();
}
MUTEX_UNLOCK(&mLock);
return ret;
}
void put(T *item) {
MUTEX_LOCK(&mLock);
mQueue.push(item);
MUTEX_UNLOCK(&mLock);
}
private:
std::queue<T *> mQueue;
pthread_mutex_t mLock;
int mAddSize;
};
} //namespace common
#endif /* __COMMON_MM_MPOOL_H__ */
......@@ -13,9 +13,11 @@ See the Mulan PSL v2 for more details. */
//
#include <thread>
#include <execinfo.h>
#include "common/defs.h"
#include "common/os/os.h"
#include "common/log/log.h"
namespace common {
// Don't care windows
......@@ -23,4 +25,19 @@ u32_t getCpuNum() {
return std::thread::hardware_concurrency();
}
#define MAX_STACK_SIZE 32
void print_stacktrace()
{
int size = MAX_STACK_SIZE;
void * array[MAX_STACK_SIZE];
int stack_num = backtrace(array, size);
char ** stacktrace = backtrace_symbols(array, stack_num);
for (int i = 0; i < stack_num; ++i)
{
LOG_INFO("%d ----- %s\n", i, stacktrace[i]);
}
free(stacktrace);
}
}//namespace common
\ No newline at end of file
......@@ -18,5 +18,7 @@ namespace common {
u32_t getCpuNum();
void print_stacktrace();
} //namespace common
#endif /* __COMMON_OS_OS_H__ */
......@@ -23,7 +23,8 @@ See the Mulan PSL v2 for more details. */
#include "common/log/log.h"
namespace common {
std::string getFileName(const std::string &fullPath) {
std::string getFileName(const std::string &fullPath)
{
std::string szRt;
size_t pos;
try {
......@@ -36,12 +37,12 @@ std::string getFileName(const std::string &fullPath) {
szRt = "";
}
} catch (...) {
}
} catch (...) {}
return szRt;
}
void getFileName(const char *path, std::string &fileName) {
void getFileName(const char *path, std::string &fileName)
{
// Don't care the last character as FILE_PATH_SPLIT
const char *endPos = strrchr(path, FILE_PATH_SPLIT);
if (endPos == NULL) {
......@@ -58,7 +59,8 @@ void getFileName(const char *path, std::string &fileName) {
return;
}
std::string getDirName(const std::string &fullPath) {
std::string getDirName(const std::string &fullPath)
{
std::string szRt;
size_t pos;
try {
......@@ -72,11 +74,11 @@ std::string getDirName(const std::string &fullPath) {
szRt = FILE_PATH_SPLIT_STR;
}
} catch (...) {
}
} catch (...) {}
return szRt;
}
void getDirName(const char *path, std::string &parent) {
void getDirName(const char *path, std::string &parent)
{
// Don't care the last character as FILE_PATH_SPLIT
const char *endPos = strrchr(path, FILE_PATH_SPLIT);
if (endPos == NULL) {
......@@ -93,7 +95,8 @@ void getDirName(const char *path, std::string &parent) {
return;
}
std::string getFilePath(const std::string &fullPath) {
std::string getFilePath(const std::string &fullPath)
{
std::string szRt;
size_t pos;
try {
......@@ -106,57 +109,56 @@ std::string getFilePath(const std::string &fullPath) {
szRt = "";
}
} catch (...) {
}
} catch (...) {}
return szRt;
}
std::string getAboslutPath(const char *path) {
std::string getAboslutPath(const char *path)
{
std::string aPath(path);
if (path[0] != '/') {
const int MAX_SIZE = 256;
char current_absolute_path[MAX_SIZE];
if (NULL == getcwd(current_absolute_path, MAX_SIZE)) {
}
if (NULL == getcwd(current_absolute_path, MAX_SIZE)) {}
}
return aPath;
}
bool is_directory(const char *path) {
bool is_directory(const char *path)
{
struct stat st;
return (0 == stat(path, &st)) && (st.st_mode & S_IFDIR);
}
bool check_directory(std::string &path) {
while (!path.empty() && path.back() == '/')
path.erase(path.size() - 1, 1);
bool check_directory(std::string &path)
{
while (!path.empty() && path.back() == '/')
path.erase(path.size() - 1, 1);
int len = path.size();
if (0 == mkdir(path.c_str(), 0777) || is_directory(path.c_str()) )
if (0 == mkdir(path.c_str(), 0777) || is_directory(path.c_str()))
return true;
bool sep_state = false;
for (int i = 0; i < len; i++)
{
if (path[i] != '/')
{
bool sep_state = false;
for (int i = 0; i < len; i++) {
if (path[i] != '/') {
if (sep_state)
sep_state = false;
continue;
}
if (sep_state)
continue;
if (sep_state)
continue;
path[i] = '\0';
if (0 != mkdir(path.c_str(), 0777) && !is_directory(path.c_str()))
return false;
path[i] = '/';
sep_state = true;
sep_state = true;
}
if (0 != mkdir(path.c_str(), 0777) && !is_directory(path.c_str()))
......@@ -164,55 +166,49 @@ bool check_directory(std::string &path) {
return true;
}
int list_file(const char *path, const char *filter_pattern, std::vector<std::string> &files) {
regex_t reg;
if (filter_pattern)
{
const int res = regcomp(&reg, filter_pattern, REG_NOSUB);
if (res)
{
char errbuf[256];
regerror(res, &reg, errbuf, sizeof(errbuf));
LOG_ERROR("regcomp return error. filter pattern %s. errmsg %d:%s",
filter_pattern, res, errbuf);
return -1;
}
}
DIR *pdir = opendir(path);
if (!pdir)
{
if (filter_pattern)
regfree(&reg);
LOG_ERROR("open directory failure. path %s, errmsg %d:%s",
path, errno, strerror(errno));
closedir(pdir);
return -1;
}
files.clear();
struct dirent entry;
struct dirent * pentry = NULL;
char tmp_path[PATH_MAX];
while((0 == readdir_r(pdir, &entry, &pentry)) && (NULL != pentry))
{
if ('.' == entry.d_name[0]) // 跳过./..文件和隐藏文件
continue;
snprintf(tmp_path, sizeof(tmp_path), "%s/%s", path, entry.d_name);
if (is_directory(tmp_path))
continue;
if (!filter_pattern || 0 == regexec(&reg, entry.d_name, 0, NULL, 0))
files.push_back(entry.d_name);
}
if (filter_pattern)
regfree(&reg);
int list_file(const char *path, const char *filter_pattern, std::vector<std::string> &files)
{
regex_t reg;
if (filter_pattern) {
const int res = regcomp(&reg, filter_pattern, REG_NOSUB);
if (res) {
char errbuf[256];
regerror(res, &reg, errbuf, sizeof(errbuf));
LOG_ERROR("regcomp return error. filter pattern %s. errmsg %d:%s", filter_pattern, res, errbuf);
return -1;
}
}
DIR *pdir = opendir(path);
if (!pdir) {
if (filter_pattern)
regfree(&reg);
LOG_ERROR("open directory failure. path %s, errmsg %d:%s", path, errno, strerror(errno));
return -1;
}
files.clear();
struct dirent entry;
struct dirent *pentry = NULL;
char tmp_path[PATH_MAX];
while ((0 == readdir_r(pdir, &entry, &pentry)) && (NULL != pentry)) {
if ('.' == entry.d_name[0]) // 跳过./..文件和隐藏文件
continue;
snprintf(tmp_path, sizeof(tmp_path), "%s/%s", path, entry.d_name);
if (is_directory(tmp_path))
continue;
if (!filter_pattern || 0 == regexec(&reg, entry.d_name, 0, NULL, 0))
files.push_back(entry.d_name);
}
if (filter_pattern)
regfree(&reg);
closedir(pdir);
return files.size();
return files.size();
}
} //namespace common
\ No newline at end of file
} // namespace common
\ No newline at end of file
此差异已折叠。
......@@ -22,8 +22,9 @@ See the Mulan PSL v2 for more details. */
namespace Json {
class Value;
} // namespace Json
} // namespace Json
// Take care of shallow copy
class FieldMeta {
public:
FieldMeta();
......@@ -33,22 +34,23 @@ public:
public:
const char *name() const;
AttrType type() const;
int offset() const;
int len() const;
bool visible() const;
AttrType type() const;
int offset() const;
int len() const;
bool visible() const;
public:
void desc(std::ostream &os) const;
public:
void to_json(Json::Value &json_value) const;
static RC from_json(const Json::Value &json_value, FieldMeta &field);
private:
std::string name_;
AttrType attr_type_;
int attr_offset_;
int attr_len_;
bool visible_;
protected:
std::string name_;
AttrType attr_type_;
int attr_offset_;
int attr_len_;
bool visible_;
};
#endif // __OBSERVER_STORAGE_COMMON_FIELD_META_H__
\ No newline at end of file
#endif // __OBSERVER_STORAGE_COMMON_FIELD_META_H__
\ No newline at end of file
此差异已折叠。
此差异已折叠。
......@@ -23,7 +23,7 @@ class FieldMeta;
namespace Json {
class Value;
} // namespace Json
} // namespace Json
class IndexMeta {
public:
......@@ -36,12 +36,13 @@ public:
const char *field() const;
void desc(std::ostream &os) const;
public:
void to_json(Json::Value &json_value) const;
static RC from_json(const TableMeta &table, const Json::Value &json_value, IndexMeta &index);
private:
std::string name_;
std::string field_;
protected:
std::string name_; // index's name
std::string field_; // field's name
};
#endif // __OBSERVER_STORAGE_COMMON_INDEX_META_H__
\ No newline at end of file
#endif // __OBSERVER_STORAGE_COMMON_INDEX_META_H__
\ No newline at end of file
......@@ -22,6 +22,7 @@ static const char *TABLE_DATA_SUFFIX = ".data";
static const char *TABLE_INDEX_SUFFIX = ".index";
std::string table_meta_file(const char *base_dir, const char *table_name);
std::string index_data_file(const char *base_dir, const char *table_name, const char *index_name);
std::string table_data_file(const char *base_dir, const char *table_name);
std::string table_index_file(const char *base_dir, const char *table_name, const char *index_name);
#endif //__OBSERVER_STORAGE_COMMON_META_UTIL_H_
#endif //__OBSERVER_STORAGE_COMMON_META_UTIL_H_
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册