예제 #1
0
  /**
   * Verify that the protocols are compatible, switch to a different protocol version, if we need
   * to.
   */
  private Protocol checkProtocol(Protocol protocol) throws IOException, ProtocolException {

    ClientVersion clientVersion =
        protocol.read(namedChannel.getChannel(), Protocol.ClientVersion.class);
    clientId = clientVersion.getNodeId();
    FeederManager.Lease lease = feederManager.leases.get(clientId);
    if (lease != null) {
      dbBackup = lease.terminate();
    }
    feederManager.feeders.put(clientId, this);
    if (clientVersion.getVersion() != protocol.getVersion()) {
      String message =
          "Client requested protocol version: "
              + clientVersion.getVersion()
              + " but the server version is "
              + protocol.getVersion();

      /*
       * Simply log the difference on the server, it's up to the client
       * to reject the protocol version, if it can't accommodate it.
       */
      LoggerUtils.warning(logger, feederManager.getEnvImpl(), message);
    }
    protocol.write(protocol.new ServerVersion(), namedChannel);

    /* In future we may switch protocol versions to accommodate the client.
     * For now, simply return the one and only version.
     */
    return protocol;
  }
예제 #2
0
  /**
   * Processes the request for the list of files that constitute a valid backup. If a leased
   * DbBackup instance is available, it uses it, otherwise it creates a new instance and uses it
   * instead.
   */
  private void sendFileList(Protocol protocol)
      throws IOException, ProtocolException, DatabaseException {

    /* Wait for the request message. */
    protocol.read(namedChannel.getChannel(), Protocol.FileListReq.class);

    if (dbBackup == null) {
      dbBackup = new DbBackup(feederManager.getEnvImpl());
      dbBackup.startBackup();
    } else {
      feederManager.leaseRenewalCount++;
    }

    /*
     * Remove the subdirectory header of the log files, because the nodes
     * that need to copy those log files may not configure the spreading
     * log files into sub directories feature.
     */
    String[] files = dbBackup.getLogFilesInBackupSet();
    for (int i = 0; i < files.length; i++) {
      if (files[i].contains(File.separator)) {
        files[i] = files[i].substring(files[i].indexOf(File.separator) + 1, files[i].length());
      }
    }

    protocol.write(protocol.new FileListResp(files), namedChannel);
  }
예제 #3
0
  /**
   * Implements the message exchange used to determine whether this feeder is suitable for use the
   * client's backup needs. The feeder may be unsuitable if it's already busy, or it's not current
   * enough to service the client's needs.
   */
  private void checkFeeder(Protocol protocol) throws IOException, DatabaseException {

    protocol.read(namedChannel.getChannel(), FeederInfoReq.class);
    int feeders = feederManager.getActiveFeederCount() - 1 /* Exclude this one */;
    VLSN rangeFirst = VLSN.NULL_VLSN;
    VLSN rangeLast = VLSN.NULL_VLSN;
    if (feederManager.getEnvImpl() instanceof RepImpl) {
      /* Include replication stream feeders as a load component. */
      RepImpl repImpl = (RepImpl) feederManager.getEnvImpl();
      feeders += repImpl.getRepNode().feederManager().activeReplicaCount();
      VLSNRange range = repImpl.getVLSNIndex().getRange();
      rangeFirst = range.getFirst();
      rangeLast = range.getLast();
    }
    protocol.write(protocol.new FeederInfoResp(feeders, rangeFirst, rangeLast), namedChannel);
  }
예제 #4
0
  /**
   * Send files in response to request messages. The request sequence looks like the following:
   *
   * <p>[FileReq | StatReq]+ Done
   *
   * <p>The response sequence to a FileReq looks like:
   *
   * <p>FileStart <file byte stream> FileEnd
   *
   * <p>and that for a StatReq, is simply a StatResp
   */
  private void sendRequestedFiles(Protocol protocol)
      throws IOException, ProtocolException, DatabaseException {

    try {
      while (true) {
        FileReq fileReq = protocol.read(namedChannel.getChannel(), FileReq.class);
        final String fileName = fileReq.getFileName();

        /*
         * Calculate the full path for a specified log file name,
         * especially when this Feeder is configured to run with sub
         * directories.
         */
        FileManager fMgr = feederManager.getEnvImpl().getFileManager();
        File file = new File(fMgr.getFullFileName(fileName));

        if (!file.exists()) {
          throw EnvironmentFailureException.unexpectedState("Log file not found: " + fileName);
        }
        /* Freeze the length and last modified date. */
        final long length = file.length();
        final long lastModified = file.lastModified();
        byte digest[] = null;
        FileInfoResp resp = null;
        Protocol.FileInfoResp cachedResp = feederManager.statResponses.get(fileName);
        byte cachedDigest[] =
            ((cachedResp != null)
                    && (cachedResp.getFileLength() == length)
                    && (cachedResp.getLastModifiedTime() == lastModified))
                ? cachedResp.getDigestSHA1()
                : null;

        if (fileReq instanceof FileInfoReq) {
          if (cachedDigest != null) {
            digest = cachedDigest;
          } else if (((FileInfoReq) fileReq).getNeedSHA1()) {
            digest = getSHA1Digest(file, length).digest();
          } else {
            // Digest not requested
            digest = new byte[0];
          }
          resp = protocol.new FileInfoResp(fileName, length, lastModified, digest);
        } else {
          protocol.write(protocol.new FileStart(fileName, length, lastModified), namedChannel);
          digest = sendFileContents(file, length);
          if ((cachedDigest != null) && !Arrays.equals(cachedDigest, digest)) {
            throw EnvironmentFailureException.unexpectedState(
                "Inconsistent cached and computed digests");
          }
          resp = protocol.new FileEnd(fileName, length, lastModified, digest);
        }
        /* Cache for subsequent requests, if it was computed. */
        if (digest.length > 0) {
          feederManager.statResponses.put(fileName, resp);
        }
        protocol.write(resp, namedChannel);
      }
    } catch (ProtocolException pe) {
      if (pe.getUnexpectedMessage() instanceof Protocol.Done) {
        return;
      }
      throw pe;
    }
  }