public void _testOperationEncodeTimeout() throws Exception {
    memcachedClient.set("name", 0, "dennis");
    assertEquals("dennis", memcachedClient.get("name"));
    long writeMessageCount = memcachedClient.getConnector().getStatistics().getWriteMessageCount();
    CountDownLatch latch = new CountDownLatch(1);
    Command errorCommand = null;
    if (memcachedClient.getProtocol() == Protocol.Text) {
      errorCommand =
          new MockEncodeTimeoutTextGetOneCommand(
              "name", "name".getBytes(), CommandType.GET_ONE, latch, 1000);
    } else {
      errorCommand =
          new MockEncodeTimeoutBinaryGetCommand(
              "name", "name".getBytes(), CommandType.GET_ONE, latch, OpCode.GET, false, 1000);
    }

    memcachedClient.getConnector().send(errorCommand);
    // Force write thread to encode command
    errorCommand.setIoBuffer(null);
    // wait 100 milliseconds,the operation will be timeout
    if (!latch.await(100, TimeUnit.MILLISECONDS)) {
      errorCommand.cancel();
    }
    Thread.sleep(1000);
    // It is not written to channel,because it is canceled.
    assertEquals(
        writeMessageCount, memcachedClient.getConnector().getStatistics().getWriteMessageCount());
    // It works
    assertEquals("dennis", memcachedClient.get("name"));
  }
Beispiel #2
0
 public void visit(Command command) {
   if (wasFirst) {
     append(command.getKey());
     wasFirst = false;
   } else {
     append(" ");
     append(command.getKey());
   }
 }
Beispiel #3
0
 /**
  * Merge get operation to multi-get operation
  *
  * @param currentCmd
  * @param mergeCommands
  * @return
  * @throws InterruptedException
  */
 @SuppressWarnings("unchecked")
 public final Command optimiezeGet(
     final Queue writeQueue, final Queue<Command> executingCmds, Command optimiezeCommand) {
   if (optimiezeCommand.getCommandType() == CommandType.GET_ONE
       || optimiezeCommand.getCommandType() == CommandType.GETS_ONE) {
     // 浼��get���
     if (optimiezeGet) {
       optimiezeCommand =
           mergeGetCommands(
               optimiezeCommand, writeQueue, executingCmds, optimiezeCommand.getCommandType());
     }
   }
   return optimiezeCommand;
 }
Beispiel #4
0
 /**
  * merge buffers to fit socket's send buffer size
  *
  * @param currentCommand
  * @return
  * @throws InterruptedException
  */
 @SuppressWarnings("unchecked")
 public final Command optimiezeMergeBuffer(
     Command optimiezeCommand,
     final Queue writeQueue,
     final Queue<Command> executingCmds,
     int sendBufferSize) {
   if (log.isDebugEnabled()) {
     log.debug("Optimieze merge buffer:" + optimiezeCommand.toString());
   }
   if (optimiezeMergeBuffer && optimiezeCommand.getIoBuffer().remaining() < sendBufferSize) {
     optimiezeCommand = mergeBuffer(optimiezeCommand, writeQueue, executingCmds, sendBufferSize);
   }
   return optimiezeCommand;
 }
  public void _testErrorCommand() throws Exception {
    Command nonexisCmd =
        new Command() {

          @Override
          public boolean decode(MemcachedTCPSession session, ByteBuffer buffer) {
            return decodeError(ByteUtils.nextLine(buffer));
          }

          @Override
          public void encode() {
            ioBuffer = IoBuffer.wrap(ByteBuffer.wrap("test\r\n".getBytes()));
          }
        };
    nonexisCmd.setKey("test");
    nonexisCmd.setLatch(new CountDownLatch(1));
    memcachedClient.getConnector().send(nonexisCmd);
    // this.memcachedClient.flushAll();
    nonexisCmd.getLatch().await();

    assertNotNull(nonexisCmd.getException());
    assertEquals(
        "Nonexist command,check your memcached version please.",
        nonexisCmd.getException().getMessage());
    assertTrue(nonexisCmd.getException() instanceof UnknownCommandException);

    memcachedClient.set("name", 0, "dennis");
    assertEquals("dennis", memcachedClient.get("name"));
  }
  public void testAddEncodeAndDecode() {

    Command command =
        this.commandFactory.createCASCommand(
            this.key, this.keyBytes, 0, this.value, 9L, this.noreply, this.transcoder);

    command.encode();
    ByteBuffer encodeBuffer = command.getIoBuffer().buf();
    assertNotNull(encodeBuffer);
    assertEquals(42, encodeBuffer.capacity());

    byte opCode = encodeBuffer.get(1);
    // cas use set command
    assertEquals(OpCode.SET.fieldValue(), opCode);

    ByteBuffer buffer =
        constructResponse(
            OpCode.SET.fieldValue(),
            (short) 0,
            (byte) 0,
            (byte) 0,
            (short) 0,
            0,
            0,
            10L,
            null,
            null,
            null);

    assertTrue(command.decode(null, buffer));
    assertTrue((Boolean) command.getResult());
    assertEquals(0, buffer.remaining());

    buffer =
        constructResponse(
            OpCode.SET.fieldValue(),
            (short) 0,
            (byte) 0,
            (byte) 0,
            (short) 0x0005,
            0,
            0,
            0L,
            null,
            null,
            null);
    command =
        this.commandFactory.createCASCommand(
            this.key, this.keyBytes, 0, this.value, 9L, this.noreply, this.transcoder);
    assertTrue(command.decode(null, buffer));
    assertFalse((Boolean) command.getResult());
    assertEquals(0, buffer.remaining());
  }
 public void testOperationDecodeTimeOut() throws Exception {
   memcachedClient.set("name", 0, "dennis");
   assertEquals("dennis", memcachedClient.get("name"));
   CountDownLatch latch = new CountDownLatch(1);
   Command errorCommand = null;
   if (memcachedClient.getProtocol() == Protocol.Text) {
     errorCommand =
         new MockDecodeTimeoutTextGetOneCommand(
             "name", "name".getBytes(), CommandType.GET_ONE, latch, 1000);
   } else {
     errorCommand =
         new MockDecodeTimeoutBinaryGetOneCommand(
             "name", "name".getBytes(), CommandType.GET_ONE, latch, OpCode.GET, false, 1000);
   }
   memcachedClient.getConnector().send(errorCommand);
   // wait 100 milliseconds,the operation will be timeout
   latch.await(100, TimeUnit.MILLISECONDS);
   assertNull(errorCommand.getResult());
   Thread.sleep(1000);
   // It works.
   assertNotNull(errorCommand.getResult());
   assertEquals("dennis", memcachedClient.get("name"));
 }
Beispiel #8
0
 public void finish() {
   // prev command is the last command,last command must be getk,ensure
   // getq commands send response back
   Command lastGetKCommand =
       new BinaryGetCommand(
           prevCommand.getKey(),
           prevCommand.getKeyBytes(),
           CommandType.GET_ONE,
           new CountDownLatch(1),
           OpCode.GET_KEY,
           false);
   lastGetKCommand.encode();
   bufferList.add(lastGetKCommand.getIoBuffer());
   totalBytes += lastGetKCommand.getIoBuffer().remaining();
 }
 public void send(final Command msg) throws MemcachedException {
   MemcachedSession session = (MemcachedSession) this.findSessionByKey(msg.getKey());
   if (session == null) {
     throw new MemcachedException("There is no available connection at this moment");
   }
   // If session was closed,try to use standby memcached node
   if (session.isClosed()) {
     session = this.findStandbySession(session);
   }
   if (session.isClosed()) {
     throw new MemcachedException(
         "Session("
             + SystemUtils.getRawAddress(session.getRemoteSocketAddress())
             + ":"
             + session.getRemoteSocketAddress().getPort()
             + ") has been closed");
   }
   if (session.isAuthFailed()) {
     throw new MemcachedException("Auth failed to connection " + session.getRemoteSocketAddress());
   }
   session.write(msg);
 }
Beispiel #10
0
 public void visit(Command command) {
   // Encode prev command
   if (prevCommand != null) {
     // first n-1 send getq command
     Command getqCommand =
         new BinaryGetCommand(
             prevCommand.getKey(),
             prevCommand.getKeyBytes(),
             null,
             null,
             OpCode.GET_KEY_QUIETLY,
             true);
     getqCommand.encode();
     totalBytes += getqCommand.getIoBuffer().remaining();
     bufferList.add(getqCommand.getIoBuffer());
   }
   prevCommand = command;
 }
Beispiel #11
0
  @SuppressWarnings("unchecked")
  private final Command mergeGetCommands(
      final Command currentCmd,
      final Queue writeQueue,
      final Queue<Command> executingCmds,
      CommandType expectedCommandType) {
    Map<Object, Command> mergeCommands = null;
    int mergeCount = 1;
    final CommandCollector commandCollector = creatCommandCollector();
    currentCmd.setStatus(OperationStatus.WRITING);

    commandCollector.visit(currentCmd);
    while (mergeCount < mergeFactor) {
      Command nextCmd = (Command) writeQueue.peek();
      if (nextCmd == null) {
        break;
      }
      if (nextCmd.isCancel()) {
        writeQueue.remove();
        continue;
      }
      if (nextCmd.getCommandType() == expectedCommandType) {
        if (mergeCommands == null) { // lazy initialize
          mergeCommands = new HashMap<Object, Command>(mergeFactor / 2);
          mergeCommands.put(currentCmd.getKey(), currentCmd);
        }
        if (log.isDebugEnabled()) {
          log.debug("Merge get command:" + nextCmd.toString());
        }
        nextCmd.setStatus(OperationStatus.WRITING);
        Command removedCommand = (Command) writeQueue.remove();
        // If the key is exists,add the command to associated list.
        if (mergeCommands.containsKey(removedCommand.getKey())) {
          final AssocCommandAware mergedGetCommand =
              (AssocCommandAware) mergeCommands.get(removedCommand.getKey());
          if (mergedGetCommand.getAssocCommands() == null) {
            mergedGetCommand.setAssocCommands(new ArrayList<Command>(5));
          }
          mergedGetCommand.getAssocCommands().add(removedCommand);
        } else {
          commandCollector.visit(nextCmd);
          mergeCommands.put(removedCommand.getKey(), removedCommand);
        }
        mergeCount++;
      } else {
        break;
      }
    }
    commandCollector.finish();
    if (mergeCount == 1) {
      return currentCmd;
    } else {
      if (log.isDebugEnabled()) {
        log.debug("Merge optimieze:merge " + mergeCount + " get commands");
      }
      return newMergedCommand(mergeCommands, mergeCount, commandCollector, expectedCommandType);
    }
  }
Beispiel #12
0
  @SuppressWarnings("unchecked")
  private final Command mergeBuffer(
      final Command firstCommand,
      final Queue writeQueue,
      final Queue<Command> executingCmds,
      final int sendBufferSize) {
    Command lastCommand = firstCommand; // ��苟������涓�ommand
    Command nextCmd = (Command) writeQueue.peek();
    if (nextCmd == null) {
      return lastCommand;
    }

    final List<Command> commands = getLocalList();
    final ByteBuffer firstBuffer = firstCommand.getIoBuffer().buf();
    int totalBytes = firstBuffer.remaining();
    commands.add(firstCommand);
    boolean wasFirst = true;
    while (totalBytes + nextCmd.getIoBuffer().remaining() <= sendBufferSize
        && (nextCmd = (Command) writeQueue.peek()) != null) {
      if (nextCmd.getStatus() == OperationStatus.WRITING) {
        break;
      }
      if (nextCmd.isCancel()) {
        writeQueue.remove();
        continue;
      }
      nextCmd.setStatus(OperationStatus.WRITING);

      writeQueue.remove();

      if (wasFirst) {
        wasFirst = false;
      }
      // if it is get_one command,try to merge get commands
      if ((nextCmd.getCommandType() == CommandType.GET_ONE
              || nextCmd.getCommandType() == CommandType.GETS_ONE)
          && optimiezeGet) {
        nextCmd = mergeGetCommands(nextCmd, writeQueue, executingCmds, nextCmd.getCommandType());
      }

      commands.add(nextCmd);
      lastCommand = nextCmd;
      totalBytes += nextCmd.getIoBuffer().remaining();
      if (totalBytes > sendBufferSize) {
        break;
      }
    }
    if (commands.size() > 1) {
      byte[] buf = new byte[totalBytes];
      int offset = 0;
      for (Command command : commands) {
        byte[] ba = command.getIoBuffer().array();
        System.arraycopy(ba, 0, buf, offset, ba.length);
        offset += ba.length;
        if (command != lastCommand
            && (!command.isNoreply() || command instanceof BaseBinaryCommand)) {
          executingCmds.add(command);
        }
      }
      lastCommand.setIoBuffer(IoBuffer.wrap(buf));
    }
    return lastCommand;
  }
Beispiel #13
0
  private void doAuth() {
    SaslClient saslClient = null;
    try {
      saslClient =
          Sasl.createSaslClient(
              authInfo.getMechanisms(),
              null,
              "memcached",
              memcachedTCPSession.getRemoteSocketAddress().toString(),
              null,
              this.authInfo.getCallbackHandler());

      final AtomicBoolean done = new AtomicBoolean(false);
      byte[] response =
          saslClient.hasInitialResponse() ? saslClient.evaluateChallenge(EMPTY_BYTES) : EMPTY_BYTES;
      CountDownLatch latch = new CountDownLatch(1);
      Command command =
          this.commandFactory.createAuthStartCommand(
              saslClient.getMechanismName(), latch, response);
      if (!this.memcachedTCPSession.isClosed()) this.memcachedTCPSession.write(command);
      else {
        log.error("Authentication fail,because the connection has been closed");
        throw new RuntimeException("Authentication fai,connection has been close");
      }

      while (!done.get()) {
        try {
          latch.await();
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          done.set(true);
        }
        ResponseStatus responseStatus = ((BaseBinaryCommand) command).getResponseStatus();
        switch (responseStatus) {
          case NO_ERROR:
            done.set(true);
            log.info(
                "Authentication to "
                    + this.memcachedTCPSession.getRemoteSocketAddress()
                    + " successfully");
            break;
          case AUTH_REQUIRED:
            log.error(
                "Authentication failed to " + this.memcachedTCPSession.getRemoteSocketAddress());
            log.warn(
                "Reopen connection to "
                    + this.memcachedTCPSession.getRemoteSocketAddress()
                    + ",beacause auth fail");
            this.memcachedTCPSession.setAuthFailed(true);

            // It it is not first time,try to sleep 1 second
            if (!this.authInfo.isFirstTime()) {
              Thread.sleep(1000);
            }
            this.memcachedTCPSession.close();
            done.set(true);
            break;
          case FUTHER_AUTH_REQUIRED:
            String result = (String) command.getResult();
            response = saslClient.evaluateChallenge(ByteUtils.getBytes(result));
            latch = new CountDownLatch(1);
            command =
                commandFactory.createAuthStepCommand(
                    saslClient.getMechanismName(), latch, response);
            if (!this.memcachedTCPSession.isClosed()) this.memcachedTCPSession.write(command);
            else {
              log.error("Authentication fail,because the connection has been closed");
              throw new RuntimeException("Authentication fai,connection has been close");
            }

            break;
          default:
            done.set(true);
            log.error(
                "Authentication failed to "
                    + this.memcachedTCPSession.getRemoteSocketAddress()
                    + ",response status="
                    + responseStatus);
            break;
        }
      }
    } catch (Exception e) {
      log.error("Create saslClient error", e);
    } finally {
      if (saslClient != null) {
        try {
          saslClient.dispose();
        } catch (SaslException e) {
          log.error("Dispose saslClient error", e);
        }
      }
    }
  }