leveldb 02 status学习

学习了 巴山独钓 的levelDB源码分析-Status
1. 主要的声明和inline定义(隐式inline和利用显式inline关键字定义)都放在了status.h文件中。 只有CopyState,Status和ToString这3个代码比较多和复杂一些的函数放在了status.cc文件中去定义。
2. 发现leveldb中的显式inline都是采用如下形式定义在.h文件中。 我自己的话一般会在声明的同时显式inline定义,以后要学习leveldb中的用法,毕竟把声明和定义分离开更加清晰。 至于隐式inline的,那是因为定义式的代码本来就1-2行,声明式和定义式放一起也不影响清晰性。

inline Status::Status(const Status& s) {
  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}


3. status类主要是封装了一个数组const char* state_; 至于这个变长数组的定义格式,源码注释写的很清楚,前4字节是长度,第5字节是错误code,第6字节以后是message。 错误code使用了enum进行了声明。总计是6种,名字都是k打头,这是谷歌规范里面的规定的,静态常量以k打头。

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


4. 由于state_的格式是固定的,所以像code()函数,也就是获取status对象的code码,可以直接取state_ 的第5个元素。

  Code code() const {
    return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
  }


5. 分析下 函数CopyState,也是利用state_的格式是已知的固定格式,来取得数据长度,进行mycpy的。

const char* Status::CopyState(const char* state) {
  uint32_t size;  //message的长度
  memcpy(&size, state, sizeof(size)); //state的前4字节正好是表示message长度的。
  char* result = new char[size + 5]; //state的长度是前面5个固定字节,再加上message的长度。 用此长度new出来数组。
  memcpy(result, state, size + 5); //将state的内容取size+5也就是总长度,copy到新new出来的数组result里
  return result;
}


6. 分析下构造函数Status,也是利用固定格式的state_

Status::Status(Code code, const Slice& msg, const Slice& msg2) {
  assert(code != kOk);  //如果是kOk,直接就是个空对象嘛。
  const uint32_t len1 = msg.size(); //用到的第一个msg的长度
  const uint32_t len2 = msg2.size();//用到的第二个msg的长度
  const uint32_t size = len1 + (len2 ? (2 + len2) : 0);//总长度是len1+len2+2,原因是msg和msg2之间要用:加上空格符号隔开。 这里做了个?:判断选择,如果len2是0的话,size直接就是len1了。
  char* result = new char[size + 5];// size是新message的长度,还要加上5个字节的固定长度。  其中前4个字节是表示新message有多长的,第5个字节表示code码是啥的。
  memcpy(result, &size, sizeof(size)); //前4个字节是表示新message多长的,直接用memcpy效率高啊。
  result[4] = static_cast<char>(code);//第5个字节放置表示code嘛是啥的,这里把enum转换成了char类型。
  memcpy(result + 5, msg.data(), len1); //先copy第一个msg到新message的内存里
  if (len2) {
    result[5 + len1] = ':';  //第一个msg后加:符号
    result[6 + len1] = ' ';  //然后再加空格符号
    memcpy(result + 7 + len1, msg2.data(), len2); //最后把msg2整个copy到新message里。 注意这里的指针已经是result+7+len1了, 7是:符号加上空格符号,加上新messag的前5个固定字节。
  }
  state_ = result;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值