閱讀483 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[leveldb] 學習leveldb第一個類Status

[TOC]

回顧上一篇文章《[leveldb] 初步探索 leveldb》的樣例代碼,是不是發現有個類比例簡單:leveldb::Status,你發現它有status.ok()status.ToString()方法。那怎麼找到Status類的定義和成員方法的實現呢?

1、 第一步:把相關代碼找出來

1-1 用grep 大法過濾內容

我們知道C++的類一般是這樣定義的:class Status {...},我們grep在當前目前遞歸-r .全詞匹配-w和半詞匹配都搜不到,最後grep "Status {"出來了,並顯示代碼所在行數-n

wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "class Status" -rnw .
wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "class Status" -rn .
wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "Status{" -rn .
wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "Status {" -rn .
./include/leveldb/status.h:22:class LEVELDB_EXPORT Status {
wu_being@UbuntuKylin1704:~/Github/leveldb$ 

這個就是Status類定義的頭文件:

./include/leveldb/status.h:22:class LEVELDB_EXPORT Status {

1-2 用find 大法找到文件

我們發現上麵grep大法連文件名都過濾出來,下麵用find大法通過文件名匹配到相關文件,找到一個Status類方法實現的文件./util/status.cc

wu_being@UbuntuKylin1704:~/Github/leveldb$ 
wu_being@UbuntuKylin1704:~/Github/leveldb$ find . -name status.
./util/status.cc
./util/status.o
./out-static/util/status.o
./include/leveldb/status.h
./out-shared/util/status.o
wu_being@UbuntuKylin1704:~/Github/leveldb$ 

2、 第二步:RTFSC (Read the fucking source code )

wu_being@UbuntuKylin1704:~/Github/leveldb$ 
wu_being@UbuntuKylin1704:~/Github/leveldb$ gedit include/leveldb/status.h &
[2] 3936
wu_being@UbuntuKylin1704:~/Github/leveldb$ gedit util/status.cc 
[2]+  已完成               gedit include/leveldb/status.h
wu_being@UbuntuKylin1704:~/Github/leveldb$ 

2-1 include/leveldb/status.h

#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_
#define STORAGE_LEVELDB_INCLUDE_STATUS_H_

#include <string>
#include "leveldb/export.h"
#include "leveldb/slice.h"

namespace leveldb {

class LEVELDB_EXPORT 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);
  }
...

  // 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; }
...

  // Return a string representation of this status suitable for printing.
  // Returns the string "OK" for success.
  // status.cc
  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
  //    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.cc
  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_) {
    delete[] state_;
    state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
  }
}

}  // namespace leveldb

#endif  // STORAGE_LEVELDB_INCLUDE_STATUS_H_

2-1-1 類Status公有成員變量和方法

構造函數

 public:
  // Create a success status.
  Status() : state_(NULL) { }

  // Copy the specified status.
  Status(const Status& s);
  void operator=(const Status& 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_) {
    delete[] state_;
    state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
  }
}

析構函數

  ~Status() { delete[] state_; }

2-1-2 類Status私有成員變量和方法

私有成員變量

下麵這個state_設計很不好調試,在後麵的CopyState方法就是了,沒有手工調試配製state_。

 // OK status has a NULL state_.  Otherwise, state_ is a new[] array
  // of the following form:
  //    state_[0..3] == length of message
  //    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.cc
  Status(Code code, const Slice& msg, const Slice& msg2);
  static const char CopyState(const char s);

2-2 util/status.cc


#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));

  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;
...
      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

Status::CopyState

 // OK status has a NULL state_.  Otherwise, state_ is a new[] array
  // of the following form:
  //    state_[0..3] == length of message
  //    state_[4]    == code
  //    state_[5..]  == message

const char Status::CopyState(const char state) {
  uint32_t size; //sizeof(size)為4
  memcpy(&size, state, sizeof(size));//把state前麵4個length of message字符給size

  char* result = new char[size + 5]; 
  memcpy(result, state, size + 5);

  return result;
}

Status::ToString() const


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;
...
      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;
  }
}

私有構造函數

Status::Status

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;
}

Wu_Being博客聲明:本人博客歡迎轉載,請標明博客原文和原鏈接!謝謝!
《[leveldb] 學習leveldb第一個類Status》: https://yq.aliyun.com/articles/241407/

Wu_Being 吳兵博客接受讚助費二維碼

如果你看完這篇博文,覺得對你有幫助,並且願意付讚助費,那麼我會更有動力寫下去。

最後更新:2017-11-13 19:34:04

  上一篇:go  為什麼雲計算需要虛擬化,睿雲智合(Wise2C)的說法
  下一篇:go  nest係列-event事件總線