Skip to content

Commit

Permalink
Merge pull request #1 from an-tao/master
Browse files Browse the repository at this point in the history
更新同步
  • Loading branch information
joestarzxh authored Sep 25, 2020
2 parents 11cabfb + 5bca202 commit c54e0a7
Show file tree
Hide file tree
Showing 21 changed files with 261 additions and 108 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
[![Build Status](https://travis-ci.com/an-tao/drogon.svg?branch=master)](https://travis-ci.com/an-tao/drogon)
[![Build status](https://ci.appveyor.com/api/projects/status/12ffuf6j5vankgyb/branch/master?svg=true)](https://ci.appveyor.com/project/an-tao/drogon/branch/master)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/an-tao/drogon.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/an-tao/drogon/alerts/)
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/an-tao/drogon.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/an-tao/drogon/context:cpp)
[![Join the chat at https://gitter.im/drogon-web/community](https://badges.gitter.im/drogon-web/community.svg)](https://gitter.im/drogon-web/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Docker image](https://img.shields.io/badge/Docker-image-blue.svg)](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)

Expand Down Expand Up @@ -182,7 +181,7 @@ As you can see, users can use the `HttpController` to map paths and parameters a

In addition, you can also find that all handler interfaces are in asynchronous mode, where the response is returned by a callback object. This design is for performance reasons because in asynchronous mode the drogon application can handle a large number of concurrent requests with a small number of threads.

After compiling all of the above source files, we get a very simple web application. This is a good start. **For more information, please visit the [wiki](https://github.com/an-tao/drogon/wiki/01-Overview) or [DocsForge](https://drogon.docsforge.com/master/overview/)**
After compiling all of the above source files, we get a very simple web application. This is a good start. **For more information, please visit the [wiki](https://github.com/an-tao/drogon/wiki/ENG-01-Overview) or [DocsForge](https://drogon.docsforge.com/master/overview/)**

## Contributions
Every contribution is welcome. Please refer to the [contribution guidelines](CONTRIBUTING.md) for more information.
4 changes: 2 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
![](https://github.com/an-tao/drogon/wiki/images/drogon-white.jpg)

[![Build Status](https://travis-ci.com/an-tao/drogon.svg?branch=master)](https://travis-ci.com/an-tao/drogon)
[![Build status](https://ci.appveyor.com/api/projects/status/12ffuf6j5vankgyb/branch/master?svg=true)](https://ci.appveyor.com/project/an-tao/drogon/branch/master)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/an-tao/drogon.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/an-tao/drogon/alerts/)
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/an-tao/drogon.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/an-tao/drogon/context:cpp)
[![Join the chat at https://gitter.im/drogon-web/community](https://badges.gitter.im/drogon-web/community.svg)](https://gitter.im/drogon-web/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Docker image](https://img.shields.io/badge/Docker-image-blue.svg)](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)

Expand Down Expand Up @@ -184,7 +184,7 @@ class User : public drogon::HttpController<User>

另外,你可以发现前面所有的处理函数接口都是异步的,处理器的响应是通过回调对象返回的。这种设计是出于对高性能的考虑,因为在异步模式下,可以使用少量的线程(比如和处理器核心数相等的线程)处理大量的并发请求。

编译上述的所有源文件后,我们得到了一个非常简单的web应用程序,这是一个不错的开始。**请访问[wiki](https://github.com/an-tao/drogon/wiki/01-Overview)或者[doxiz](https://doxiz.com/drogon/master/overview/)以获取更多的信息**
编译上述的所有源文件后,我们得到了一个非常简单的web应用程序,这是一个不错的开始。**请访问[wiki](https://github.com/an-tao/drogon/wiki/CHN-01-概述)或者[doxiz](https://doxiz.com/drogon/master/overview/)以获取更多的信息**

## 贡献方式

Expand Down
4 changes: 3 additions & 1 deletion drogon_ctl/create_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ void create_model::createModelClassFromPG(
}
else if (pkNumber > 1)
{
std::vector<std::string> pkNames, pkTypes;
std::vector<std::string> pkNames, pkTypes, pkValNames;
for (size_t i = 1; i <= pkNumber; ++i)
{
*client << "SELECT \
Expand All @@ -283,6 +283,7 @@ void create_model::createModelClassFromPG(
if (isNull)
return;
pkNames.push_back(colName);
pkValNames.push_back(nameTransform(colName, false));
for (auto &col : cols)
{
if (col.colName_ == colName)
Expand All @@ -299,6 +300,7 @@ void create_model::createModelClassFromPG(
}
data["primaryKeyName"] = pkNames;
data["primaryKeyType"] = pkTypes;
data["primaryKeyValNames"] = pkValNames;
}

data["columns"] = cols;
Expand Down
14 changes: 6 additions & 8 deletions drogon_ctl/templates/model_cc.csp
Original file line number Diff line number Diff line change
Expand Up @@ -868,15 +868,13 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
$$<<"{\n";
$$<<" return std::make_tuple(";
int count=0;
for(auto col:cols)
auto pkNames=@@.get<std::vector<std::string>>("primaryKeyValNames");
for(auto pkName:pkNames)
{
if(col.isPrimaryKey_)
{
++count;
$$<<"*"<<col.colValName_<<"_";
if(count<@@.get<int>("hasPrimaryKey"))
$$<<",";
}
++count;
$$<<"*"<<pkName<<"_";
if(count<@@.get<int>("hasPrimaryKey"))
$$<<",";
}
$$<<");\n";
$$<<"}\n";
Expand Down
4 changes: 2 additions & 2 deletions examples/simple_example/FileUpload.csp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//File uploading method
function UpladFile() {
var fileObj = document.getElementById("file").files[0]; // js get file object
var url = "http://localhost:8848" + "/api/attachment/upload";
var url = "/api/attachment/upload";

var form = new FormData(); // FormData object
form.append("file", fileObj); // File object
Expand Down Expand Up @@ -84,4 +84,4 @@
<input type="button" onclick="UpladFile()" value="Upload" />
<input type="button" onclick="cancleUploadFile()" value="Cancel" />
</body>
</html>
</html>
163 changes: 108 additions & 55 deletions lib/inc/drogon/CacheMap.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* CacheMap.h
* @file CacheMap.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
Expand Down Expand Up @@ -99,7 +99,7 @@ class CacheMap
}
if (tickInterval_ > 0 && wheelsNumber_ > 0 && bucketsNumPerWheel_ > 0)
{
timerId_ = loop_->runEvery(tickInterval_, [=]() {
timerId_ = loop_->runEvery(tickInterval_, [this]() {
size_t t = ++ticksCounter_;
size_t pow = 1;
for (size_t i = 0; i < wheelsNumber_; ++i)
Expand Down Expand Up @@ -127,23 +127,46 @@ class CacheMap
};
~CacheMap()
{
map_.clear();
for (auto iter = wheels_.rbegin(); iter != wheels_.rend(); ++iter)
{
std::lock_guard<std::mutex> guard(mtx_);
map_.clear();
}
{
std::lock_guard<std::mutex> lock(bucketMutex_);
for (auto iter = wheels_.rbegin(); iter != wheels_.rend(); ++iter)
{
iter->clear();
}
iter->clear();
}
LOG_TRACE << "CacheMap destruct!";
}
struct MapValue
{
size_t timeout = 0;
T2 value;
MapValue(const T2 &value,
size_t timeout,
std::function<void()> &&callback)
: value_(value),
timeout_(timeout),
timeoutCallback_(std::move(callback))
{
}
MapValue(T2 &&value, size_t timeout, std::function<void()> &&callback)
: value_(std::move(value)),
timeout_(timeout),
timeoutCallback_(std::move(callback))
{
}
MapValue(T2 &&value, size_t timeout)
: value_(std::move(value)), timeout_(timeout)
{
}
MapValue(const T2 &value, size_t timeout)
: value_(value), timeout_(timeout)
{
}
MapValue(T2 &&value) : value_(std::move(value))
{
}
MapValue(const T2 &value) : value_(value)
{
}
MapValue() = default;
T2 value_;
size_t timeout_{0};
std::function<void()> timeoutCallback_;
WeakCallbackEntryPtr weakEntryPtr_;
};
Expand All @@ -165,23 +188,16 @@ class CacheMap
{
if (timeout > 0)
{
MapValue v;
v.value = std::move(value);
v.timeout = timeout;
v.timeoutCallback_ = std::move(timeoutCallback);
MapValue v{std::move(value), timeout, std::move(timeoutCallback)};
std::lock_guard<std::mutex> lock(mtx_);
map_[key] = std::move(v);
map_.insert(std::make_pair(key, std::move(v)));
eraseAfter(timeout, key);
}
else
{
MapValue v;
v.value = std::move(value);
v.timeout = timeout;
v.timeoutCallback_ = std::function<void()>();
v.weakEntryPtr_ = WeakCallbackEntryPtr();
MapValue v{std::move(value)};
std::lock_guard<std::mutex> lock(mtx_);
map_[key] = std::move(v);
map_.insert(std::make_pair(key, std::move(v)));
}
}
/**
Expand All @@ -201,43 +217,79 @@ class CacheMap
{
if (timeout > 0)
{
MapValue v;
v.value = value;
v.timeout = timeout;
v.timeoutCallback_ = std::move(timeoutCallback);
MapValue v{value, timeout, std::move(timeoutCallback)};
std::lock_guard<std::mutex> lock(mtx_);
map_[key] = std::move(v);
map_.insert(std::make_pair(key, std::move(v)));
eraseAfter(timeout, key);
}
else
{
MapValue v;
v.value = value;
v.timeout = timeout;
v.timeoutCallback_ = std::function<void()>();
v.weakEntryPtr_ = WeakCallbackEntryPtr();
MapValue v{value};
std::lock_guard<std::mutex> lock(mtx_);
map_[key] = std::move(v);
map_.insert(std::make_pair(key, std::move(v)));
}
}

/// Return the reference to the value of the keyword.
T2 &operator[](const T1 &key)
/**
* @brief Return the value of the keyword.
*
* @param key
* @return T2
* @note This function returns a copy of the data in the cache. If the data
* is not found, a default T2 type value is returned and nothing is inserted
* into the cache.
*/
T2 operator[](const T1 &key)
{
int timeout = 0;

std::lock_guard<std::mutex> lock(mtx_);
auto iter = map_.find(key);
if (iter != map_.end())
{
timeout = iter->second.timeout;
timeout = iter->second.timeout_;
if (timeout > 0)
eraseAfter(timeout, key);
return iter->second.value;
return iter->second.value_;
}
return map_[key].value;
return T2();
}

/**
* @brief Modify or visit the data identified by the key parameter.
*
* @tparam Callable the type of the handler.
* @param key
* @param handler A callable that can modify or visit the data. The
* signature of the handler should be equivalent to 'void(T2&)' or
* 'void(const T2&)'
* @param timeout In seconds.
*
* @note This function is multiple-thread safe. if the data identified by
* the key doesn't exist, a new one is created and passed to the handler and
* stored in the cache with the timeout parameter. The changing of the data
* is protected by the mutex of the cache.
*/
template <typename Callable>
void modify(const T1 &key, Callable &&handler, size_t timeout = 0)
{
std::lock_guard<std::mutex> lock(mtx_);
auto iter = map_.find(key);
if (iter != map_.end())
{
timeout = iter->second.timeout_;
handler(iter->second.value_);
if (timeout > 0)
eraseAfter(timeout, key);
return;
}
MapValue v{T2(), timeout};
handler(v.value_);
map_.insert(std::make_pair(key, std::move(v)));
if (timeout > 0)
{
eraseAfter(timeout, key);
}
}
/// Check if the value of the keyword exists
bool find(const T1 &key)
{
Expand All @@ -248,7 +300,7 @@ class CacheMap
auto iter = map_.find(key);
if (iter != map_.end())
{
timeout = iter->second.timeout;
timeout = iter->second.timeout_;
flag = true;
}

Expand All @@ -271,9 +323,9 @@ class CacheMap
auto iter = map_.find(key);
if (iter != map_.end())
{
timeout = iter->second.timeout;
timeout = iter->second.timeout_;
flag = true;
value = iter->second.value;
value = iter->second.value_;
}

if (timeout > 0)
Expand Down Expand Up @@ -357,15 +409,16 @@ class CacheMap
}
if (i < (wheelsNumber_ - 1))
{
entryPtr = std::make_shared<CallbackEntry>([=]() {
if (delay > 0)
{
std::lock_guard<std::mutex> lock(bucketMutex_);
wheels_[i][(delay + (t % bucketsNumPerWheel_) - 1) %
bucketsNumPerWheel_]
.insert(entryPtr);
}
});
entryPtr = std::make_shared<CallbackEntry>(
[this, delay, i, t, entryPtr]() {
if (delay > 0)
{
std::lock_guard<std::mutex> lock(bucketMutex_);
wheels_[i][(delay + (t % bucketsNumPerWheel_) - 1) %
bucketsNumPerWheel_]
.insert(entryPtr);
}
});
}
else
{
Expand Down Expand Up @@ -397,14 +450,14 @@ class CacheMap
}
else
{
std::function<void()> cb = [=]() {
std::function<void()> cb = [this, key]() {
std::lock_guard<std::mutex> lock(mtx_);
if (map_.find(key) != map_.end())
{
auto &value = map_[key];
auto entryPtr = value.weakEntryPtr_.lock();
// entryPtr is used to avoid race conditions
if (value.timeout > 0 && !entryPtr)
if (value.timeout_ > 0 && !entryPtr)
{
if (value.timeoutCallback_)
{
Expand Down
3 changes: 1 addition & 2 deletions lib/inc/drogon/DrObject.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* DrObject.h
* @file DrObject.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
Expand Down Expand Up @@ -110,7 +110,6 @@ class DrObject : public virtual DrObjectBase
void>::type
registerClass()
{
LOG_ERROR << "Can't register classes without a default constructor";
}
};

Expand Down
Loading

0 comments on commit c54e0a7

Please sign in to comment.