Esempio n. 1
0
  void createClient() throws Exception {
    PathBasedZkSerializer zkSerializer =
        ChainedPathZkSerializer.builder(new ZNRecordStreamingSerializer()).build();

    _zkclient =
        new ZkClient(
            _zkAddress, _sessionTimeout, ZkClient.DEFAULT_CONNECTION_TIMEOUT, zkSerializer);

    _baseDataAccessor = createBaseDataAccessor();

    _dataAccessor = new ZKHelixDataAccessor(_clusterName, _instanceType, _baseDataAccessor);
    _configAccessor = new ConfigAccessor(_zkclient);

    int retryCount = 0;

    _zkclient.subscribeStateChanges(this);
    while (retryCount < 3) {
      try {
        _zkclient.waitUntilConnected(_sessionTimeout, TimeUnit.MILLISECONDS);
        handleStateChanged(KeeperState.SyncConnected);
        handleNewSession();
        break;
      } catch (HelixException e) {
        LOG.error("fail to createClient.", e);
        throw e;
      } catch (Exception e) {
        retryCount++;

        LOG.error("fail to createClient. retry " + retryCount, e);
        if (retryCount == 3) {
          throw e;
        }
      }
    }
  }
Esempio n. 2
0
 /** sync remove */
 @Override
 public boolean remove(String path, int options) {
   try {
     // optimize on common path
     _zkClient.delete(path);
   } catch (ZkException e) {
     _zkClient.deleteRecursive(path);
   }
   return true;
 }
Esempio n. 3
0
  /**
   * sync update
   *
   * @return: updatedData on success, or null on fail
   */
  public T update(
      String path, DataUpdater<T> updater, List<String> createPaths, Stat stat, int options) {
    CreateMode mode = AccessOption.getMode(options);
    if (mode == null) {
      LOG.error("Invalid update mode. options: " + options);
      return null;
    }

    boolean retry;
    T updatedData = null;
    do {
      retry = false;
      try {
        Stat readStat = new Stat();
        T oldData = (T) _zkClient.readData(path, readStat);
        T newData = updater.update(oldData);
        Stat setStat = _zkClient.writeDataGetStat(path, newData, readStat.getVersion());
        if (stat != null) {
          DataTree.copyStat(setStat, stat);
        }

        updatedData = newData;
      } catch (ZkBadVersionException e) {
        retry = true;
      } catch (ZkNoNodeException e) {
        // node not exist, try create
        try {
          T newData = updater.update(null);
          RetCode rc = create(path, newData, createPaths, options);
          switch (rc) {
            case OK:
              updatedData = newData;
              break;
            case NODE_EXISTS:
              retry = true;
              break;
            default:
              LOG.error("Fail to update path by creating: " + path);
              return null;
          }
        } catch (Exception e1) {
          LOG.error("Exception while updating path by creating: " + path, e1);
          return null;
        }
      } catch (Exception e) {
        LOG.error("Exception while updating path: " + path, e);
        return null;
      }
    } while (retry);

    return updatedData;
  }
Esempio n. 4
0
  @Override
  public void disconnect() {
    if (_zkclient == null) {
      LOG.info("instanceName: " + _instanceName + " already disconnected");
      return;
    }

    LOG.info("disconnect " + _instanceName + "(" + _instanceType + ") from " + _clusterName);

    try {
      /** stop all timer tasks */
      stopTimerTasks();

      /**
       * shutdown thread pool first to avoid reset() being invoked in the middle of state transition
       */
      _messagingService.getExecutor().shutdown();

      // TODO reset user defined handlers only
      resetHandlers();

      _dataAccessor.shutdown();

      if (_leaderElectionHandler != null) {
        _leaderElectionHandler.reset();
      }

    } finally {
      _zkclient.close();
      _zkclient = null;
      LOG.info("Cluster manager: " + _instanceName + " disconnected");
    }
  }
Esempio n. 5
0
 public boolean offer(T element) {
   try {
     _zkClient.createPersistentSequential(_root + "/" + ELEMENT_NAME + "-", element);
   } catch (Exception e) {
     throw ExceptionUtil.convertToRuntimeException(e);
   }
   return true;
 }
Esempio n. 6
0
 /**
  * sync getChildNames
  *
  * @return null if parentPath doesn't exist
  */
 @Override
 public List<String> getChildNames(String parentPath, int options) {
   try {
     List<String> childNames = _zkClient.getChildren(parentPath);
     Collections.sort(childNames);
     return childNames;
   } catch (ZkNoNodeException e) {
     return null;
   }
 }
Esempio n. 7
0
 /** sync get */
 @Override
 public T get(String path, Stat stat, int options) {
   T data = null;
   try {
     data = (T) _zkClient.readData(path, stat);
   } catch (ZkNoNodeException e) {
     if (AccessOption.isThrowExceptionIfNotExist(options)) {
       throw e;
     }
   }
   return data;
 }
Esempio n. 8
0
 @Override
 public boolean isConnected() {
   if (_zkclient == null) {
     return false;
   }
   ZkConnection zkconnection = (ZkConnection) _zkclient.getConnection();
   if (zkconnection != null) {
     States state = zkconnection.getZookeeperState();
     return state == States.CONNECTED;
   }
   return false;
 }
Esempio n. 9
0
  @SuppressWarnings("unchecked")
  private Element<T> getFirstElement() {
    try {
      while (true) {
        List<String> list = _zkClient.getChildren(_root);
        if (list.size() == 0) {
          return null;
        }
        String elementName = getSmallestElement(list);

        try {
          return new Element<T>(
              _root + "/" + elementName, (T) _zkClient.readData(_root + "/" + elementName));
        } catch (ZkNoNodeException e) {
          // somebody else picked up the element first, so we have to
          // retry with the new first element
        }
      }
    } catch (Exception e) {
      throw ExceptionUtil.convertToRuntimeException(e);
    }
  }
Esempio n. 10
0
  /**
   * wait until we get a non-zero session-id. note that we might lose zkconnection right after we
   * read session-id. but it's ok to get stale session-id and we will have another
   * handle-new-session callback to correct this.
   */
  void waitUntilConnected() {
    boolean isConnected;
    do {
      isConnected =
          _zkclient.waitUntilConnected(ZkClient.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);
      if (!isConnected) {
        LOG.error(
            "fail to connect zkserver: "
                + _zkAddress
                + " in "
                + ZkClient.DEFAULT_CONNECTION_TIMEOUT
                + "ms. expiredSessionId: "
                + _sessionId
                + ", clusterName: "
                + _clusterName);
        continue;
      }

      ZkConnection zkConnection = ((ZkConnection) _zkclient.getConnection());
      _sessionId = Long.toHexString(zkConnection.getZookeeper().getSessionId());

      /**
       * at the time we read session-id, zkconnection might be lost again wait until we get a
       * non-zero session-id
       */
    } while ("0".equals(_sessionId));

    LOG.info(
        "Handling new session, session id: "
            + _sessionId
            + ", instance: "
            + _instanceName
            + ", instanceTye: "
            + _instanceType
            + ", cluster: "
            + _clusterName
            + ", zkconnection: "
            + ((ZkConnection) _zkclient.getConnection()).getZookeeper());
  }
Esempio n. 11
0
  @Override
  public void handleStateChanged(KeeperState state) throws Exception {
    switch (state) {
      case SyncConnected:
        ZkConnection zkConnection = (ZkConnection) _zkclient.getConnection();
        LOG.info("KeeperState: " + state + ", zookeeper:" + zkConnection.getZookeeper());
        break;
      case Disconnected:
        LOG.info(
            "KeeperState:"
                + state
                + ", disconnectedSessionId: "
                + _sessionId
                + ", instance: "
                + _instanceName
                + ", type: "
                + _instanceType);

        /**
         * Track the time stamp that the disconnected happens, then check history and see if we
         * should disconnect the helix-manager
         */
        _disconnectTimeHistory.add(System.currentTimeMillis());
        if (isFlapping()) {
          LOG.error(
              "instanceName: "
                  + _instanceName
                  + " is flapping. diconnect it. "
                  + " maxDisconnectThreshold: "
                  + _maxDisconnectThreshold
                  + " disconnects in "
                  + _flappingTimeWindowMs
                  + "ms.");
          disconnect();
        }
        break;
      case Expired:
        LOG.info(
            "KeeperState:"
                + state
                + ", expiredSessionId: "
                + _sessionId
                + ", instance: "
                + _instanceName
                + ", type: "
                + _instanceType);
        break;
      default:
        break;
    }
  }
Esempio n. 12
0
  /**
   * sync set
   *
   * @param setstat : if node is created instead of set, stat will NOT be set
   */
  public boolean set(
      String path,
      T record,
      List<String> pathsCreated,
      Stat setstat,
      int expectVersion,
      int options) {
    CreateMode mode = AccessOption.getMode(options);
    if (mode == null) {
      LOG.error("Invalid set mode. options: " + options);
      return false;
    }

    boolean retry;
    do {
      retry = false;
      try {
        // _zkClient.writeData(path, record);
        Stat setStat = _zkClient.writeDataGetStat(path, record, expectVersion);
        if (setstat != null) DataTree.copyStat(setStat, setstat);
      } catch (ZkNoNodeException e) {
        // node not exists, try create. in this case, stat will not be set
        try {
          RetCode rc = create(path, record, pathsCreated, options);
          // if (rc == RetCode.OK || rc == RetCode.NODE_EXISTS)
          // retry = true;
          switch (rc) {
            case OK:
              // not set stat if node is created (instead of set)
              break;
            case NODE_EXISTS:
              retry = true;
              break;
            default:
              LOG.error("Fail to set path by creating: " + path);
              return false;
          }
        } catch (Exception e1) {
          LOG.error("Exception while setting path by creating: " + path, e);
          return false;
        }
      } catch (ZkBadVersionException e) {
        throw e;
      } catch (Exception e) {
        LOG.error("Exception while setting path: " + path, e);
        return false;
      }
    } while (retry);

    return true;
  }
Esempio n. 13
0
  public T poll() {
    while (true) {
      Element<T> element = getFirstElement();
      if (element == null) {
        return null;
      }

      try {
        _zkClient.delete(element.getName());
        return element.getData();
      } catch (ZkNoNodeException e) {
        // somebody else picked up the element first, so we have to
        // retry with the new first element
      } catch (Exception e) {
        throw ExceptionUtil.convertToRuntimeException(e);
      }
    }
  }
Esempio n. 14
0
  /** async getStat */
  @Override
  public Stat[] getStats(List<String> paths, int options) {
    if (paths == null || paths.size() == 0) {
      LOG.error("paths is null or empty");
      return new Stat[0];
    }

    Stat[] stats = new Stat[paths.size()];

    long startT = System.nanoTime();

    try {
      ExistsCallbackHandler[] cbList = new ExistsCallbackHandler[paths.size()];
      for (int i = 0; i < paths.size(); i++) {
        String path = paths.get(i);
        cbList[i] = new ExistsCallbackHandler();
        _zkClient.asyncExists(path, cbList[i]);
      }

      for (int i = 0; i < cbList.length; i++) {
        ExistsCallbackHandler cb = cbList[i];
        cb.waitForSuccess();
        stats[i] = cb._stat;
      }

      return stats;
    } finally {
      long endT = System.nanoTime();
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "exists_async, size: "
                + paths.size()
                + ", paths: "
                + paths.get(0)
                + ",... time: "
                + (endT - startT)
                + " ns");
      }
    }
  }
Esempio n. 15
0
  /** async remove */
  @Override
  public boolean[] remove(List<String> paths, int options) {
    if (paths == null || paths.size() == 0) {
      return new boolean[0];
    }

    boolean[] success = new boolean[paths.size()];

    DeleteCallbackHandler[] cbList = new DeleteCallbackHandler[paths.size()];

    long startT = System.nanoTime();

    try {
      for (int i = 0; i < paths.size(); i++) {
        String path = paths.get(i);
        cbList[i] = new DeleteCallbackHandler();
        _zkClient.asyncDelete(path, cbList[i]);
      }

      for (int i = 0; i < cbList.length; i++) {
        DeleteCallbackHandler cb = cbList[i];
        cb.waitForSuccess();
        success[i] = (cb.getRc() == 0);
      }

      return success;
    } finally {
      long endT = System.nanoTime();
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "delete_async, size: "
                + paths.size()
                + ", paths: "
                + paths.get(0)
                + ",... time: "
                + (endT - startT)
                + " ns");
      }
    }
  }
Esempio n. 16
0
  /** sync create */
  public RetCode create(String path, T record, List<String> pathCreated, int options) {
    CreateMode mode = AccessOption.getMode(options);
    if (mode == null) {
      LOG.error("Invalid create mode. options: " + options);
      return RetCode.ERROR;
    }

    boolean retry;
    do {
      retry = false;
      try {
        _zkClient.create(path, record, mode);
        if (pathCreated != null) pathCreated.add(path);

        return RetCode.OK;
      } catch (ZkNoNodeException e) {
        // this will happen if parent node does not exist
        String parentPath = new File(path).getParent();
        try {
          RetCode rc = create(parentPath, null, pathCreated, AccessOption.PERSISTENT);
          if (rc == RetCode.OK || rc == RetCode.NODE_EXISTS) {
            // if parent node created/exists, retry
            retry = true;
          }
        } catch (Exception e1) {
          LOG.error("Exception while creating path: " + parentPath, e1);
          return RetCode.ERROR;
        }
      } catch (ZkNodeExistsException e) {
        LOG.warn("Node already exists. path: " + path);
        return RetCode.NODE_EXISTS;
      } catch (Exception e) {
        LOG.error("Exception while creating path: " + path, e);
        return RetCode.ERROR;
      }
    } while (retry);

    return RetCode.OK;
  }
Esempio n. 17
0
  @Override
  public void process(WatchedEvent event) {
    if (!asnycConnection && event.getState() == Event.KeeperState.SyncConnected) {
      connectionLock.release(); // 连接成功
    } else if (event.getState() == Event.KeeperState.Disconnected) { // 连接断开
      log.warn("zookeeper 连接断开......");
    } else if (event.getState() == Event.KeeperState.Expired) { // 连接超时
      log.warn("zookeeper session timeout......");
      try {
        zkClient.reconnect();
        process.relisten();
        process.recreate();
      } catch (Exception e) {
        log.error("reconnection to zookeeper error.", e);
      }
    }

    if (event.getType() == Event.EventType.NodeChildrenChanged) { // 子节点变化
      process.clientNodeChanged(event.getPath());
    } else if (event.getType() == Event.EventType.NodeDataChanged) { // 节点数据变化
      process.nodeDataChanged(event.getPath());
    }
  }
Esempio n. 18
0
  // simple test
  public static void main(String[] args) {
    ZkClient zkclient = new ZkClient("localhost:2191");
    zkclient.setZkSerializer(new ZNRecordSerializer());
    ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(zkclient);

    // test async create
    List<String> createPaths = Arrays.asList("/test/child1/child1", "/test/child2/child2");
    List<ZNRecord> createRecords = Arrays.asList(new ZNRecord("child1"), new ZNRecord("child2"));

    boolean[] needCreate = new boolean[createPaths.size()];
    Arrays.fill(needCreate, true);
    List<List<String>> pathsCreated =
        new ArrayList<List<String>>(Collections.<List<String>>nCopies(createPaths.size(), null));
    accessor.create(createPaths, createRecords, needCreate, pathsCreated, AccessOption.PERSISTENT);
    System.out.println("pathsCreated: " + pathsCreated);

    // test async set
    List<String> setPaths = Arrays.asList("/test/setChild1/setChild1", "/test/setChild2/setChild2");
    List<ZNRecord> setRecords = Arrays.asList(new ZNRecord("setChild1"), new ZNRecord("setChild2"));

    pathsCreated =
        new ArrayList<List<String>>(Collections.<List<String>>nCopies(setPaths.size(), null));
    boolean[] success =
        accessor.set(setPaths, setRecords, pathsCreated, null, AccessOption.PERSISTENT);
    System.out.println("pathsCreated: " + pathsCreated);
    System.out.println("setSuccess: " + Arrays.toString(success));

    // test async update
    List<String> updatePaths =
        Arrays.asList("/test/updateChild1/updateChild1", "/test/setChild2/setChild2");
    class TestUpdater implements DataUpdater<ZNRecord> {
      final ZNRecord _newData;

      public TestUpdater(ZNRecord newData) {
        _newData = newData;
      }

      @Override
      public ZNRecord update(ZNRecord currentData) {
        return _newData;
      }
    }
    List<DataUpdater<ZNRecord>> updaters =
        Arrays.asList(
            (DataUpdater<ZNRecord>) new TestUpdater(new ZNRecord("updateChild1")),
            (DataUpdater<ZNRecord>) new TestUpdater(new ZNRecord("updateChild2")));

    pathsCreated =
        new ArrayList<List<String>>(Collections.<List<String>>nCopies(updatePaths.size(), null));

    List<ZNRecord> updateRecords =
        accessor.update(updatePaths, updaters, pathsCreated, null, AccessOption.PERSISTENT);
    for (int i = 0; i < updatePaths.size(); i++) {
      success[i] = updateRecords.get(i) != null;
    }
    System.out.println("pathsCreated: " + pathsCreated);
    System.out.println("updateSuccess: " + Arrays.toString(success));

    System.out.println("CLOSING");
    zkclient.close();
  }
Esempio n. 19
0
  /** async get */
  List<T> get(List<String> paths, List<Stat> stats, boolean[] needRead) {
    if (paths == null || paths.size() == 0) {
      return Collections.emptyList();
    }

    // init stats
    if (stats != null) {
      stats.clear();
      stats.addAll(Collections.<Stat>nCopies(paths.size(), null));
    }

    long startT = System.nanoTime();

    try {
      // issue asyn get requests
      GetDataCallbackHandler[] cbList = new GetDataCallbackHandler[paths.size()];
      for (int i = 0; i < paths.size(); i++) {
        if (!needRead[i]) continue;

        String path = paths.get(i);
        cbList[i] = new GetDataCallbackHandler();
        _zkClient.asyncGetData(path, cbList[i]);
      }

      // wait for completion
      for (int i = 0; i < cbList.length; i++) {
        if (!needRead[i]) continue;

        GetDataCallbackHandler cb = cbList[i];
        cb.waitForSuccess();
      }

      // construct return results
      List<T> records = new ArrayList<T>(Collections.<T>nCopies(paths.size(), null));

      for (int i = 0; i < paths.size(); i++) {
        if (!needRead[i]) continue;

        GetDataCallbackHandler cb = cbList[i];
        if (Code.get(cb.getRc()) == Code.OK) {
          @SuppressWarnings("unchecked")
          T record = (T) _zkClient.deserialize(cb._data, paths.get(i));
          records.set(i, record);
          if (stats != null) {
            stats.set(i, cb._stat);
          }
        }
      }

      return records;
    } finally {
      long endT = System.nanoTime();
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "getData_async, size: "
                + paths.size()
                + ", paths: "
                + paths.get(0)
                + ",... time: "
                + (endT - startT)
                + " ns");
      }
    }
  }
Esempio n. 20
0
 /** sync exists */
 @Override
 public boolean exists(String path, int options) {
   return _zkClient.exists(path);
 }
Esempio n. 21
0
 /** sync getStat */
 @Override
 public Stat getStat(String path, int options) {
   return _zkClient.getStat(path);
 }
Esempio n. 22
0
 public boolean isEmpty() {
   return _zkClient.getChildren(_root).size() == 0;
 }
Esempio n. 23
0
  /** async set, give up on error other than NoNode */
  boolean[] set(
      List<String> paths,
      List<T> records,
      List<List<String>> pathsCreated,
      List<Stat> stats,
      int options) {
    if (paths == null || paths.size() == 0) {
      return new boolean[0];
    }

    if ((records != null && records.size() != paths.size())
        || (pathsCreated != null && pathsCreated.size() != paths.size())) {
      throw new IllegalArgumentException("paths, records, and pathsCreated should be of same size");
    }

    boolean[] success = new boolean[paths.size()];

    CreateMode mode = AccessOption.getMode(options);
    if (mode == null) {
      LOG.error("Invalid async set mode. options: " + options);
      return success;
    }

    List<Stat> setStats = new ArrayList<Stat>(Collections.<Stat>nCopies(paths.size(), null));
    SetDataCallbackHandler[] cbList = new SetDataCallbackHandler[paths.size()];
    CreateCallbackHandler[] createCbList = null;
    boolean[] needSet = new boolean[paths.size()];
    Arrays.fill(needSet, true);

    long startT = System.nanoTime();

    try {
      boolean retry;
      do {
        retry = false;

        for (int i = 0; i < paths.size(); i++) {
          if (!needSet[i]) continue;

          String path = paths.get(i);
          T record = records.get(i);
          cbList[i] = new SetDataCallbackHandler();
          _zkClient.asyncSetData(path, record, -1, cbList[i]);
        }

        boolean failOnNoNode = false;

        for (int i = 0; i < cbList.length; i++) {
          SetDataCallbackHandler cb = cbList[i];
          cb.waitForSuccess();
          Code rc = Code.get(cb.getRc());
          switch (rc) {
            case OK:
              setStats.set(i, cb.getStat());
              needSet[i] = false;
              break;
            case NONODE:
              // if fail on NoNode, try create the node
              failOnNoNode = true;
              break;
            default:
              // if fail on error other than NoNode, give up
              needSet[i] = false;
              break;
          }
        }

        // if failOnNoNode, try create
        if (failOnNoNode) {
          boolean[] needCreate = Arrays.copyOf(needSet, needSet.length);
          createCbList = create(paths, records, needCreate, pathsCreated, options);
          for (int i = 0; i < createCbList.length; i++) {
            CreateCallbackHandler createCb = createCbList[i];
            if (createCb == null) {
              continue;
            }

            Code rc = Code.get(createCb.getRc());
            switch (rc) {
              case OK:
                setStats.set(i, ZNode.ZERO_STAT);
                needSet[i] = false;
                break;
              case NODEEXISTS:
                retry = true;
                break;
              default:
                // if creation fails on error other than NodeExists
                // no need to retry set
                needSet[i] = false;
                break;
            }
          }
        }
      } while (retry);

      // construct return results
      for (int i = 0; i < cbList.length; i++) {
        SetDataCallbackHandler cb = cbList[i];

        Code rc = Code.get(cb.getRc());
        if (rc == Code.OK) {
          success[i] = true;
        } else if (rc == Code.NONODE) {
          CreateCallbackHandler createCb = createCbList[i];
          if (Code.get(createCb.getRc()) == Code.OK) {
            success[i] = true;
          }
        }
      }

      if (stats != null) {
        stats.clear();
        stats.addAll(setStats);
      }

      return success;
    } finally {
      long endT = System.nanoTime();
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "setData_async, size: "
                + paths.size()
                + ", paths: "
                + paths.get(0)
                + ",... time: "
                + (endT - startT)
                + " ns");
      }
    }
  }
Esempio n. 24
0
  /** async create. give up on error other than NONODE */
  CreateCallbackHandler[] create(
      List<String> paths,
      List<T> records,
      boolean[] needCreate,
      List<List<String>> pathsCreated,
      int options) {
    if ((records != null && records.size() != paths.size())
        || needCreate.length != paths.size()
        || (pathsCreated != null && pathsCreated.size() != paths.size())) {
      throw new IllegalArgumentException(
          "paths, records, needCreate, and pathsCreated should be of same size");
    }

    CreateCallbackHandler[] cbList = new CreateCallbackHandler[paths.size()];

    CreateMode mode = AccessOption.getMode(options);
    if (mode == null) {
      LOG.error("Invalid async set mode. options: " + options);
      return cbList;
    }

    boolean retry;
    do {
      retry = false;

      for (int i = 0; i < paths.size(); i++) {
        if (!needCreate[i]) continue;

        String path = paths.get(i);
        T record = records == null ? null : records.get(i);
        cbList[i] = new CreateCallbackHandler();
        _zkClient.asyncCreate(path, record, mode, cbList[i]);
      }

      List<String> parentPaths =
          new ArrayList<String>(Collections.<String>nCopies(paths.size(), null));
      boolean failOnNoNode = false;

      for (int i = 0; i < paths.size(); i++) {
        if (!needCreate[i]) continue;

        CreateCallbackHandler cb = cbList[i];
        cb.waitForSuccess();
        String path = paths.get(i);

        if (Code.get(cb.getRc()) == Code.NONODE) {
          String parentPath = new File(path).getParent();
          parentPaths.set(i, parentPath);
          failOnNoNode = true;
        } else {
          // if create succeed or fail on error other than NONODE,
          // give up
          needCreate[i] = false;

          // if succeeds, record what paths we've created
          if (Code.get(cb.getRc()) == Code.OK && pathsCreated != null) {
            if (pathsCreated.get(i) == null) {
              pathsCreated.set(i, new ArrayList<String>());
            }
            pathsCreated.get(i).add(path);
          }
        }
      }

      if (failOnNoNode) {
        boolean[] needCreateParent = Arrays.copyOf(needCreate, needCreate.length);

        CreateCallbackHandler[] parentCbList =
            create(parentPaths, null, needCreateParent, pathsCreated, AccessOption.PERSISTENT);
        for (int i = 0; i < parentCbList.length; i++) {
          CreateCallbackHandler parentCb = parentCbList[i];
          if (parentCb == null) continue;

          Code rc = Code.get(parentCb.getRc());

          // if parent is created, retry create child
          if (rc == Code.OK || rc == Code.NODEEXISTS) {
            retry = true;
            break;
          }
        }
      }
    } while (retry);

    return cbList;
  }
Esempio n. 25
0
  /**
   * async update
   *
   * <p>return: updatedData on success or null on fail
   */
  List<T> update(
      List<String> paths,
      List<DataUpdater<T>> updaters,
      List<List<String>> pathsCreated,
      List<Stat> stats,
      int options) {
    if (paths == null || paths.size() == 0) {
      LOG.error("paths is null or empty");
      return Collections.emptyList();
    }

    if (updaters.size() != paths.size()
        || (pathsCreated != null && pathsCreated.size() != paths.size())) {
      throw new IllegalArgumentException(
          "paths, updaters, and pathsCreated should be of same size");
    }

    List<Stat> setStats = new ArrayList<Stat>(Collections.<Stat>nCopies(paths.size(), null));
    List<T> updateData = new ArrayList<T>(Collections.<T>nCopies(paths.size(), null));

    CreateMode mode = AccessOption.getMode(options);
    if (mode == null) {
      LOG.error("Invalid update mode. options: " + options);
      return updateData;
    }

    SetDataCallbackHandler[] cbList = new SetDataCallbackHandler[paths.size()];
    CreateCallbackHandler[] createCbList = null;
    boolean[] needUpdate = new boolean[paths.size()];
    Arrays.fill(needUpdate, true);

    long startT = System.nanoTime();

    try {
      boolean retry;
      do {
        retry = false;
        boolean[] needCreate = new boolean[paths.size()]; // init'ed with false
        boolean failOnNoNode = false;

        // asycn read all data
        List<Stat> curStats = new ArrayList<Stat>();
        List<T> curDataList = get(paths, curStats, Arrays.copyOf(needUpdate, needUpdate.length));

        // async update
        List<T> newDataList = new ArrayList<T>();
        for (int i = 0; i < paths.size(); i++) {
          if (!needUpdate[i]) {
            newDataList.add(null);
            continue;
          }
          String path = paths.get(i);
          DataUpdater<T> updater = updaters.get(i);
          T newData = updater.update(curDataList.get(i));
          newDataList.add(newData);
          Stat curStat = curStats.get(i);
          if (curStat == null) {
            // node not exists
            failOnNoNode = true;
            needCreate[i] = true;
          } else {
            cbList[i] = new SetDataCallbackHandler();
            _zkClient.asyncSetData(path, newData, curStat.getVersion(), cbList[i]);
          }
        }

        // wait for completion
        boolean failOnBadVersion = false;

        for (int i = 0; i < paths.size(); i++) {
          SetDataCallbackHandler cb = cbList[i];
          if (cb == null) continue;

          cb.waitForSuccess();

          switch (Code.get(cb.getRc())) {
            case OK:
              updateData.set(i, newDataList.get(i));
              setStats.set(i, cb.getStat());
              needUpdate[i] = false;
              break;
            case NONODE:
              failOnNoNode = true;
              needCreate[i] = true;
              break;
            case BADVERSION:
              failOnBadVersion = true;
              break;
            default:
              // if fail on error other than NoNode or BadVersion
              // will not retry
              needUpdate[i] = false;
              break;
          }
        }

        // if failOnNoNode, try create
        if (failOnNoNode) {
          createCbList = create(paths, newDataList, needCreate, pathsCreated, options);
          for (int i = 0; i < paths.size(); i++) {
            CreateCallbackHandler createCb = createCbList[i];
            if (createCb == null) {
              continue;
            }

            switch (Code.get(createCb.getRc())) {
              case OK:
                needUpdate[i] = false;
                updateData.set(i, newDataList.get(i));
                setStats.set(i, ZNode.ZERO_STAT);
                break;
              case NODEEXISTS:
                retry = true;
                break;
              default:
                // if fail on error other than NodeExists
                // will not retry
                needUpdate[i] = false;
                break;
            }
          }
        }

        // if failOnBadVersion, retry
        if (failOnBadVersion) {
          retry = true;
        }
      } while (retry);

      if (stats != null) {
        stats.clear();
        stats.addAll(setStats);
      }

      return updateData;
    } finally {
      long endT = System.nanoTime();
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "setData_async, size: "
                + paths.size()
                + ", paths: "
                + paths.get(0)
                + ",... time: "
                + (endT - startT)
                + " ns");
      }
    }
  }
Esempio n. 26
0
 /** Unsubscrie to zookeeper data changes */
 @Override
 public void unsubscribeChildChanges(String path, IZkChildListener childListener) {
   _zkClient.unsubscribeChildChanges(path, childListener);
 }
Esempio n. 27
0
 /** Subscrie to zookeeper data changes */
 @Override
 public List<String> subscribeChildChanges(String path, IZkChildListener listener) {
   return _zkClient.subscribeChildChanges(path, listener);
 }
Esempio n. 28
0
 /** Unsubscribe to zookeeper data changes */
 @Override
 public void unsubscribeDataChanges(String path, IZkDataListener dataListener) {
   _zkClient.unsubscribeDataChanges(path, dataListener);
 }
Esempio n. 29
0
 /** Subscribe to zookeeper data changes */
 @Override
 public void subscribeDataChanges(String path, IZkDataListener listener) {
   _zkClient.subscribeDataChanges(path, listener);
 }
Esempio n. 30
0
  @Test
  public void testAsyncZkBaseDataAccessor() {
    System.out.println(
        "START TestZkBaseDataAccessor.async at " + new Date(System.currentTimeMillis()));

    String root = "TestZkBaseDataAccessor_asyn";
    ZkClient zkClient = new ZkClient(ZK_ADDR);
    zkClient.setZkSerializer(new ZNRecordSerializer());
    zkClient.deleteRecursive("/" + root);

    ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(zkClient);

    // test async createChildren
    String parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1");
    List<ZNRecord> records = new ArrayList<ZNRecord>();
    List<String> paths = new ArrayList<String>();
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId));
      records.add(new ZNRecord(msgId));
    }
    boolean[] success = accessor.createChildren(paths, records, AccessOption.PERSISTENT);
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      Assert.assertTrue(success[i], "Should succeed in create " + msgId);
    }

    // test get what we created
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId);
      ZNRecord record = zkClient.readData(path);
      Assert.assertEquals(record.getId(), msgId, "Should get what we created");
    }

    // test async setChildren
    parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1");
    records = new ArrayList<ZNRecord>();
    paths = new ArrayList<String>();
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId));
      ZNRecord newRecord = new ZNRecord(msgId);
      newRecord.setSimpleField("key1", "value1");
      records.add(newRecord);
    }
    success = accessor.setChildren(paths, records, AccessOption.PERSISTENT);
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      Assert.assertTrue(success[i], "Should succeed in set " + msgId);
    }

    // test get what we set
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId);
      ZNRecord record = zkClient.readData(path);
      Assert.assertEquals(record.getSimpleFields().size(), 1, "Should have 1 simple field set");
      Assert.assertEquals(record.getSimpleField("key1"), "value1", "Should have value1 set");
    }

    // test async updateChildren
    parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1");
    // records = new ArrayList<ZNRecord>();
    List<DataUpdater<ZNRecord>> znrecordUpdaters = new ArrayList<DataUpdater<ZNRecord>>();
    paths = new ArrayList<String>();
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId));
      ZNRecord newRecord = new ZNRecord(msgId);
      newRecord.setSimpleField("key2", "value2");
      // records.add(newRecord);
      znrecordUpdaters.add(new ZNRecordUpdater(newRecord));
    }
    success = accessor.updateChildren(paths, znrecordUpdaters, AccessOption.PERSISTENT);
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      Assert.assertTrue(success[i], "Should succeed in update " + msgId);
    }

    // test get what we updated
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId);
      ZNRecord record = zkClient.readData(path);
      Assert.assertEquals(record.getSimpleFields().size(), 2, "Should have 2 simple fields set");
      Assert.assertEquals(record.getSimpleField("key2"), "value2", "Should have value2 set");
    }

    // test async getChildren
    parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1");
    records = accessor.getChildren(parentPath, null, 0);
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      ZNRecord record = records.get(i);
      Assert.assertEquals(record.getId(), msgId, "Should get what we updated");
      Assert.assertEquals(record.getSimpleFields().size(), 2, "Should have 2 simple fields set");
      Assert.assertEquals(record.getSimpleField("key2"), "value2", "Should have value2 set");
    }

    // test async exists
    parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1");
    paths = new ArrayList<String>();
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId));
    }
    boolean[] exists = accessor.exists(paths, 0);
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      Assert.assertTrue(exists[i], "Should exist " + msgId);
    }

    // test async getStats
    parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1");
    paths = new ArrayList<String>();
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId));
    }
    Stat[] stats = accessor.getStats(paths, 0);
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      Assert.assertNotNull(stats[i], "Stat should exist for " + msgId);
      Assert.assertEquals(
          stats[i].getVersion(),
          2,
          "DataVersion should be 2, since we set 1 and update 1 for " + msgId);
    }

    // test async remove
    parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1");
    paths = new ArrayList<String>();
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId));
    }
    success = accessor.remove(paths, 0);
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      Assert.assertTrue(success[i], "Should succeed in remove " + msgId);
    }

    // test get what we removed
    for (int i = 0; i < 10; i++) {
      String msgId = "msg_" + i;
      String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId);
      boolean pathExists = zkClient.exists(path);
      Assert.assertFalse(pathExists, "Should be removed " + msgId);
    }

    zkClient.close();
    System.out.println(
        "END TestZkBaseDataAccessor.async at " + new Date(System.currentTimeMillis()));
  }