| /* |
| * 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. |
| */ |
| |
| #ifndef UTILS_UTILS_H |
| #define UTILS_UTILS_H |
| |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <string.h> // memcpy |
| #include <sys/time.h> |
| |
| #include <iostream> |
| #include <sstream> |
| #include <string> |
| |
| #include "common/allocator/my_string.h" |
| #include "common/db_common.h" |
| #include "utils/util_define.h" |
| |
| namespace common { |
| |
| typedef struct FileID { |
| int64_t seq_; // timestamp when create |
| int32_t version_; |
| int32_t merge_; |
| |
| FileID() : seq_(0), version_(0), merge_(0) {} |
| void reset() { |
| seq_ = 0; |
| version_ = 0; |
| merge_ = 0; |
| } |
| FORCE_INLINE bool is_valid() const { return seq_ != 0; } |
| FORCE_INLINE bool operator<(const FileID &that) const { |
| return this->seq_ < that.seq_; |
| } |
| FORCE_INLINE bool operator==(const FileID &that) const { |
| return this->seq_ == that.seq_; |
| } |
| #ifndef NDEBUG |
| friend std::ostream &operator<<(std::ostream &out, const FileID &file_id) { |
| out << "{seq_=" << file_id.seq_ << ", version_=" << file_id.version_ |
| << ", merge_=" << file_id.merge_ << "}"; |
| return out; |
| } |
| #endif |
| } FileID; |
| |
| typedef uint16_t NodeID; |
| struct TsID { |
| NodeID db_nid_; |
| NodeID device_nid_; |
| NodeID measurement_nid_; |
| |
| TsID() : db_nid_(0), device_nid_(0), measurement_nid_(0){}; |
| |
| TsID(NodeID db_nid, NodeID device_nid, NodeID measurement_nid) |
| : db_nid_(db_nid), |
| device_nid_(device_nid), |
| measurement_nid_(measurement_nid) {} |
| |
| /* |
| * To make TsID to be a trival copyable struct. |
| */ |
| #if 0 |
| TsID(const TsID &other) : db_nid_(other.db_nid_), |
| device_nid_(other.device_nid_), |
| measurement_nid_(other.measurement_nid_) {} |
| |
| TsID & operator = (const TsID &other) |
| { |
| db_nid_ = other.db_nid_; |
| device_nid_ = other.device_nid_; |
| measurement_nid_ = other.measurement_nid_; |
| return *this; |
| } |
| #endif |
| |
| void reset() { |
| db_nid_ = 0; |
| device_nid_ = 0; |
| measurement_nid_ = 0; |
| } |
| |
| bool is_valid() const { |
| // TODO |
| return true; |
| } |
| |
| FORCE_INLINE bool operator==(const TsID &other) const { |
| return db_nid_ == other.db_nid_ && device_nid_ == other.device_nid_ && |
| measurement_nid_ == other.measurement_nid_; |
| } |
| FORCE_INLINE bool operator!=(const TsID &other) const { |
| return db_nid_ != other.db_nid_ || device_nid_ != other.device_nid_ || |
| measurement_nid_ != other.measurement_nid_; |
| } |
| |
| FORCE_INLINE int64_t to_int64() const { |
| int64_t res = db_nid_; |
| res = (res << 16) | device_nid_; |
| res = (res << 16) | measurement_nid_; |
| return res; |
| } |
| |
| FORCE_INLINE bool operator<(const TsID &that) const { |
| return to_int64() < that.to_int64(); |
| } |
| |
| FORCE_INLINE bool operator>(const TsID &other) { |
| return to_int64() > other.to_int64(); |
| } |
| |
| friend std::ostream &operator<<(std::ostream &out, TsID &ti) { |
| out << "(" << ti.db_nid_ << ", " << ti.device_nid_ << ", " |
| << ti.measurement_nid_ << ") "; |
| return out; |
| } |
| |
| FORCE_INLINE void to_string(char *print_buf, int len) const { |
| snprintf(print_buf, len, "<%d,%d,%d>", db_nid_, device_nid_, |
| measurement_nid_); |
| } |
| FORCE_INLINE std::string to_string() const { |
| const int buf_len = 32; |
| char buf[buf_len]; |
| snprintf(buf, buf_len, "<%d,%d,%d>", db_nid_, device_nid_, |
| measurement_nid_); |
| // construct std::string will invoke memory allocation and copy. |
| // try to use first to_string instead. |
| return std::string(buf); |
| } |
| }; |
| |
| struct DeviceID { |
| NodeID db_nid_; |
| NodeID device_nid_; |
| |
| DeviceID() : db_nid_(0), device_nid_(0) {} |
| DeviceID(const NodeID db_nid, const NodeID device_nid) |
| : db_nid_(db_nid), device_nid_(device_nid) {} |
| explicit DeviceID(const TsID &ts_id) |
| : db_nid_(ts_id.db_nid_), device_nid_(ts_id.device_nid_) {} |
| |
| FORCE_INLINE bool operator==(const DeviceID &other) const { |
| return db_nid_ == other.db_nid_ && device_nid_ == other.device_nid_; |
| } |
| FORCE_INLINE bool operator!=(const DeviceID &other) const { |
| return db_nid_ != other.db_nid_ || device_nid_ != other.device_nid_; |
| } |
| FORCE_INLINE void from(const TsID &ts_id) { |
| db_nid_ = ts_id.db_nid_; |
| device_nid_ = ts_id.device_nid_; |
| } |
| FORCE_INLINE bool operator<(const DeviceID &that) const { |
| int32_t this_i32 = (((int32_t)db_nid_) << 16) | (device_nid_); |
| int32_t that_i32 = (((int32_t)that.db_nid_) << 16) | (that.device_nid_); |
| return this_i32 < that_i32; |
| } |
| }; |
| |
| #define INVALID_TTL (-1) |
| |
| // describe single database |
| struct DatabaseDesc { |
| int64_t ttl_; |
| std::string db_name_; |
| TsID ts_id_; |
| |
| DatabaseDesc() : ttl_(INVALID_TTL), db_name_(""), ts_id_() {} |
| DatabaseDesc(uint64_t ttl, const std::string &name, const TsID &ts_id) |
| : ttl_(ttl), db_name_(name), ts_id_(ts_id) {} |
| }; |
| |
| // Describe single timeseries |
| struct ColumnDesc { |
| TSDataType type_; |
| TSEncoding encoding_; |
| CompressionType compression_; |
| int64_t ttl_; // obtained from the metadata and passed to the storage |
| std::string column_name_; // measurement name or Time |
| TsID ts_id_; // id of timeseries |
| |
| ColumnDesc() |
| : type_(INVALID_DATATYPE), |
| encoding_(PLAIN), |
| compression_(UNCOMPRESSED), |
| ttl_(INVALID_TTL), |
| column_name_(""), |
| ts_id_() {} |
| |
| ColumnDesc(TSDataType type, TSEncoding encoding, |
| CompressionType compression, uint64_t ttl, |
| const std::string &name, const TsID &ts_id) |
| : type_(type), |
| encoding_(encoding), |
| compression_(compression), |
| ttl_(ttl), |
| column_name_(name), |
| ts_id_(ts_id) {} |
| |
| ~ColumnDesc() {} |
| |
| bool operator==(const ColumnDesc &other) const { |
| return (type_ == other.type_ && encoding_ == other.encoding_ && |
| compression_ == other.compression_ && |
| column_name_ == other.column_name_ && ts_id_ == other.ts_id_); |
| } |
| |
| bool operator!=(const ColumnDesc &other) const { |
| return (type_ != other.type_ || encoding_ != other.encoding_ || |
| compression_ != other.compression_ || |
| column_name_ != other.column_name_ || ts_id_ != other.ts_id_); |
| } |
| |
| bool is_valid() const { |
| return type_ != INVALID_DATATYPE && encoding_ != INVALID_ENCODING && |
| compression_ != INVALID_COMPRESSION && ts_id_.is_valid(); |
| } |
| |
| void reset() { |
| // TODO |
| } |
| |
| void get_device_name(char *ret_device_name_buf, const int buf_len, |
| uint32_t &ret_len) const { |
| int pos = column_name_.find_last_of('.'); |
| ASSERT(pos > 0 && pos < buf_len); |
| memcpy(ret_device_name_buf, column_name_.c_str(), pos); |
| ret_device_name_buf[pos] = '\0'; |
| ret_len = pos; |
| } |
| std::string get_device_name_str() const { |
| int pos = column_name_.find_last_of('.'); |
| ASSERT(pos > 0); |
| return column_name_.substr(0, pos); |
| } |
| void get_device_name(String &device_name) const { |
| int pos = column_name_.find_last_of('.'); |
| ASSERT(pos > 0); |
| const char *c_string = column_name_.c_str(); |
| device_name.buf_ = (char *)c_string; |
| device_name.len_ = pos; |
| } |
| void get_measurement_name(char *ret_measurement_name_buf, const int buf_len, |
| uint32_t &ret_len) const { |
| int pos = column_name_.find_last_of('.'); |
| ASSERT(pos > 0 && pos < buf_len); |
| ret_len = column_name_.size() - pos - 1; |
| memcpy(ret_measurement_name_buf, column_name_.c_str() + pos + 1, |
| ret_len); |
| ret_measurement_name_buf[ret_len] = '\0'; |
| } |
| std::string get_measurement_name_str() const { |
| int pos = column_name_.find_last_of('.'); |
| ASSERT(pos > 0); |
| return column_name_.substr(pos + 1, column_name_.size() - pos); |
| } |
| // TODO remove |
| void get_measurement_name(String &measurement_name) const { |
| int pos = column_name_.find_last_of('.'); |
| ASSERT(pos > 0); |
| const char *c_string = column_name_.c_str(); |
| measurement_name.buf_ = (char *)c_string + pos + 1; |
| measurement_name.len_ = column_name_.size() - pos - 1; |
| } |
| String get_measurement_name() { |
| int pos = column_name_.find_last_of('.'); |
| ASSERT(pos > 0); |
| const char *c_string = column_name_.c_str(); |
| String res; |
| res.buf_ = (char *)c_string + pos + 1; |
| res.len_ = column_name_.size() - pos - 1; |
| return res; |
| } |
| |
| std::string debug_string() // for debug |
| { |
| std::stringstream out; |
| out << "print ColumnDesc: " << this << std::endl |
| << "name: " << column_name_.c_str() << std::endl |
| << "datatype: " << type_ << std::endl |
| << "encoding: " << encoding_ << std::endl |
| << "compression:" << compression_ << std::endl |
| << "ttl:" << ttl_ << std::endl |
| << "tsid:" << ts_id_.to_string().c_str() << std::endl; |
| return out.str(); |
| } |
| }; |
| |
| enum WALFlushPolicy { |
| WAL_DISABLED = 0, |
| WAL_ASYNC = 1, |
| WAL_FLUSH = 2, |
| WAL_SYNC = 3, |
| }; |
| |
| template <typename T> |
| std::string to_string(const T &val) { |
| // todo: There may be a better way to avoid the memory problem of |
| // ostringstream |
| std::ostringstream oss; |
| oss << val; |
| return oss.str(); |
| } |
| |
| // TODO rename to DatabaseIdTTL |
| struct DatabaseIdTTL { |
| NodeID db_nid_; |
| int64_t ttl_; |
| DatabaseIdTTL() {} |
| DatabaseIdTTL(NodeID db_nid, int64_t ttl) : db_nid_(db_nid), ttl_(ttl) {} |
| DatabaseIdTTL(const DatabaseIdTTL &other) |
| : db_nid_(other.db_nid_), ttl_(other.ttl_) {} |
| DatabaseIdTTL &operator=(const DatabaseIdTTL &other) { |
| this->db_nid_ = other.db_nid_; |
| this->ttl_ = other.ttl_; |
| return *this; |
| } |
| bool operator==(const DatabaseIdTTL &other) { |
| if (db_nid_ != other.db_nid_ || ttl_ != other.ttl_) { |
| return false; |
| } |
| return true; |
| } |
| friend std::ostream &operator<<(std::ostream &out, DatabaseIdTTL &di) { |
| out << "(" << di.db_nid_ << ", " << di.ttl_ << ") "; |
| return out; |
| } |
| }; |
| |
| FORCE_INLINE int64_t get_cur_timestamp() { |
| int64_t timestamp = 0; |
| struct timeval tv; |
| if (gettimeofday(&tv, NULL) >= 0) { |
| timestamp = (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; |
| } |
| return timestamp; |
| } |
| |
| #if 0 |
| struct DatabaseIdTTL |
| { |
| NodeID db_nid_; |
| int64_t ttl_; |
| int16_t counter_; // suppose we at most support 64k timeseries. |
| DatabaseIdTTL() {} |
| DatabaseIdTTL(NodeID db_nid, int64_t ttl, int16_t counter) : db_nid_(db_nid), ttl_(ttl), counter_(counter) {} |
| DatabaseIdTTL(const DatabaseIdTTL &other) : db_nid_(other.db_nid_), ttl_(other.ttl_), counter_(other.counter_) {} |
| DatabaseIdTTL & operator = (const DatabaseIdTTL &other) |
| { |
| this->db_nid_ = other.db_nid_; |
| this->ttl_ = other.ttl_; |
| this->counter_ = other.counter_; |
| return *this; |
| } |
| bool operator == (const DatabaseIdTTL &other) |
| { |
| if (db_nid_ != other.db_nid_ || ttl_ != other.ttl_ || counter_ != other.counter_) { |
| return false; |
| } |
| return true; |
| } |
| friend std::ostream& operator << (std::ostream& out, DatabaseIdTTL& di) |
| { |
| |
| return out; |
| } |
| }; |
| |
| struct DeviceIDWithCounter |
| { |
| NodeID device_nid_; |
| int16_t counter_; // suppose we at most support 64k timeseries. |
| DeviceIDWithCounter() {} |
| DeviceIDWithCounter(NodeID device_nid, int16_t counter) : device_nid_(device_nid), counter_(counter) {} |
| DeviceIDWithCounter(const DeviceIDWithCounter &other) : device_nid_(other.device_nid_), counter_(other.counter_) {} |
| DeviceIDWithCounter& operator = (const DeviceIDWithCounter &other) |
| { |
| this->device_nid_ = other.device_nid_; |
| this->counter_ = other.counter_; |
| return *this; |
| } |
| bool operator == (const DeviceID &other) |
| { |
| if (device_nid_ != other.device_nid_ || counter_ != other.counter_) { |
| return false; |
| } |
| return true; |
| } |
| friend std::ostream& operator << (std::ostream& out, DeviceID& di) |
| { |
| out << "(" << di.device_nid_ << ", " << di.counter_ << ") "; |
| return out; |
| } |
| }; |
| #endif |
| |
| } // end namespace common |
| |
| #endif // UTILS_UTILS_H |