public void clear() {
    // int size=0;

    // remove all timed out conns
    try {
      Object[] arr = dcs.entrySet().toArray();
      if (ArrayUtil.isEmpty(arr)) return;
      for (int i = 0; i < arr.length; i++) {
        DCStack conns = (DCStack) ((Map.Entry) arr[i]).getValue();
        if (conns != null) conns.clear();
        // size+=conns.size();
      }
    } catch (Throwable t) {
    }
  }
  public void remove(DataSource datasource) {
    Object[] arr = dcs.keySet().toArray();
    String key, id = createId(datasource);
    for (int i = 0; i < arr.length; i++) {
      key = (String) arr[i];
      if (key.startsWith(id)) {
        DCStack conns = dcs.get(key);
        conns.clear();
      }
    }

    RefInteger ri = counter.get(id);
    if (ri != null) ri.setValue(0);
    else counter.put(id, new RefIntegerSync(0));
  }
  public void releaseDatasourceConnection(DatasourceConnection dc, boolean closeIt) {
    if (dc == null) return;
    DCStack stack = getDCStack(dc.getDatasource(), dc.getUsername(), dc.getPassword());
    synchronized (stack) {
      if (closeIt) IOUtil.closeEL(dc.getConnection());
      else stack.add(dc);
      int max = dc.getDatasource().getConnectionLimit();

      if (max != -1) {
        _dec(dc.getDatasource());
        stack.notify();

      } else _dec(dc.getDatasource());
    }
  }
  public DatasourceConnection getDatasourceConnection(
      DataSource datasource, String user, String pass) throws PageException {
    // pc=ThreadLocalPageContext.get(pc);
    if (StringUtil.isEmpty(user)) {
      user = datasource.getUsername();
      pass = datasource.getPassword();
    }
    if (pass == null) pass = "";

    // get stack
    DCStack stack = getDCStack(datasource, user, pass);

    // max connection
    int max = datasource.getConnectionLimit();
    synchronized (stack) {
      while (max != -1 && max <= _size(datasource)) {
        try {
          // stack.inc();
          stack.wait(10000L);

        } catch (InterruptedException e) {
          throw Caster.toPageException(e);
        }
      }

      while (!stack.isEmpty()) {
        DatasourceConnectionImpl dc = (DatasourceConnectionImpl) stack.get();
        if (dc != null && isValid(dc, Boolean.TRUE)) {
          _inc(datasource);
          return dc.using();
        }
      }
      _inc(datasource);
    }
    return loadDatasourceConnection(datasource, user, pass).using();
  }