leveldb源码解析3——Status类

来源:互联网 发布:云计算运维工程师招聘 编辑:程序博客网 时间:2024/06/06 09:10

    这周太忙了,快下周一了才有时间写写博客,还好这次准备写的Status类非常简单,看起唯一的成员变量state_的注释就知道这个类是干嘛的:

 private:  // OK status has a NULL state_.  Otherwise, state_ is a new[] array  // of the following form:  //    state_[0..3] == length of message 4个字节(sizeof(uint32_t))  //    state_[4]    == code 一个字节  //    state_[5..]  == message  const char* state_;  enum Code {    kOk = 0,    kNotFound = 1,    kCorruption = 2,    kNotSupported = 3,    kInvalidArgument = 4,    kIOError = 5  };  Code code() const {    return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);  }

从注释中可以知道,这是个典型的TLV结构,但是Status严格的说应该是个LTV,不过本质都一样啦,该类提供了一个私有的code方法,是其它方法可以知道要处理的类型,使用memcpy(&size, state, sizeof(size))这样的操作就能很方便的获取state的长度,下面直接贴出status.h和status.cc,由于其源代码注释非常完整而且本身非常简单,所以只加了少许自己的注释。

// Copyright (c) 2011 The LevelDB Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file. See the AUTHORS file for names of contributors.//// A Status encapsulates the result of an operation.  It may indicate success,// or it may indicate an error with an associated error message.//// Multiple threads can invoke const methods on a Status without// external synchronization, but if any of the threads may call a// non-const method, all threads accessing the same Status must use// external synchronization.#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_#define STORAGE_LEVELDB_INCLUDE_STATUS_H_#include <string>#include "leveldb/slice.h"namespace leveldb {class Status { public:  // Create a success status.  Status() : state_(NULL) { }  ~Status() { delete[] state_; }  // Copy the specified status.  Status(const Status& s);  void operator=(const Status& s);  // Return a success status.  static Status OK() { return Status(); }  // Return error status of an appropriate type.  static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) {    return Status(kNotFound, msg, msg2);  }  static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) {    return Status(kCorruption, msg, msg2);  }  static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {    return Status(kNotSupported, msg, msg2);  }  static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) {    return Status(kInvalidArgument, msg, msg2);  }  static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {    return Status(kIOError, msg, msg2);  }  // Returns true iff the status indicates success.  bool ok() const { return (state_ == NULL); }  // Returns true iff the status indicates a NotFound error.  bool IsNotFound() const { return code() == kNotFound; }  // Returns true iff the status indicates a Corruption error.  bool IsCorruption() const { return code() == kCorruption; }  // Returns true iff the status indicates an IOError.  bool IsIOError() const { return code() == kIOError; }  // Return a string representation of this status suitable for printing.  // Returns the string "OK" for success.  std::string ToString() const; private:  // OK status has a NULL state_.  Otherwise, state_ is a new[] array  // of the following form:  //    state_[0..3] == length of message 4个字节(sizeof(uint32_t))  //    state_[4]    == code 一个字节  //    state_[5..]  == message  const char* state_;  enum Code {    kOk = 0,    kNotFound = 1,    kCorruption = 2,    kNotSupported = 3,    kInvalidArgument = 4,    kIOError = 5  };  Code code() const {    return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);  }  Status(Code code, const Slice& msg, const Slice& msg2);  static const char* CopyState(const char* s);};inline Status::Status(const Status& s) {  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);}inline void Status::operator=(const Status& s) {  // The following condition catches both aliasing (when this == &s),  // and the common case where both s and *this are ok.  if (state_ != s.state_) {/*  这样应该更安全,可以避免CopyState中new操作抛出的异常使得state_维持原则Status tmp(s);tmp.state_ = state_;state_ = s.state_;delete[] tmp.state_;*/    delete[] state_;// 可以delete空指针    state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);  }}}  // namespace leveldb#endif  // STORAGE_LEVELDB_INCLUDE_STATUS_H_

// Copyright (c) 2011 The LevelDB Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file. See the AUTHORS file for names of contributors.#include <stdio.h>#include "port/port.h"#include "leveldb/status.h"namespace leveldb {const char* Status::CopyState(const char* state) {  uint32_t size;  memcpy(&size, state, sizeof(size)); //state的前4个字节表示长度即size  char* result = new char[size + 5];  memcpy(result, state, size + 5);  return result;}Status::Status(Code code, const Slice& msg, const Slice& msg2) {  assert(code != kOk);  const uint32_t len1 = msg.size();  const uint32_t len2 = msg2.size();  const uint32_t size = len1 + (len2 ? (2 + len2) : 0);  char* result = new char[size + 5];  memcpy(result, &size, sizeof(size));  result[4] = static_cast<char>(code);  memcpy(result + 5, msg.data(), len1);  if (len2) {    result[5 + len1] = ':';    result[6 + len1] = ' ';    memcpy(result + 7 + len1, msg2.data(), len2);  }  state_ = result;}std::string Status::ToString() const {  if (state_ == NULL) {    return "OK";  } else {    char tmp[30];    const char* type;    switch (code()) {      case kOk:        type = "OK";        break;      case kNotFound:        type = "NotFound: ";        break;      case kCorruption:        type = "Corruption: ";        break;      case kNotSupported:        type = "Not implemented: ";        break;      case kInvalidArgument:        type = "Invalid argument: ";        break;      case kIOError:        type = "IO error: ";        break;      default:        snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",                 static_cast<int>(code()));        type = tmp;        break;    }    std::string result(type);    uint32_t length;    memcpy(&length, state_, sizeof(length));    result.append(state_ + 5, length);    return result;  }}}  // namespace leveldb


0 0
原创粉丝点击