示例#1
0
  private Database readWinnersDatabase(Branch winnersApplyBranch, List<File> remoteDatabases)
      throws IOException {
    // Make map 'short filename' -> 'full filename'
    Map<String, File> shortFilenameToFileMap = new HashMap<String, File>();

    for (File remoteDatabase : remoteDatabases) {
      shortFilenameToFileMap.put(remoteDatabase.getName(), remoteDatabase);
    }

    // Load individual databases for branch ranges
    DatabaseDAO databaseDAO = new XmlDatabaseDAO(config.getTransformer());
    Database winnerBranchDatabase =
        new Database(); // Database cannot be reused, since these might be different clients

    String clientName = null;
    VectorClock clientVersionFrom = null;
    VectorClock clientVersionTo = null;

    for (DatabaseVersionHeader databaseVersionHeader : winnersApplyBranch.getAll()) {
      // First of range for this client
      if (clientName == null || !clientName.equals(databaseVersionHeader.getClient())) {
        clientName = databaseVersionHeader.getClient();
        clientVersionFrom = databaseVersionHeader.getVectorClock();
        clientVersionTo = databaseVersionHeader.getVectorClock();
      }

      // Still in range for this client
      else if (clientName.equals(databaseVersionHeader.getClient())) {
        clientVersionTo = databaseVersionHeader.getVectorClock();
      }

      String potentialDatabaseShortFileNameForRange =
          "db-" + clientName + "-" + clientVersionTo.get(clientName); // TODO [medium] Naming stuff
      File databaseFileForRange =
          shortFilenameToFileMap.get(potentialDatabaseShortFileNameForRange);

      if (databaseFileForRange != null) {
        // Load database
        logger.log(
            Level.INFO,
            "- Loading "
                + databaseFileForRange
                + " (from "
                + clientVersionFrom
                + ", to "
                + clientVersionTo
                + ") ...");
        databaseDAO.load(
            winnerBranchDatabase, databaseFileForRange, clientVersionFrom, clientVersionTo);

        // Reset range
        clientName = null;
        clientVersionFrom = null;
        clientVersionTo = null;
      }
    }

    return winnerBranchDatabase;
  }
示例#2
0
  private void applyWinnersBranch(Branch winnersBranch, List<File> unknownRemoteDatabasesInCache)
      throws Exception {
    Branch winnersApplyBranch =
        databaseReconciliator.findWinnersApplyBranch(localBranch, winnersBranch);
    logger.log(Level.INFO, "- Database versions to APPLY locally: " + winnersApplyBranch);

    if (winnersApplyBranch.size() == 0) {
      logger.log(Level.WARNING, "  + Nothing to update. Nice!");
      result.setResultCode(DownResultCode.OK_NO_REMOTE_CHANGES);
    } else {
      logger.log(Level.INFO, "- Loading winners database ...");
      Database winnersDatabase =
          readWinnersDatabase(winnersApplyBranch, unknownRemoteDatabasesInCache);

      FileSystemActionReconciliator actionReconciliator =
          new FileSystemActionReconciliator(config, localDatabase, result);
      List<FileSystemAction> actions =
          actionReconciliator.determineFileSystemActions(winnersDatabase);

      Set<MultiChunkEntry> unknownMultiChunks =
          determineRequiredMultiChunks(actions, winnersDatabase);
      downloadAndDecryptMultiChunks(unknownMultiChunks);

      applyFileSystemActions(actions);

      // Add winners database to local database
      // Note: This must happen AFTER the file system stuff, because we compare the winners database
      // with the local database!
      for (DatabaseVersionHeader applyDatabaseVersionHeader : winnersApplyBranch.getAll()) {
        logger.log(
            Level.INFO,
            "   + Applying database version " + applyDatabaseVersionHeader.getVectorClock());

        DatabaseVersion applyDatabaseVersion =
            winnersDatabase.getDatabaseVersion(applyDatabaseVersionHeader.getVectorClock());
        localDatabase.addDatabaseVersion(applyDatabaseVersion);
      }

      logger.log(Level.INFO, "- Saving local database to " + config.getDatabaseFile() + " ...");
      saveLocalDatabase(localDatabase, config.getDatabaseFile());

      result.setResultCode(DownResultCode.OK_WITH_REMOTE_CHANGES);
    }
  }
示例#3
0
  public static DatabaseVersionHeader createFromString(String databaseVersionHeaderString)
      throws Exception {
    Matcher databaseVersionHeaderMatcher =
        databaseVersionHeaderPattern.matcher(databaseVersionHeaderString);

    if (!databaseVersionHeaderMatcher.matches()) {
      throw new Exception("Invalid database version header string: " + databaseVersionHeaderString);
    }

    String client = databaseVersionHeaderMatcher.group(1);
    String vectorClockString = databaseVersionHeaderMatcher.group(2);
    long databaseVersionHeaderTime = Long.parseLong(databaseVersionHeaderMatcher.group(3));

    VectorClock vectorClock = createVectorClock(vectorClockString);

    DatabaseVersionHeader newDatabaseVersionHeader = new DatabaseVersionHeader();

    newDatabaseVersionHeader.setDate(new Date(databaseVersionHeaderTime));
    newDatabaseVersionHeader.setVectorClock(vectorClock);
    newDatabaseVersionHeader.setClient(client);

    return newDatabaseVersionHeader;
  }
示例#4
0
  private void pruneConflictingLocalBranch(Branch winnersBranch) throws Exception {
    Branch localPruneBranch =
        databaseReconciliator.findLosersPruneBranch(localBranch, winnersBranch);
    logger.log(Level.INFO, "- Database versions to REMOVE locally: " + localPruneBranch);

    if (localPruneBranch.size() == 0) {
      logger.log(Level.INFO, "  + Nothing to prune locally. No conflicts. Only updates. Nice!");
    } else {
      // Load dirty database (if existent)
      logger.log(Level.INFO, "  + Pruning databases locally ...");
      Database dirtyDatabase = new Database();

      for (DatabaseVersionHeader databaseVersionHeader : localPruneBranch.getAll()) {
        // Database version
        DatabaseVersion databaseVersion =
            localDatabase.getDatabaseVersion(databaseVersionHeader.getVectorClock());
        dirtyDatabase.addDatabaseVersion(databaseVersion);

        // Remove database version locally
        logger.log(Level.INFO, "    * Removing " + databaseVersionHeader + " ...");
        localDatabase.removeDatabaseVersion(databaseVersion);

        DatabaseRemoteFile remoteFileToPrune =
            new DatabaseRemoteFile(
                "db-"
                    + config.getMachineName()
                    + "-"
                    + databaseVersionHeader.getVectorClock().get(config.getMachineName()));
        logger.log(Level.INFO, "    * Deleting remote database file " + remoteFileToPrune + " ...");
        transferManager.delete(remoteFileToPrune);
      }

      logger.log(
          Level.INFO, "    * Saving dirty database to " + config.getDirtyDatabaseFile() + " ...");
      saveLocalDatabase(dirtyDatabase, config.getDirtyDatabaseFile());
    }
  }
示例#5
0
  public static DatabaseVersion createDatabaseVersion(
      DatabaseVersionHeader basedOnDatabaseVersionHeader, Date date) {
    VectorClock vectorClock =
        (basedOnDatabaseVersionHeader != null)
            ? basedOnDatabaseVersionHeader.getVectorClock().clone()
            : new VectorClock();
    vectorClock.incrementClock("someclient");

    DatabaseVersion databaseVersion = new DatabaseVersion();

    databaseVersion.setClient("someclient");
    databaseVersion.setTimestamp(date);
    databaseVersion.setVectorClock(vectorClock);

    return databaseVersion;
  }