Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

Commit

Permalink
http: support tcmalloc heap profiler and growth profiler (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wu Tao committed Jun 20, 2019
1 parent bf6c29a commit c00770c
Show file tree
Hide file tree
Showing 9 changed files with 803 additions and 5 deletions.
5 changes: 3 additions & 2 deletions bin/dsn.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ function(dsn_add_project)
set(MY_PROJ_SRC "")
endif()
set(TEMP_SRC "")
# We restrict the file suffix to keep our codes consitent.
# We restrict the file suffix to keep our codes consistent.
file(${MY_SRC_SEARCH_MODE} TEMP_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/*.c"
Expand Down Expand Up @@ -294,7 +294,8 @@ function(dsn_setup_system_libs)
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} ${OPENSSL_CRYPTO_LIBRARY})

if(ENABLE_GPERF)
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} tcmalloc)
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} tcmalloc_and_profiler)
add_definitions(-DDSN_ENABLE_GPERF)
endif()

set(DSN_SYSTEM_LIBS
Expand Down
10 changes: 9 additions & 1 deletion include/dsn/tool-api/http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@

namespace dsn {

enum http_method
{
HTTP_METHOD_GET = 1,
HTTP_METHOD_POST = 2,
};

struct http_request
{
static error_with<http_request> parse(dsn::message_ex *m);

// http://ip:port/<service>/<method>
std::pair<std::string, std::string> service_method;
blob body;
blob full_url;
http_method method;
};

enum class http_status_code
Expand Down Expand Up @@ -60,7 +68,7 @@ class http_service
it->second(req, resp);
} else {
resp.status_code = http_status_code::bad_request;
resp.body = "method not found";
resp.body = std::string("method not found for \"") + req.service_method.second + "\"";
}
}

Expand Down
248 changes: 248 additions & 0 deletions include/dsn/utility/string_splitter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
// Copyright (c) 2018, Xiaomi, Inc. All rights reserved.
// This source code is licensed under the Apache License Version 2.0, which
// can be found in the LICENSE file in the root directory of this source tree.

// Copyright (c) 2011 Baidu, Inc.
//
// 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.

#pragma once

#include <stdlib.h>
#include <stdint.h>

namespace dsn {

enum empty_field_action
{
SKIP_EMPTY_FIELD,
ALLOW_EMPTY_FIELD
};

// Split a string with one character
class string_splitter
{
public:
// Split `input' with `separator'. If `action' is SKIP_EMPTY_FIELD, zero-
// length() field() will be skipped.
inline string_splitter(const char *input,
char separator,
empty_field_action action = SKIP_EMPTY_FIELD);

// Allows containing embedded '\0' characters and separator can be '\0',
// if str_end is not NULL.
inline string_splitter(const char *str_begin,
const char *str_end,
char separator,
empty_field_action = SKIP_EMPTY_FIELD);

// Move splitter forward.
inline string_splitter &operator++();

inline string_splitter operator++(int);

// True iff field() is valid.
inline operator const void *() const;

// Beginning address and length of the field. *(field() + length()) may
// not be '\0' because we don't modify `input'.
inline const char *field() const;

inline size_t length() const;

// Cast field to specific type, and write the value into `pv'.
// Returns 0 on success, -1 otherwise.
// NOTE: If separator is a digit, casting functions always return -1.
inline int to_int8(int8_t *pv) const;

inline int to_uint8(uint8_t *pv) const;

inline int to_int(int *pv) const;

inline int to_uint(unsigned int *pv) const;

inline int to_long(long *pv) const;

inline int to_ulong(unsigned long *pv) const;

inline int to_longlong(long long *pv) const;

inline int to_ulonglong(unsigned long long *pv) const;

inline int to_float(float *pv) const;

inline int to_double(double *pv) const;

private:
inline bool not_end(const char *p) const;

inline void init();

const char *_head;
const char *_tail;
const char *_str_tail;
const char _sep;
const empty_field_action _empty_field_action;
};

string_splitter::string_splitter(const char *str, char sep, empty_field_action action)
: _head(str), _str_tail(NULL), _sep(sep), _empty_field_action(action)
{
init();
}

string_splitter::string_splitter(const char *str_begin,
const char *str_end,
const char sep,
empty_field_action action)
: _head(str_begin), _str_tail(str_end), _sep(sep), _empty_field_action(action)
{
init();
}

void string_splitter::init()
{
// Find the starting _head and _tail.
if (__builtin_expect(_head != NULL, 1)) {
if (_empty_field_action == SKIP_EMPTY_FIELD) {
for (; _sep == *_head && not_end(_head); ++_head) {
}
}
for (_tail = _head; *_tail != _sep && not_end(_tail); ++_tail) {
}
} else {
_tail = NULL;
}
}

string_splitter &string_splitter::operator++()
{
if (__builtin_expect(_tail != NULL, 1)) {
if (not_end(_tail)) {
++_tail;
if (_empty_field_action == SKIP_EMPTY_FIELD) {
for (; _sep == *_tail && not_end(_tail); ++_tail) {
}
}
}
_head = _tail;
for (; *_tail != _sep && not_end(_tail); ++_tail) {
}
}
return *this;
}

string_splitter string_splitter::operator++(int)
{
string_splitter tmp = *this;
operator++();
return tmp;
}

string_splitter::operator const void *() const
{
return (_head != NULL && not_end(_head)) ? _head : NULL;
}

const char *string_splitter::field() const { return _head; }

size_t string_splitter::length() const { return static_cast<size_t>(_tail - _head); }

bool string_splitter::not_end(const char *p) const
{
return (_str_tail == NULL) ? *p : (p != _str_tail);
}

int string_splitter::to_int8(int8_t *pv) const
{
long v = 0;
if (to_long(&v) == 0 && v >= -128 && v <= 127) {
*pv = (int8_t)v;
return 0;
}
return -1;
}

int string_splitter::to_uint8(uint8_t *pv) const
{
unsigned long v = 0;
if (to_ulong(&v) == 0 && v <= 255) {
*pv = (uint8_t)v;
return 0;
}
return -1;
}

int string_splitter::to_int(int *pv) const
{
long v = 0;
if (to_long(&v) == 0 && v >= INT_MIN && v <= INT_MAX) {
*pv = (int)v;
return 0;
}
return -1;
}

int string_splitter::to_uint(unsigned int *pv) const
{
unsigned long v = 0;
if (to_ulong(&v) == 0 && v <= UINT_MAX) {
*pv = (unsigned int)v;
return 0;
}
return -1;
}

int string_splitter::to_long(long *pv) const
{
char *endptr = NULL;
*pv = strtol(field(), &endptr, 10);
return (endptr == field() + length()) ? 0 : -1;
}

int string_splitter::to_ulong(unsigned long *pv) const
{
char *endptr = NULL;
*pv = strtoul(field(), &endptr, 10);
return (endptr == field() + length()) ? 0 : -1;
}

int string_splitter::to_longlong(long long *pv) const
{
char *endptr = NULL;
*pv = strtoll(field(), &endptr, 10);
return (endptr == field() + length()) ? 0 : -1;
}

int string_splitter::to_ulonglong(unsigned long long *pv) const
{
char *endptr = NULL;
*pv = strtoull(field(), &endptr, 10);
return (endptr == field() + length()) ? 0 : -1;
}

int string_splitter::to_float(float *pv) const
{
char *endptr = NULL;
*pv = strtof(field(), &endptr);
return (endptr == field() + length()) ? 0 : -1;
}

int string_splitter::to_double(double *pv) const
{
char *endptr = NULL;
*pv = strtod(field(), &endptr);
return (endptr == field() + length()) ? 0 : -1;
}

} // namespace dsn
63 changes: 63 additions & 0 deletions include/dsn/utility/timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) 2018, Xiaomi, Inc. All rights reserved.
// This source code is licensed under the Apache License Version 2.0, which
// can be found in the LICENSE file in the root directory of this source tree.

// Copyright (c) 2014 Baidu, Inc.
//
// 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.

#pragma once

#include <dsn/utility/chrono_literals.h>

namespace dsn {

class timer
{
public:
timer() = default;

// Start this timer
void start()
{
_start = std::chrono::system_clock::now();
_stop = _start;
}

// Stop this timer
void stop() { _stop = std::chrono::system_clock::now(); }

// Get the elapse from start() to stop(), in various units.
std::chrono::nanoseconds n_elapsed() const
{
return std::chrono::duration_cast<std::chrono::nanoseconds>(_stop - _start);
}
std::chrono::microseconds u_elapsed() const
{
return std::chrono::duration_cast<std::chrono::microseconds>(_stop - _start);
}
std::chrono::milliseconds m_elapsed() const
{
return std::chrono::duration_cast<std::chrono::milliseconds>(_stop - _start);
}
std::chrono::seconds s_elapsed() const
{
return std::chrono::duration_cast<std::chrono::seconds>(_stop - _start);
}

private:
std::chrono::time_point<std::chrono::system_clock> _stop;
std::chrono::time_point<std::chrono::system_clock> _start;
};

} // namespace dsn
4 changes: 2 additions & 2 deletions src/core/tools/http/http_message_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ http_message_parser::http_message_parser()

message_header *header = msg->header;
if (parser->type == HTTP_REQUEST && parser->method == HTTP_GET) {
header->hdr_type = *(uint32_t *)"GET ";
header->hdr_type = http_method::HTTP_METHOD_GET;
header->context.u.is_request = 1;
} else if (parser->type == HTTP_REQUEST && parser->method == HTTP_POST) {
header->hdr_type = *(uint32_t *)"POST";
header->hdr_type = http_method::HTTP_METHOD_POST;
header->context.u.is_request = 1;
} else {
derror("invalid http type %d and method %d", parser->type, parser->method);
Expand Down
Loading

0 comments on commit c00770c

Please sign in to comment.