Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
apache
Incubator Pegasus
提交
e56690c2
Incubator Pegasus
项目概览
apache
/
Incubator Pegasus
通知
9
Star
5
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Incubator Pegasus
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
e56690c2
编写于
9月 16, 2020
作者:
W
Wu Tao
提交者:
GitHub
9月 16, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor: use db_get to implement incr (#598)
上级
b0578482
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
114 addition
and
28 deletion
+114
-28
src/server/pegasus_read_service.h
src/server/pegasus_read_service.h
+17
-0
src/server/pegasus_write_service_impl.h
src/server/pegasus_write_service_impl.h
+20
-28
src/server/test/pegasus_write_service_impl_test.cpp
src/server/test/pegasus_write_service_impl_test.cpp
+77
-0
未找到文件。
src/server/pegasus_read_service.h
浏览文件 @
e56690c2
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#pragma once
#include <iostream>
#include <dsn/dist/replication/replication_app_base.h>
...
...
src/server/pegasus_write_service_impl.h
浏览文件 @
e56690c2
...
...
@@ -177,21 +177,25 @@ public:
resp
.
decree
=
decree
;
resp
.
server
=
_primary_address
;
rocksdb
::
Slice
raw_key
(
update
.
key
.
data
(),
update
.
key
.
length
());
std
::
string
raw_value
;
dsn
::
string_view
raw_key
(
update
.
key
.
data
(),
update
.
key
.
length
());
int64_t
new_value
=
0
;
uint32_t
new_expire_ts
=
0
;
rocksdb
::
Status
s
=
_db
->
Get
(
_rd_opts
,
raw_key
,
&
raw_value
);
if
(
s
.
ok
())
{
uint32_t
old_expire_ts
=
pegasus_extract_expire_ts
(
_pegasus_data_version
,
raw_value
);
if
(
check_if_ts_expired
(
utils
::
epoch_now
(),
old_expire_ts
))
{
db_get_context
get_ctx
;
int
err
=
db_get
(
raw_key
,
&
get_ctx
);
if
(
err
==
0
)
{
if
(
!
get_ctx
.
found
)
{
// old value is not found, set to 0 before increment
new_value
=
update
.
increment
;
new_expire_ts
=
update
.
expire_ts_seconds
>
0
?
update
.
expire_ts_seconds
:
0
;
}
else
if
(
get_ctx
.
expired
)
{
// ttl timeout, set to 0 before increment
_pfc_recent_expire_count
->
increment
();
new_value
=
update
.
increment
;
new_expire_ts
=
update
.
expire_ts_seconds
>
0
?
update
.
expire_ts_seconds
:
0
;
}
else
{
::
dsn
::
blob
old_value
;
pegasus_extract_user_data
(
_pegasus_data_version
,
std
::
move
(
raw_value
),
old_value
);
pegasus_extract_user_data
(
_pegasus_data_version
,
std
::
move
(
get_ctx
.
raw_value
),
old_value
);
if
(
old_value
.
length
()
==
0
)
{
// empty old value, set to 0 before increment
new_value
=
update
.
increment
;
...
...
@@ -223,29 +227,14 @@ public:
}
}
// set new ttl
if
(
update
.
expire_ts_seconds
==
0
)
new_expire_ts
=
old_
expire_ts
;
else
if
(
update
.
expire_ts_seconds
<
0
)
if
(
update
.
expire_ts_seconds
==
0
)
{
new_expire_ts
=
get_ctx
.
expire_ts
;
}
else
if
(
update
.
expire_ts_seconds
<
0
)
{
new_expire_ts
=
0
;
else
// update.expire_ts_seconds > 0
}
else
{
// update.expire_ts_seconds > 0
new_expire_ts
=
update
.
expire_ts_seconds
;
}
}
}
else
if
(
s
.
IsNotFound
())
{
// old value is not found, set to 0 before increment
new_value
=
update
.
increment
;
new_expire_ts
=
update
.
expire_ts_seconds
>
0
?
update
.
expire_ts_seconds
:
0
;
}
else
{
// read old value failed
::
dsn
::
blob
hash_key
,
sort_key
;
pegasus_restore_key
(
::
dsn
::
blob
(
raw_key
.
data
(),
0
,
raw_key
.
size
()),
hash_key
,
sort_key
);
derror_rocksdb
(
"Get for Incr"
,
s
.
ToString
(),
"decree: {}, hash_key: {}, sort_key: {}"
,
decree
,
utils
::
c_escape_string
(
hash_key
),
utils
::
c_escape_string
(
sort_key
));
resp
.
error
=
s
.
code
();
return
resp
.
error
;
}
resp
.
error
=
...
...
@@ -675,7 +664,10 @@ private:
return
status
.
code
();
}
// The resulted `expire_ts` is -1 if record is expired.
/// Calls RocksDB Get and store the result into `db_get_context`.
/// \returns 0 if Get succeeded. On failure, a non-zero rocksdb status code is returned.
/// \result ctx.expired=true if record expired. Still 0 is returned.
/// \result ctx.found=false if record is not found. Still 0 is returned.
int
db_get
(
dsn
::
string_view
raw_key
,
/*out*/
db_get_context
*
ctx
)
{
...
...
src/server/test/pegasus_write_service_impl_test.cpp
浏览文件 @
e56690c2
...
...
@@ -52,6 +52,22 @@ public:
SetUp
();
}
int
db_get
(
dsn
::
string_view
raw_key
,
db_get_context
*
get_ctx
)
{
return
_write_impl
->
db_get
(
raw_key
,
get_ctx
);
}
void
single_set
(
dsn
::
blob
raw_key
,
dsn
::
blob
user_value
)
{
dsn
::
apps
::
update_request
put
;
put
.
key
=
raw_key
;
put
.
value
=
user_value
;
db_write_context
write_ctx
;
dsn
::
apps
::
update_response
put_resp
;
_write_impl
->
batch_put
(
write_ctx
,
put
,
put_resp
);
ASSERT_EQ
(
_write_impl
->
batch_commit
(
0
),
0
);
}
};
TEST_F
(
pegasus_write_service_impl_test
,
put_verify_timetag
)
...
...
@@ -140,5 +156,66 @@ TEST_F(pegasus_write_service_impl_test, verify_timetag_compatible_with_version_0
dsn
::
fail
::
teardown
();
}
class
incr_test
:
public
pegasus_write_service_impl_test
{
public:
void
SetUp
()
override
{
pegasus_write_service_impl_test
::
SetUp
();
pegasus
::
pegasus_generate_key
(
req
.
key
,
dsn
::
string_view
(
"hash_key"
),
dsn
::
string_view
(
"sort_key"
));
}
dsn
::
apps
::
incr_request
req
;
dsn
::
apps
::
incr_response
resp
;
};
TEST_F
(
incr_test
,
incr_on_absent_record
)
{
// ensure key is absent
db_get_context
get_ctx
;
db_get
(
req
.
key
,
&
get_ctx
);
ASSERT_FALSE
(
get_ctx
.
found
);
req
.
increment
=
100
;
_write_impl
->
incr
(
0
,
req
,
resp
);
ASSERT_EQ
(
resp
.
new_value
,
100
);
db_get
(
req
.
key
,
&
get_ctx
);
ASSERT_TRUE
(
get_ctx
.
found
);
}
TEST_F
(
incr_test
,
negative_incr_and_zero_incr
)
{
req
.
increment
=
-
100
;
ASSERT_EQ
(
0
,
_write_impl
->
incr
(
0
,
req
,
resp
));
ASSERT_EQ
(
resp
.
new_value
,
-
100
);
req
.
increment
=
-
1
;
ASSERT_EQ
(
0
,
_write_impl
->
incr
(
0
,
req
,
resp
));
ASSERT_EQ
(
resp
.
new_value
,
-
101
);
req
.
increment
=
0
;
ASSERT_EQ
(
0
,
_write_impl
->
incr
(
0
,
req
,
resp
));
ASSERT_EQ
(
resp
.
new_value
,
-
101
);
}
TEST_F
(
incr_test
,
invalid_incr
)
{
single_set
(
req
.
key
,
dsn
::
blob
::
create_from_bytes
(
"abc"
));
req
.
increment
=
10
;
_write_impl
->
incr
(
1
,
req
,
resp
);
ASSERT_EQ
(
resp
.
error
,
rocksdb
::
Status
::
kInvalidArgument
);
ASSERT_EQ
(
resp
.
new_value
,
0
);
single_set
(
req
.
key
,
dsn
::
blob
::
create_from_bytes
(
"100"
));
req
.
increment
=
std
::
numeric_limits
<
int64_t
>::
max
();
_write_impl
->
incr
(
1
,
req
,
resp
);
ASSERT_EQ
(
resp
.
error
,
rocksdb
::
Status
::
kInvalidArgument
);
ASSERT_EQ
(
resp
.
new_value
,
100
);
}
}
// namespace server
}
// namespace pegasus
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录