コード例 #1
0
ファイル: compact_block.cpp プロジェクト: 0huah0/tfs
    int CompactBlock::real_compact(LogicBlock* src, LogicBlock* dest)
    {
      assert(NULL != src && NULL != dest);

      BlockInfo dest_blk;
      BlockInfo* src_blk = src->get_block_info();
      dest_blk.block_id_ = src_blk->block_id_;
      dest_blk.seq_no_ = src_blk->seq_no_;
      dest_blk.version_ = src_blk->version_;
      dest_blk.file_count_ = 0;
      dest_blk.size_ = 0;
      dest_blk.del_file_count_ = 0;
      dest_blk.del_size_ = 0;

      dest->set_last_update(time(NULL));
      TBSYS_LOG(DEBUG, "compact block set last update. blockid: %u\n", dest->get_logic_block_id());

      char* dest_buf = new char[MAX_COMPACT_READ_SIZE];
      int32_t write_offset = 0, data_len = 0;
      int32_t w_file_offset = 0;
      RawMetaVec dest_metas;
      FileIterator* fit = new FileIterator(src);

      int ret = TFS_SUCCESS;
      while (fit->has_next())
      {
        ret = fit->next();
        if (TFS_SUCCESS != ret)
        {
          tbsys::gDeleteA(dest_buf);
          tbsys::gDelete(fit);
          return ret;
        }

        const FileInfo* pfinfo = fit->current_file_info();
        if (pfinfo->flag_ & (FI_DELETED | FI_INVALID))
        {
          continue;
        }

        FileInfo dfinfo = *pfinfo;
        dfinfo.offset_ = w_file_offset;
        // the size returned by FileIterator.current_file_info->size is
        // the size of file content!!!
        dfinfo.size_ = pfinfo->size_ + sizeof(FileInfo);
        dfinfo.usize_ = pfinfo->size_ + sizeof(FileInfo);
        w_file_offset += dfinfo.size_;

        dest_blk.file_count_++;
        dest_blk.size_ += dfinfo.size_;

        RawMeta tmp_meta;
        tmp_meta.set_file_id(dfinfo.id_);
        tmp_meta.set_size(dfinfo.size_);
        tmp_meta.set_offset(dfinfo.offset_);
        dest_metas.push_back(tmp_meta);

        // need flush write buffer
        if ((0 != data_len) && (fit->is_big_file() || data_len + dfinfo.size_ > MAX_COMPACT_READ_SIZE))
        {
          TBSYS_LOG(DEBUG, "write one, blockid: %u, write offset: %d\n", dest->get_logic_block_id(),
              write_offset);
          ret = dest->write_raw_data(dest_buf, data_len, write_offset);
          if (TFS_SUCCESS != ret)
          {
            TBSYS_LOG(ERROR, "write raw data fail, blockid: %u, offset %d, readinglen: %d, ret :%d",
                dest->get_logic_block_id(), write_offset, data_len, ret);
            tbsys::gDeleteA(dest_buf);
            tbsys::gDelete(fit);
            return ret;
          }
          write_offset += data_len;
          data_len = 0;
        }

        if (fit->is_big_file())
        {
          ret = write_big_file(src, dest, *pfinfo, dfinfo, write_offset);
          write_offset += dfinfo.size_;
        }
        else
        {
          memcpy(dest_buf + data_len, &dfinfo, sizeof(FileInfo));
          int left_len = MAX_COMPACT_READ_SIZE - data_len;
          ret = fit->read_buffer(dest_buf + data_len + sizeof(FileInfo), left_len);
          data_len += dfinfo.size_;
        }
        if (TFS_SUCCESS != ret)
        {
          tbsys::gDeleteA(dest_buf);
          tbsys::gDelete(fit);
          return ret;
        }

      } // end of iterate

      if (0 != data_len) // flush the last buffer
      {
        TBSYS_LOG(DEBUG, "write one, blockid: %u, write offset: %d\n", dest->get_logic_block_id(), write_offset);
        ret = dest->write_raw_data(dest_buf, data_len, write_offset);
        if (TFS_SUCCESS != ret)
        {
          TBSYS_LOG(ERROR, "write raw data fail, blockid: %u, offset %d, readinglen: %d, ret :%d",
              dest->get_logic_block_id(), write_offset, data_len, ret);
          tbsys::gDeleteA(dest_buf);
          tbsys::gDelete(fit);
          return ret;
        }
      }

      tbsys::gDeleteA(dest_buf);
      tbsys::gDelete(fit);
      TBSYS_LOG(DEBUG, "compact write complete. blockid: %u\n", dest->get_logic_block_id());

      ret = dest->batch_write_meta(&dest_blk, &dest_metas);
      if (TFS_SUCCESS != ret)
      {
        TBSYS_LOG(ERROR, "compact write segment meta failed. blockid: %u, meta size %zd\n", dest->get_logic_block_id(),
            dest_metas.size());
        return ret;
      }

      TBSYS_LOG(DEBUG, "compact set dirty flag. blockid: %u\n", dest->get_logic_block_id());
      ret = dest->set_block_dirty_type(C_DATA_CLEAN);
      if (TFS_SUCCESS != ret)
      {
        TBSYS_LOG(ERROR, "compact blockid: %u set dirty flag fail. ret: %d\n", dest->get_logic_block_id(), ret);
        return ret;
      }

      return TFS_SUCCESS;
    }