/** * Memcached protocol decoder * * @author dennis */ public class MemcachedDecoder implements Decoder { public static final Logger log = LoggerFactory.getLogger(MemcachedDecoder.class); public MemcachedDecoder() { super(); } /** shift-and algorithm for ByteBuffer's match */ public static final ByteBufferMatcher SPLIT_MATCHER = new ShiftAndByteBufferMatcher(IoBuffer.wrap(ByteUtils.SPLIT)); public Object decode(IoBuffer buffer, Session origSession) { MemcachedTCPSession session = (MemcachedTCPSession) origSession; if (session.getCurrentCommand() != null) { return decode0(buffer, session); } else { session.takeCurrentCommand(); if (session.getCurrentCommand() == null) return null; return decode0(buffer, session); } } private Object decode0(IoBuffer buffer, MemcachedTCPSession session) { if (session.getCurrentCommand().decode(session, buffer.buf())) { final Command command = session.getCurrentCommand(); session.setCurrentCommand(null); return command; } return null; } }
private Command newMergedCommand( final Map<Object, Command> mergeCommands, int mergeCount, final CommandCollector commandCollector, final CommandType commandType) { if (protocol == Protocol.Text) { String resultKey = (String) commandCollector.getResult(); byte[] keyBytes = ByteUtils.getBytes(resultKey); byte[] cmdBytes = commandType == CommandType.GET_ONE ? Constants.GET : Constants.GETS; final byte[] buf = new byte[cmdBytes.length + 3 + keyBytes.length]; ByteUtils.setArguments(buf, 0, cmdBytes, keyBytes); TextGetOneCommand cmd = new TextGetOneCommand(resultKey, keyBytes, commandType, null); cmd.setMergeCommands(mergeCommands); cmd.setWriteFuture(new FutureImpl<Boolean>()); cmd.setMergeCount(mergeCount); cmd.setIoBuffer(IoBuffer.wrap(buf)); return cmd; } else { BinaryGetMultiCommand result = (BinaryGetMultiCommand) commandCollector.getResult(); result.setMergeCount(mergeCount); result.setMergeCommands(mergeCommands); return result; } }
public Object getResult() { byte[] buf = new byte[totalBytes]; int offset = 0; for (IoBuffer buffer : bufferList) { byte[] ba = buffer.array(); System.arraycopy(ba, 0, buf, offset, ba.length); offset += ba.length; } BinaryGetMultiCommand resultCommand = new BinaryGetMultiCommand(null, CommandType.GET_MANY, new CountDownLatch(1)); resultCommand.setIoBuffer(IoBuffer.wrap(buf)); return resultCommand; }
@Override public final void encode() { int size = Constants.DELETE.length + 1 + this.keyBytes.length + Constants.CRLF.length; if (isNoreply()) { size += 8; } byte[] buf = new byte[size]; if (isNoreply()) { ByteUtils.setArguments(buf, 0, Constants.DELETE, this.keyBytes, Constants.NO_REPLY); } else { ByteUtils.setArguments(buf, 0, Constants.DELETE, this.keyBytes); } this.ioBuffer = IoBuffer.wrap(buf); }
/** * �峰�涓��琛� * * @param buffer */ public static final String nextLine(ByteBuffer buffer) { if (buffer == null) { return null; } /** * 娴��琛ㄦ���� Shift-And绠���归� >BM绠���归���� > �寸��归� > KMP�归�锛� * 濡��浣���村ソ��缓璁��璇�mail缁��([email protected]) */ int index = MemcachedDecoder.SPLIT_MATCHER.matchFirst( com.google.code.yanf4j.buffer.IoBuffer.wrap(buffer)); if (index >= 0) { int limit = buffer.limit(); buffer.limit(index); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); buffer.limit(limit); buffer.position(index + ByteUtils.SPLIT.remaining()); return getString(bytes); } return null; }
@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; }