public int start() throws RemoteException {
    try {
      File logF = new File(logFile);
      FileWriter fw = new FileWriter(logF.getAbsoluteFile(), true);
      bw = new BufferedWriter(fw);
      bw.write(Integer.toString(xidCounter));
      bw.write(" started\n");
      bw.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

    enlistList.put(xidCounter, new HashSet<ResourceManager>());
    protocolDB.put(xidCounter, new HashMap<String, TwoPC_ST>());
    return xidCounter++;
  }
  public boolean commit(int xid)
      throws RemoteException, TransactionAbortedException, InvalidTransactionException {
    System.out.println("TM starts to commit " + xid);
    if (!xidIsValid(xid)) {
      File f = new File(logFile);
      if (f.exists()) throw new TransactionAbortedException(xid, "");
      else throw new InvalidTransactionException(xid, "");
    }
    if (!enlistList.containsKey(xid)) {
      throw new TransactionAbortedException(xid, "Nonexist xid for TM.");
    }

    Set<ResourceManager> commitSet = enlistList.get(xid);
    System.out.println(xid + " TM commitSet size: " + commitSet.size());
    ResourceManager rm = null;
    Iterator<ResourceManager> i = commitSet.iterator();
    try {
      while (i.hasNext()) {
        rm = i.next();
        rm.vote(xid, TwoPC_ST.Prepared);
        rm.getMyRMIName();
        System.out.println(rm.getMyRMIName() + " in TM commit " + xid);
      }
    } catch (Exception e) {
      System.out.println("When vote, there is an exception");
      enlistList.get(xid).remove(rm);
      abort(xid);
      throw new TransactionAbortedException(xid, "invalid rm");
    }

    if (dieTMBeforeCommit) dieNow();

    // log "committed" here, and enlistList
    try {
      File logF = new File(logFile);
      FileWriter fw = new FileWriter(logF.getAbsoluteFile(), true);
      bw = new BufferedWriter(fw);
      bw.write(Integer.toString(xid));
      bw.write(" committed\n");
      bw.close();

      ObjectOutputStream protocolDBBackup =
          new ObjectOutputStream(new FileOutputStream(protocolDBFile));
      protocolDBBackup.writeObject(protocolDB);
      protocolDBBackup.close();

      ObjectOutputStream enlistFileBackup =
          new ObjectOutputStream(new FileOutputStream(enlistFile));
      enlistFileBackup.writeObject(enlistList);
      enlistFileBackup.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

    if (dieTMAfterCommit) dieNow();
    for (ResourceManager r : commitSet) {
      r.commit(xid);
    }
    protocolDB.remove(xid);
    enlistList.remove(xid);
    try {
      ObjectOutputStream protocolDBBackup =
          new ObjectOutputStream(new FileOutputStream(protocolDBFile));
      protocolDBBackup.writeObject(protocolDB);
      protocolDBBackup.close(); // enlistFile

      ObjectOutputStream enlistFileBackup =
          new ObjectOutputStream(new FileOutputStream(enlistFile));
      enlistFileBackup.writeObject(enlistList);
      enlistFileBackup.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return true;
  }