hbase 源代码解析(3) 的createTable 服务端解析第二部分

上一节讲到hbaseAdmin 从zk里拿到hbase的地址后建立stub。这个就是master。

http://blog.csdn.net/chenfenggang/article/details/74937508

上一节里面有这个代码

     callable.prepare(tries != 0); // if called with false, check table status on ZK
        interceptor.intercept(context.prepare(callable, tries));
        return callable.call(getTimeout(callTimeout));

*callable.prepare(tries != 0); //准备
interceptor.intercept(context.prepare(callable, tries)); //出现问题时拦截器。重试
return callable.call(getTimeout(callTimeout)); //调用call 这个call被重写了*
所以最终调用master.createTable(controller, request); 进入服务端

CreateTableResponse response = executeCallable(
      new MasterCallable<CreateTableResponse>(getConnection()) {
        @Override
        public CreateTableResponse call(int callTimeout) throws ServiceException {
          PayloadCarryingRpcController controller = rpcControllerFactory.newController();
          controller.setCallTimeout(callTimeout);
          controller.setPriority(desc.getTableName());
          CreateTableRequest request = RequestConverter.buildCreateTableRequest(
            desc, splitKeys, ng.getNonceGroup(), ng.newNonce());
          return master.createTable(controller, request);
        }
      });

进入MasterProtos
然后由MasterRpcServices 解码的请求信息,

@Override
  public CreateTableResponse createTable(RpcController controller, CreateTableRequest req)
  throws ServiceException {
    HTableDescriptor hTableDescriptor = HTableDescriptor.convert(req.getTableSchema());
    byte [][] splitKeys = ProtobufUtil.getSplitKeysArray(req);
    try {
      long procId =
          master.createTable(hTableDescriptor, splitKeys, req.getNonceGroup(), req.getNonce());
      return CreateTableResponse.newBuilder().setProcId(procId).build();
    } catch (IOException ioe) {
      throw new ServiceException(ioe);
    }
  }

然后调用HMaster。
在里面检测命名空间是否有效,check一下sanityCheckTableDescriptor// 然后提交一个submitProcedure 里面重写了run方法。

  return MasterProcedureUtil.submitProcedure(
      new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
      @Override
      protected void run() throws IOException {
        getMaster().getMasterCoprocessorHost().preCreateTable(hTableDescriptor, newRegions);
        LOG.info(getClientIdAuditPrefix() + " create " + hTableDescriptor);
        // TODO: We can handle/merge duplicate requests, and differentiate the case of
        //       TableExistsException by saying if the schema is the same or not.
        ProcedurePrepareLatch latch = ProcedurePrepareLatch.createLatch();
        submitProcedure(new CreateTableProcedure(
          procedureExecutor.getEnvironment(), hTableDescriptor, newRegions, latch));
        latch.await();
        getMaster().getMasterCoprocessorHost().postCreateTable(hTableDescriptor, newRegions);
      }

这里主要是
1)做一点准备
2)锁门
3)杀人
4)开门
5)清除痕迹

现在看看怎么建表的
提交之前做了这些事情:

  // Initialize the procedure
    proc.setNonceKey(nonceKey);
    proc.setProcId(currentProcId.longValue());
    // Commit the transaction
    store.insert(proc, null);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Procedure " + proc + " added to the store.");
    }
    // Create the rollback stack for the procedure
    RootProcedureState stack = new RootProcedureState();
    rollbackStack.put(currentProcId, stack);
    // Submit the new subprocedures
    assert !procedures.containsKey(currentProcId);
    procedures.put(currentProcId, proc);
    sendProcedureAddedNotification(currentProcId);
    runnables.addBack(proc);
    return currentProcId;

1)初始化。
2)写入日志(WAL) store.insert(proc, null);
3)回滚准备
4) 提交。
提交后只要执行execute 你会发现new CreateTableProcedure 这个里面没有execute方法。怎么办找父亲。一个靠爹的时代,爹会帮忙搞定很多事情。 在父类里找到 executeFromState(env, state);

这是个流水线。挺美的一个流水线。上午在公司都是简单步骤。 晚上看的1.3.1的版本。

@Override
  protected Flow executeFromState(final MasterProcedureEnv env, final CreateTableState state)
      throws InterruptedException {
    if (LOG.isTraceEnabled()) {
      LOG.trace(this + " execute state=" + state);
    }
    try {
      switch (state) {
        case CREATE_TABLE_PRE_OPERATION:
          // Verify if we can create the table
          boolean exists = !prepareCreate(env);
          ProcedurePrepareLatch.releaseLatch(syncLatch, this);
          if (exists) {
            assert isFailed() : "the delete should have an exception here";
            return Flow.NO_MORE_STATE;
          }
          preCreate(env);
          setNextState(CreateTableState.CREATE_TABLE_WRITE_FS_LAYOUT);
          break;
        case CREATE_TABLE_WRITE_FS_LAYOUT:
          newRegions = createFsLayout(env, hTableDescriptor, newRegions);
          setNextState(CreateTableState.CREATE_TABLE_ADD_TO_META);
          break;
        case CREATE_TABLE_ADD_TO_META:
          newRegions = addTableToMeta(env, hTableDescriptor, newRegions);
          setNextState(CreateTableState.CREATE_TABLE_ASSIGN_REGIONS);
          break;
        case CREATE_TABLE_ASSIGN_REGIONS:
          assignRegions(env, getTableName(), newRegions);
          setNextState(CreateTableState.CREATE_TABLE_UPDATE_DESC_CACHE);
          break;
        case CREATE_TABLE_UPDATE_DESC_CACHE:
          updateTableDescCache(env, getTableName());
          setNextState(CreateTableState.CREATE_TABLE_POST_OPERATION);
          break;
        case CREATE_TABLE_POST_OPERATION:
          postCreate(env);
          return Flow.NO_MORE_STATE;
        default:
          throw new UnsupportedOperationException("unhandled state=" + state);
      }
    } catch (HBaseException|IOException e) {
      LOG.error("Error trying to create table=" + getTableName() + " state=" + state, e);
      setFailure("master-create-table", e);
    }
    return Flow.HAS_MORE_STATE;
  }

按上面的名字可以看出。主要是
之前)准备,主要是检测合法性。是否存在,是否是系统表,是否disable等
1)FS 表的写region信息到hdfs ,创建的region。
2)写到META表,元数据表。
3)分配region,这里还enable表了,这个代码还点复杂,下节再继续。。。。
4)表描述写入缓存
之后)清除痕迹。。。

下面是1)的中间的代码

 public static HRegion createHRegion(final HRegionInfo info, final Path rootDir,
      final Path tableDir, final Configuration conf, final HTableDescriptor hTableDescriptor,
      final WAL wal, final boolean initialize, final boolean ignoreWAL)
  throws IOException {
    LOG.info("creating HRegion " + info.getTable().getNameAsString()
        + " HTD == " + hTableDescriptor + " RootDir = " + rootDir +
        " Table name == " + info.getTable().getNameAsString());
    FileSystem fs = FileSystem.get(conf);
    HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, info);
    WAL effectiveWAL = wal;
    if (wal == null && !ignoreWAL) {
      // TODO HBASE-11983 There'll be no roller for this wal?
      // The WAL subsystem will use the default rootDir rather than the passed in rootDir
      // unless I pass along via the conf.
      Configuration confForWAL = new Configuration(conf);
      confForWAL.set(HConstants.HBASE_DIR, rootDir.toString());
      effectiveWAL = (new WALFactory(confForWAL,
          Collections.<WALActionsListener>singletonList(new MetricsWAL()),
          "hregion-" + RandomStringUtils.randomNumeric(8))).
            getWAL(info.getEncodedNameAsBytes(), info.getTable().getNamespace());
    }
    HRegion region = HRegion.newHRegion(tableDir,
        effectiveWAL, fs, conf, info, hTableDescriptor, null);
    if (initialize) region.initialize(null);
    return region;
  }

这样一个表的创建过程基本结束。

一个表的创建就把hbase很多功能串联起来了。Hadmin里面还有很多东西,以后看有空在补不。

下个章节讲

case CREATE_TABLE_ASSIGN_REGIONS:
  assignRegions(env, getTableName(), newRegions);

未完待续。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值