diff --git a/klein-common/pom.xml b/klein-common/pom.xml index cdd3620e..52635d43 100644 --- a/klein-common/pom.xml +++ b/klein-common/pom.xml @@ -20,10 +20,6 @@ UTF-8 - - com.caucho - hessian - org.javassist javassist diff --git a/klein-common/src/main/java/com/ofcoder/klein/common/serialization/Hessian2Util.java b/klein-common/src/main/java/com/ofcoder/klein/common/serialization/Hessian2Util.java deleted file mode 100644 index ef90968f..00000000 --- a/klein-common/src/main/java/com/ofcoder/klein/common/serialization/Hessian2Util.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.ofcoder.klein.common.serialization; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import com.caucho.hessian.io.Hessian2Input; -import com.caucho.hessian.io.Hessian2Output; -import com.ofcoder.klein.common.exception.SerializationException; -import com.ofcoder.klein.common.util.StreamUtil; - -/** - * Hessian util. - * - * @author far.liu - */ -public class Hessian2Util { - - /** - * serialize object. - * - * @param javaBean object - * @param java object type - * @return serialized data - */ - public static byte[] serialize(final T javaBean) { - Hessian2Output ho = null; - ByteArrayOutputStream baos = null; - - try { - baos = new ByteArrayOutputStream(); - ho = new Hessian2Output(baos); - ho.writeObject(javaBean); - ho.flush(); - return baos.toByteArray(); - } catch (Exception ex) { - throw new SerializationException(ex.getMessage(), ex); - } finally { - if (ho != null) { - try { - ho.close(); - } catch (IOException e) { - throw new SerializationException(e.getMessage(), e); - } - } - StreamUtil.close(baos); - } - } - - /** - * deserialize data to java object. - * - * @param serializeData serialized data - * @param java object type - * @return java object - */ - @SuppressWarnings("unchecked") - public static T deserialize(final byte[] serializeData) { - Hessian2Input hi = null; - ByteArrayInputStream bais = null; - - try { - bais = new ByteArrayInputStream(serializeData); - hi = new Hessian2Input(bais); - return (T) hi.readObject(); - } catch (Exception ex) { - throw new SerializationException(ex.getMessage(), ex); - } finally { - if (null != hi) { - try { - hi.close(); - } catch (IOException e) { - throw new SerializationException(e.getMessage(), e); - } - } - StreamUtil.close(bais); - } - } -} diff --git a/klein-common/src/test/java/com/ofcoder/klein/common/serialization/Hessian2UtilTest.java b/klein-common/src/test/java/com/ofcoder/klein/common/serialization/Hessian2UtilTest.java deleted file mode 100644 index 30e95ee7..00000000 --- a/klein-common/src/test/java/com/ofcoder/klein/common/serialization/Hessian2UtilTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.ofcoder.klein.common.serialization; - -import org.junit.Assert; - -import junit.framework.TestCase; - -public class Hessian2UtilTest extends TestCase { - - public void testSerialize() { - String resource = "Hello Klein"; - byte[] serialize = Hessian2Util.serialize(resource); - Assert.assertNotNull(serialize); - String deserialize = Hessian2Util.deserialize(serialize); - Assert.assertEquals(deserialize, resource); - - } -} \ No newline at end of file diff --git a/klein-consensus/klein-consensus-facade/pom.xml b/klein-consensus/klein-consensus-facade/pom.xml index fc4c12bc..badf9f86 100644 --- a/klein-consensus/klein-consensus-facade/pom.xml +++ b/klein-consensus/klein-consensus-facade/pom.xml @@ -28,6 +28,10 @@ com.ofcoder.klein.storage.api klein-storage-facade + + klein-serializer-facade + com.ofcoder.klein.serializer.facade + \ No newline at end of file diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractInvokeCallback.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractInvokeCallback.java index c7b7a37f..1be83eec 100644 --- a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractInvokeCallback.java +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractInvokeCallback.java @@ -16,10 +16,9 @@ */ package com.ofcoder.klein.consensus.facade; -import java.nio.ByteBuffer; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.rpc.facade.InvokeCallback; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; /** * Invoke callback. @@ -27,6 +26,12 @@ * @author far.liu */ public abstract class AbstractInvokeCallback implements InvokeCallback { + private final Serializer serializer; + + public AbstractInvokeCallback() { + serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); + } + /** * invoke completed. * @@ -35,8 +40,8 @@ public abstract class AbstractInvokeCallback implements InvokeCallback { public abstract void complete(RES result); @Override - public void complete(final ByteBuffer result) { - RES deserialize = Hessian2Util.deserialize(result.array()); + public void complete(final byte[] result) { + RES deserialize = serializer.deserialize(result); complete(deserialize); } } diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractRpcProcessor.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractRpcProcessor.java index 9664314d..7717ebce 100644 --- a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractRpcProcessor.java +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/AbstractRpcProcessor.java @@ -16,11 +16,10 @@ */ package com.ofcoder.klein.consensus.facade; -import java.nio.ByteBuffer; - import com.ofcoder.klein.rpc.facade.RpcContext; import com.ofcoder.klein.rpc.facade.RpcProcessor; -import com.ofcoder.klein.common.serialization.Hessian2Util; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; /** * rpc processor. @@ -28,6 +27,11 @@ * @author 释慧利 */ public abstract class AbstractRpcProcessor implements RpcProcessor { + private final Serializer serializer; + + public AbstractRpcProcessor() { + serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); + } /** * handle request. @@ -38,8 +42,13 @@ public abstract class AbstractRpcProcessor implements RpcProcessor { public abstract void handleRequest(R request, RpcContext context); @Override - public void handleRequest(final ByteBuffer request, final RpcContext context) { - R deserialize = Hessian2Util.deserialize(request.array()); + public void handleRequest(final byte[] request, final RpcContext context) { + R deserialize = serializer.deserialize(request); handleRequest(deserialize, context); } + + protected void response(final Object msg, final RpcContext context) { + byte[] serialize = serializer.serialize(msg); + context.response(serialize); + } } diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Command.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Command.java index 87cfd48e..d744c4f1 100644 --- a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Command.java +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Command.java @@ -22,20 +22,6 @@ * consensus content. */ public interface Command extends Serializable { - - Command NOOP = new Command() { - - @Override - public String getGroup() { - return Noop.GROUP; - } - - @Override - public Object getData() { - return Noop.DEFAULT; - } - }; - String getGroup(); /** @@ -43,13 +29,7 @@ public Object getData() { * * @return data */ - Object getData(); + byte[] getData(); - /** - * No operation proposal. - */ - class Noop implements Serializable { - public static final Noop DEFAULT = new Noop(); - public static final String GROUP = "NOOP"; - } + boolean getIfSystemOp(); } diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Consensus.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Consensus.java index c77a32e1..8742d102 100644 --- a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Consensus.java +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Consensus.java @@ -16,8 +16,6 @@ */ package com.ofcoder.klein.consensus.facade; -import java.io.Serializable; - import com.ofcoder.klein.consensus.facade.sm.SM; import com.ofcoder.klein.spi.SPI; @@ -45,11 +43,9 @@ public interface Consensus extends Cluster { * e.g. The input value of the state machine * @param apply Whether you need to wait until the state machine is applied * If true, wait until the state machine is applied before returning - * @param result type - * @param request type * @return whether success */ - Result propose(String group, E data, boolean apply); + Result propose(String group, byte[] data, boolean apply); /** * Obtain the consensus reached instanceId. @@ -58,7 +54,7 @@ public interface Consensus extends Cluster { * @param group group name * @return instance id */ - Result readIndex(String group); + Long readIndex(String group); /** * preheating. diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/NoopCommand.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/NoopCommand.java new file mode 100644 index 00000000..083ba3f9 --- /dev/null +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/NoopCommand.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ofcoder.klein.consensus.facade; + +/** + * noop command. + * A no-operation command implementation that represents a null operation in the consensus system. + * This command is typically used as a placeholder in the consensus protocol when there are no actual + * commands to process, helping maintain the consensus mechanism's continuity. + */ +public enum NoopCommand implements Command { + NOOP; + + @Override + public String getGroup() { + return "NOOP"; + } + + @Override + public byte[] getData() { + return new byte[0]; + } + + @Override + public boolean getIfSystemOp() { + return true; + } +} diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Result.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Result.java index b98119d7..654a6724 100644 --- a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Result.java +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/Result.java @@ -23,10 +23,10 @@ * * @author 释慧利 */ -public class Result implements Serializable { +public class Result implements Serializable { private State state; - private D data; + private byte[] data; public enum State { /** @@ -51,17 +51,17 @@ public void setState(final State state) { this.state = state; } - public D getData() { + public byte[] getData() { return data; } - public void setData(final D data) { + public void setData(final byte[] data) { this.data = data; } - public static final class Builder { + public static final class Builder { private State state; - private D data; + private byte[] data; private Builder() { } @@ -69,11 +69,10 @@ private Builder() { /** * aResult. * - * @param data type * @return Builder */ - public static Builder aResult() { - return new Builder<>(); + public static Builder aResult() { + return new Builder(); } /** @@ -82,7 +81,7 @@ public static Builder aResult() { * @param state state * @return Builder */ - public Builder state(final State state) { + public Builder state(final State state) { this.state = state; return this; } @@ -93,7 +92,7 @@ public Builder state(final State state) { * @param data data * @return Builder */ - public Builder data(final D data) { + public Builder data(final byte[] data) { this.data = data; return this; } @@ -103,8 +102,8 @@ public Builder data(final D data) { * * @return Result object */ - public Result build() { - Result result = new Result<>(); + public Result build() { + Result result = new Result(); result.setState(state); result.setData(data); return result; diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SM.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SM.java index e65b542b..ac67a8e9 100644 --- a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SM.java +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SM.java @@ -29,21 +29,21 @@ public interface SM { * @param data proposal's data * @return apply result */ - Object apply(Object data); + byte[] apply(byte[] data); /** * make a snapshot. * * @return snapshot */ - Object makeImage(); + byte[] makeImage(); /** * load snapshot. * * @param snap snapshot */ - void loadImage(Object snap); + void loadImage(byte[] snap); /** * close sm. diff --git a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SMApplier.java b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SMApplier.java index 64ab77e3..51b11d8e 100644 --- a/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SMApplier.java +++ b/klein-consensus/klein-consensus-facade/src/main/java/com/ofcoder/klein/consensus/facade/sm/SMApplier.java @@ -16,6 +16,14 @@ */ package com.ofcoder.klein.consensus.facade.sm; +import com.ofcoder.klein.common.util.KleinThreadFactory; +import com.ofcoder.klein.consensus.facade.Command; +import com.ofcoder.klein.consensus.facade.config.ConsensusProp; +import com.ofcoder.klein.consensus.facade.config.SnapshotStrategy; +import com.ofcoder.klein.spi.ExtensionLoader; +import com.ofcoder.klein.storage.facade.Instance; +import com.ofcoder.klein.storage.facade.LogManager; +import com.ofcoder.klein.storage.facade.Snap; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -27,19 +35,9 @@ import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.ofcoder.klein.common.util.KleinThreadFactory; -import com.ofcoder.klein.consensus.facade.Command; -import com.ofcoder.klein.consensus.facade.config.ConsensusProp; -import com.ofcoder.klein.consensus.facade.config.SnapshotStrategy; -import com.ofcoder.klein.spi.ExtensionLoader; -import com.ofcoder.klein.storage.facade.Instance; -import com.ofcoder.klein.storage.facade.LogManager; -import com.ofcoder.klein.storage.facade.Snap; - /** * SM Applier. */ @@ -55,6 +53,7 @@ public class SMApplier { private Long lastSnapTime = System.currentTimeMillis(); private final List snapshotStrategies; + @SuppressWarnings("unchecked") public SMApplier(final String group, final SM sm, final ConsensusProp op) { this.group = group; this.sm = sm; @@ -127,14 +126,14 @@ private void _apply(final Task task) { final long lastApplyId = this.lastAppliedId; final long instanceId = task.priority; - Map applyResult = new HashMap<>(); + Map applyResult = new HashMap<>(); if (instanceId > lastApplyId) { LOG.debug("doing apply instance[{}]", instanceId); Instance instance = logManager.getInstance(instanceId); List proposals = instance.getGrantedValue().stream() - .filter(it -> it != Command.NOOP) - .filter(it -> group.equals(it.getGroup())) - .collect(Collectors.toList()); + // .filter(it -> it != Command.NOOP) by group + .filter(it -> group.equals(it.getGroup())) + .collect(Collectors.toList()); proposals.forEach(it -> applyResult.put(it, sm.apply(it.getData()))); this.lastAppliedId = instanceId; @@ -290,7 +289,7 @@ public interface TaskCallback { * * @param result apply result */ - default void onApply(final Map result) { + default void onApply(final Map result) { } diff --git a/klein-consensus/klein-consensus-paxos/pom.xml b/klein-consensus/klein-consensus-paxos/pom.xml index bcb8a11e..2c581bca 100644 --- a/klein-consensus/klein-consensus-paxos/pom.xml +++ b/klein-consensus/klein-consensus-paxos/pom.xml @@ -24,6 +24,11 @@ com.ofcoder.klein.consensus.facade klein-consensus-facade + + com.ofcoder.klein.serializer.hessian2 + klein-serializer-hessian2 + test + com.h2database h2 diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/MasterProposeProxy.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/MasterProposeProxy.java index 18403327..76cfa281 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/MasterProposeProxy.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/MasterProposeProxy.java @@ -25,12 +25,11 @@ import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.RpcClient; import com.ofcoder.klein.rpc.facade.exception.ConnectionException; +import com.ofcoder.klein.serializer.Serializer; import com.ofcoder.klein.spi.ExtensionLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.Serializable; - import static com.ofcoder.klein.consensus.paxos.rpc.vo.RedirectReq.TRANSACTION_REQUEST; /** @@ -44,22 +43,24 @@ public class MasterProposeProxy implements ProposeProxy { private final PaxosNode self; private final ConsensusProp prop; private final ProposeProxy directProxy; + private final Serializer proposalValueSerializer; public MasterProposeProxy(final ConsensusProp op, final PaxosNode self) { this.self = self; this.prop = op; this.client = ExtensionLoader.getExtensionLoader(RpcClient.class).getJoin(); this.directProxy = new UniversalProposeProxy(op); + this.proposalValueSerializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); } @Override - public Result propose(final Proposal data, final boolean apply) { + public Result propose(final Proposal data, final boolean apply) { MasterState masterState = RuntimeAccessor.getMaster().getMaster(); if (masterState.isSelf() || !prop.getPaxosProp().isEnableMaster()) { return this.directProxy.propose(data, apply); } - Result.Builder builder = Result.Builder.aResult(); + Result.Builder builder = Result.Builder.aResult(); Endpoint master = masterState.getMaster(); if (master == null) { @@ -69,14 +70,16 @@ public Result propose(final Proposal data, final boo } RedirectReq req = RedirectReq.Builder.aRedirectReq() - .nodeId(this.self.getSelf().getId()) - .redirect(TRANSACTION_REQUEST) - .proposal(data) - .apply(apply) - .build(); + .nodeId(this.self.getSelf().getId()) + .redirect(TRANSACTION_REQUEST) + .proposal(data) + .apply(apply) + .build(); try { - RedirectRes res = this.client.sendRequestSync(master, req, this.prop.getRoundTimeout() * this.prop.getRetry() + client.requestTimeout()); - return (Result) res.getProposeResult(); + byte[] content = proposalValueSerializer.serialize(req); + byte[] response = this.client.sendRequestSync(master, content, this.prop.getRoundTimeout() * this.prop.getRetry() + client.requestTimeout()); + RedirectRes redirectRes = proposalValueSerializer.deserialize(response); + return redirectRes.getProposeResult(); } catch (Exception e) { if (e instanceof ConnectionException) { return builder.state(Result.State.FAILURE).build(); @@ -88,7 +91,7 @@ public Result propose(final Proposal data, final boo } @Override - public Result readIndex(final String group) { + public Long readIndex(final String group) { return null; } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/PaxosConsensus.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/PaxosConsensus.java index d6848f90..84c97c53 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/PaxosConsensus.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/PaxosConsensus.java @@ -44,13 +44,13 @@ import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.RpcClient; import com.ofcoder.klein.rpc.facade.RpcEngine; +import com.ofcoder.klein.serializer.Serializer; import com.ofcoder.klein.spi.ExtensionLoader; import com.ofcoder.klein.spi.Join; import com.ofcoder.klein.storage.facade.LogManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.Serializable; import java.util.List; import java.util.Set; @@ -66,10 +66,12 @@ public class PaxosConsensus implements Consensus { private final ConsensusProp prop; private final RpcClient client; private final ProposeProxy proposeProxy; + private final Serializer proposalValueSerializer; public PaxosConsensus(final ConsensusProp prop) { this.prop = prop; this.client = ExtensionLoader.getExtensionLoader(RpcClient.class).getJoin(); + this.proposalValueSerializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); ExtensionLoader.getExtensionLoader(Nwr.class).register(this.prop.getNwr()); // reload self information from storage. @@ -123,13 +125,28 @@ public void loadSM(final String group, final SM sm) { } @Override - public Result propose(final String group, final E data, final boolean apply) { - Proposal proposal = new Proposal(group, data); + public Result propose(final String group, final byte[] data, final boolean apply) { + return propose(group, data, apply, false); + } + + /** + * propose proposal. + * + * @param group group name + * @param data Client data, type is Serializable + * e.g. The input value of the state machine + * @param apply Whether you need to wait until the state machine is applied + * If true, wait until the state machine is applied before returning + * @param isSystemOp is SystemOp + * @return whether success + */ + public Result propose(final String group, final byte[] data, final boolean apply, final boolean isSystemOp) { + Proposal proposal = new Proposal(group, data, isSystemOp); return proposeProxy.propose(proposal, apply); } @Override - public Result readIndex(final String group) { + public Long readIndex(final String group) { return proposeProxy.readIndex(group); } @@ -155,7 +172,8 @@ private void joinCluster() { for (Endpoint endpoint : MemberRegistry.getInstance().getMemberConfiguration().getAllMembers()) { try { - ElasticRes res = client.sendRequestSync(endpoint, req); + byte[] response = this.client.sendRequestSync(endpoint, proposalValueSerializer.serialize(req)); + ElasticRes res = proposalValueSerializer.deserialize(response); if (res.isResult()) { return; } @@ -170,10 +188,11 @@ private void exitCluster() { ElasticReq req = new ElasticReq(); req.setEndpoint(self.getSelf()); req.setOp(ElasticReq.SHUTDOWN); + byte[] content = proposalValueSerializer.serialize(req); for (Endpoint endpoint : MemberRegistry.getInstance().getMemberConfiguration().getAllMembers()) { try { - ElasticRes res = client.sendRequestSync(endpoint, req); + ElasticRes res = proposalValueSerializer.deserialize(client.sendRequestSync(endpoint, content)); if (res.isResult()) { return; } @@ -220,7 +239,7 @@ public boolean changeMember(final List add, final List remov firstPhase.setNewConfig(newConfig); firstPhase.setPhase(ChangeMemberOp.FIRST_PHASE); - Result first = propose(MemberManagerSM.GROUP, firstPhase, false); + Result first = propose(MemberManagerSM.GROUP, proposalValueSerializer.serialize(firstPhase), false, true); LOG.info("change member first phase, add: {}, remove: {}, result: {}", add, remove, first.getState()); if (first.getState() == Result.State.SUCCESS) { @@ -229,9 +248,15 @@ public boolean changeMember(final List add, final List remov secondPhase.setNewConfig(newConfig); secondPhase.setPhase(ChangeMemberOp.SECOND_PHASE); - Result second = propose(MemberManagerSM.GROUP, secondPhase, false); - LOG.info("change member second phase, add: {}, remove: {}, result: {}", add, remove, first.getState()); - return second.getState() == Result.State.SUCCESS; + try { + Result second = propose(MemberManagerSM.GROUP, proposalValueSerializer.serialize(secondPhase), false, true); + LOG.info("change member second phase, add: {}, remove: {}, result: {}", add, remove, first.getState()); + return second.getState() == Result.State.SUCCESS; + } catch (Exception e) { + LOG.error("Failed to serialize second phase data. Phase: {}, NodeId: {}, NewConfig: {}", + secondPhase.getPhase(), secondPhase.getNodeId(), secondPhase.getNewConfig(), e); + return false; + } } else { return false; } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/Proposal.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/Proposal.java index 8bfc0840..13b76d88 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/Proposal.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/Proposal.java @@ -16,9 +16,10 @@ */ package com.ofcoder.klein.consensus.paxos; -import java.util.Objects; - import com.ofcoder.klein.consensus.facade.Command; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; /** * Proposal. @@ -27,14 +28,25 @@ */ public class Proposal implements Command { private String group; - private Object data; + private byte[] data; + private Boolean ifSystemOp; public Proposal() { } - public Proposal(final String group, final Object data) { + public Proposal(final String group, final byte[] data, final Boolean ifSystemOp) { this.group = group; this.data = data; + this.ifSystemOp = ifSystemOp; + } + + @Override + public boolean getIfSystemOp() { + return ifSystemOp; + } + + public void setIfSystemOp(final Boolean ifSystemOp) { + this.ifSystemOp = ifSystemOp; } @Override @@ -47,12 +59,12 @@ public void setGroup(final String group) { } @Override - public Object getData() { - return data; + public byte[] getData() { + return data.clone(); } - public void setData(final Object data) { - this.data = data; + public void setData(final byte[] data) { + this.data = data.clone(); } @Override @@ -64,20 +76,22 @@ public boolean equals(final Object o) { return false; } Proposal proposal = (Proposal) o; - return Objects.equals(getGroup(), proposal.getGroup()) && Objects.equals(getData(), proposal.getData()); + return Objects.equals(group, proposal.group) + && Arrays.equals(data, proposal.data) + && Objects.equals(ifSystemOp, proposal.ifSystemOp); } @Override public int hashCode() { - return Objects.hash(getGroup(), getData()); + return Objects.hash(group, Arrays.hashCode(data), ifSystemOp); } @Override public String toString() { return "Proposal{" - + "group='" + group + '\'' - + ", data=" + data - + '}'; + + "group='" + group + '\'' + + ", data=" + Optional.ofNullable(data).map(value -> value.length).orElse(0) + + ", ifSystemOp=" + ifSystemOp + + '}'; } - } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/ProposeProxy.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/ProposeProxy.java index 6ed627bb..dcb283d6 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/ProposeProxy.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/ProposeProxy.java @@ -16,8 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos; -import java.io.Serializable; - import com.ofcoder.klein.consensus.facade.Result; /** @@ -32,10 +30,9 @@ public interface ProposeProxy { * @param data proposal * @param apply Whether you need to wait until the state machine is applied * If true, wait until the state machine is applied before returning - * @param result type * @return propose result */ - Result propose(Proposal data, boolean apply); + Result propose(Proposal data, boolean apply); /** * todo: read index. @@ -43,6 +40,6 @@ public interface ProposeProxy { * @param group group name * @return instance id */ - Result readIndex(String group); + Long readIndex(String group); } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/UniversalProposeProxy.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/UniversalProposeProxy.java index 24224932..aeca10f0 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/UniversalProposeProxy.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/UniversalProposeProxy.java @@ -16,7 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos; -import java.io.Serializable; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -45,10 +44,9 @@ public UniversalProposeProxy(final ConsensusProp prop) { } @Override - public Result propose(final Proposal proposal, final boolean apply) { - + public Result propose(final Proposal proposal, final boolean apply) { CountDownLatch completed = new CountDownLatch(1); - Result.Builder builder = Result.Builder.aResult(); + Result.Builder builder = Result.Builder.aResult(); if (LOG.isDebugEnabled()) { LOG.debug("Direct Propose, outsider: {}, write on master: {}", prop.getSelf().isOutsider(), prop.getPaxosProp().isEnableMaster()); } @@ -69,12 +67,11 @@ public void negotiationDone(final boolean result, final boolean changed) { } @Override - @SuppressWarnings("unchecked") - public void applyDone(final Map result) { + public void applyDone(final Map result) { if (LOG.isDebugEnabled()) { LOG.debug("Direct Propose applyDone, result: {}", result); } - builder.data((D) result.get(proposal)); + builder.data(result.get(proposal)); completed.countDown(); } }, false); @@ -91,8 +88,9 @@ public void applyDone(final Map result) { } @Override - public Result readIndex(final String group) { + public Long readIndex(final String group) { // only for enabled master return null; } + } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/DataAligner.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/DataAligner.java index 549ca48b..1f266924 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/DataAligner.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/DataAligner.java @@ -30,19 +30,19 @@ import com.ofcoder.klein.consensus.paxos.rpc.vo.Sync; import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.RpcClient; +import com.ofcoder.klein.serializer.Serializer; import com.ofcoder.klein.spi.ExtensionLoader; import com.ofcoder.klein.storage.facade.Instance; import com.ofcoder.klein.storage.facade.LogManager; import com.ofcoder.klein.storage.facade.Snap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Comparator; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.PriorityBlockingQueue; import java.util.function.Predicate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DataAligner { private static final Logger LOG = LoggerFactory.getLogger(DataAligner.class); @@ -53,12 +53,13 @@ public class DataAligner { private RpcClient client; private final BlockingQueue learnQueue; private boolean shutdown = false; + private final Serializer serializer; public DataAligner(final PaxosNode self) { this.self = self; this.learnQueue = new PriorityBlockingQueue<>(1024, Comparator.comparingLong(value -> value.priority)); this.memberConfig = MemberRegistry.getInstance().getMemberConfiguration(); - + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); ExecutorService alignerExecutor = Executors.newFixedThreadPool(1, KleinThreadFactory.create("data-aligner", true)); alignerExecutor.execute(() -> { while (!shutdown) { @@ -122,7 +123,7 @@ private void _learn(final long instanceId, final Endpoint target, final LearnCal LOG.info("start learn instanceId[{}] from node-{}", instanceId, target.getId()); LearnReq req = LearnReq.Builder.aLearnReq().instanceId(instanceId).nodeId(self.getSelf().getId()).build(); - client.sendRequestAsync(target, req, new AbstractInvokeCallback() { + client.sendRequestAsync(target, serializer.serialize(req), new AbstractInvokeCallback() { @Override public void error(final Throwable err) { LOG.error("learned instance[{}] from node-{}, {}", instanceId, target.getId(), err.getMessage()); @@ -138,11 +139,11 @@ public void complete(final LearnRes result) { } else if (result.isResult() == Sync.SINGLE) { LOG.info("learned instance[{}] from node-{}, sync.type: SINGLE", instanceId, target.getId()); Instance update = Instance.Builder.anInstance() - .instanceId(instanceId) - .proposalNo(result.getInstance().getProposalNo()) - .grantedValue(result.getInstance().getGrantedValue()) - .state(result.getInstance().getState()) - .build(); + .instanceId(instanceId) + .proposalNo(result.getInstance().getProposalNo()) + .grantedValue(result.getInstance().getGrantedValue()) + .state(result.getInstance().getState()) + .build(); try { logManager.getLock(instanceId).writeLock().lock(); @@ -168,12 +169,12 @@ private void _snapSync(final Endpoint target, final LearnCallback callback) { long checkpoint = -1; try { SnapSyncReq req = SnapSyncReq.Builder.aSnapSyncReq() - .nodeId(self.getSelf().getId()) - .proposalNo(self.getCurProposalNo()) - .memberConfigurationVersion(memberConfig.getVersion()) - .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) - .build(); - SnapSyncRes res = client.sendRequestSync(target, req, 1000); + .nodeId(self.getSelf().getId()) + .proposalNo(self.getCurProposalNo()) + .memberConfigurationVersion(memberConfig.getVersion()) + .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) + .build(); + SnapSyncRes res = serializer.deserialize(client.sendRequestSync(target, serializer.serialize(req), 1000)); RuntimeAccessor.getLearner().loadSnapSync(res.getImages()); checkpoint = res.getImages().values().stream().max(Comparator.comparingLong(Snap::getCheckpoint)).orElse(new Snap(checkpoint, null)).getCheckpoint(); diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/LearnerImpl.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/LearnerImpl.java index 3a55db7a..56a84f1d 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/LearnerImpl.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/LearnerImpl.java @@ -16,24 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.core; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.ofcoder.klein.consensus.facade.AbstractInvokeCallback; @@ -54,10 +36,27 @@ import com.ofcoder.klein.consensus.paxos.rpc.vo.Sync; import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.RpcClient; +import com.ofcoder.klein.serializer.Serializer; import com.ofcoder.klein.spi.ExtensionLoader; import com.ofcoder.klein.storage.facade.Instance; import com.ofcoder.klein.storage.facade.LogManager; import com.ofcoder.klein.storage.facade.Snap; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * learner implement. @@ -74,11 +73,13 @@ public class LearnerImpl implements Learner { private final DataAligner dataAligner; private final ConcurrentMap> applyCallback = new ConcurrentHashMap<>(); private ConsensusProp prop; + private final Serializer serializer; public LearnerImpl(final PaxosNode self) { this.self = self; this.memberConfig = MemberRegistry.getInstance().getMemberConfiguration(); this.dataAligner = new DataAligner(self); + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); } @Override @@ -98,15 +99,15 @@ public void shutdown() { @Override public long getLastAppliedInstanceId() { return sms.values().stream() - .mapToLong(SMApplier::getLastAppliedId) - .max().orElse(-1L); + .mapToLong(SMApplier::getLastAppliedId) + .max().orElse(-1L); } @Override public long getLastCheckpoint() { return sms.values().stream() - .mapToLong(SMApplier::getLastCheckpoint) - .max().orElse(-1L); + .mapToLong(SMApplier::getLastCheckpoint) + .max().orElse(-1L); } private Map generateSnap() { @@ -165,7 +166,7 @@ public void onLoadSnap(final long checkpoint) { } else { latch.countDown(); LOG.warn("load snap failure, group: {}, The state machine is not found." - + " It may be that Klein is starting and the state machine has not been loaded. Or, the state machine is unloaded.", group); + + " It may be that Klein is starting and the state machine has not been loaded. Or, the state machine is unloaded.", group); } }); @@ -193,8 +194,8 @@ public void replayLog(final String group, final long start) { break; } List replayData = instance.getGrantedValue().stream() - .filter(it -> StringUtils.equals(group, it.getGroup())) - .collect(Collectors.toList()); + .filter(it -> StringUtils.equals(group, it.getGroup())) + .collect(Collectors.toList()); if (CollectionUtils.isEmpty(replayData)) { continue; } @@ -231,11 +232,11 @@ public void confirm(final long instanceId, final String checksum, final List client.sendRequestAsync(it, req, new AbstractInvokeCallback() { - @Override - public void error(final Throwable err) { - LOG.error("send confirm msg to node-{}, instance[{}], {}", it.getId(), instanceId, err.getMessage()); - // do nothing - } + .forEach(it -> client.sendRequestAsync(it, content, new AbstractInvokeCallback() { + @Override + public void error(final Throwable err) { + LOG.error("send confirm msg to node-{}, instance[{}], {}", it.getId(), instanceId, err.getMessage()); + // do nothing + } - @Override - public void complete(final Serializable result) { - // do nothing - } - })); + @Override + public void complete(final Serializable result) { + // do nothing + } + })); } @Override @@ -278,7 +280,7 @@ public void alignData(final NodeState state) { } LOG.info("keepSameData, target[id: {}, cp: {}, maxAppliedInstanceId:{}], local[cp: {}, maxAppliedInstanceId:{}]", - target.getId(), targetCheckpoint, targetApplied, localCheckpoint, localApplied); + target.getId(), targetCheckpoint, targetApplied, localCheckpoint, localApplied); if (targetCheckpoint > localApplied || targetCheckpoint - localCheckpoint >= 100) { this.dataAligner.snap(target, result -> { if (result) { @@ -374,7 +376,7 @@ public void negotiationDone(final boolean result, final boolean dataChange) { } @Override - public void applyDone(final Map result) { + public void applyDone(final Map result) { apply(instanceId); } })); @@ -407,13 +409,13 @@ public void applyDone(final Map result) { private void _apply(final long instanceId) { List smAppliers = new ArrayList<>(sms.values()); List remove = applyCallback.remove(instanceId); - Map applyResult = new HashMap<>(); + Map applyResult = new HashMap<>(); smAppliers.stream().map(smApplier -> { - final CompletableFuture> complete = new CompletableFuture<>(); + final CompletableFuture> complete = new CompletableFuture<>(); smApplier.offer(SMApplier.Task.createApplyTask(instanceId, new SMApplier.TaskCallback() { @Override - public void onApply(final Map result) { + public void onApply(final Map result) { complete.complete(result); } })); @@ -423,7 +425,7 @@ public void onApply(final Map result) { return future.get(prop.getRoundTimeout(), TimeUnit.MILLISECONDS); } catch (Exception e) { LOG.error("apply sm error, instanceId: {}, {}", instanceId, e.getMessage()); - return new HashMap(); + return new HashMap(); } }).collect(Collectors.toList()).forEach(applyResult::putAll); @@ -452,7 +454,7 @@ public LearnRes handleLearnRequest(final LearnReq request) { if (instance == null || instance.getState() != Instance.State.CONFIRMED) { LOG.debug("NO_SUPPORT, learnInstance[{}], cp: {}, cur: {}", request.getInstanceId(), - RuntimeAccessor.getLearner().getLastCheckpoint(), self.getCurInstanceId()); + RuntimeAccessor.getLearner().getLastCheckpoint(), self.getCurInstanceId()); MasterState masterState = RuntimeAccessor.getMaster().getMaster(); if (masterState.getElectState().allowBoost()) { LOG.debug("NO_SUPPORT, but i am master, try boost: {}", request.getInstanceId()); @@ -481,9 +483,9 @@ public LearnRes handleLearnRequest(final LearnReq request) { public SnapSyncRes handleSnapSyncRequest(final SnapSyncReq req) { LOG.info("processing the pull snap message from node-{}", req.getNodeId()); SnapSyncRes res = SnapSyncRes.Builder.aSnapSyncRes() - .images(new HashMap<>()) - .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) - .build(); + .images(new HashMap<>()) + .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) + .build(); if (getLastAppliedInstanceId() - getLastCheckpoint() >= 100) { Map allSnaps = generateSnap(); res.getImages().putAll(allSnaps); diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/MasterImpl.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/MasterImpl.java index 71ae0880..b5dbe47d 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/MasterImpl.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/MasterImpl.java @@ -16,24 +16,11 @@ */ package com.ofcoder.klein.consensus.paxos.core; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.ofcoder.klein.common.util.ThreadExecutor; import com.ofcoder.klein.common.util.TrueTime; import com.ofcoder.klein.common.util.timer.RepeatedTimer; import com.ofcoder.klein.consensus.facade.AbstractInvokeCallback; -import com.ofcoder.klein.consensus.facade.Command; +import com.ofcoder.klein.consensus.facade.NoopCommand; import com.ofcoder.klein.consensus.facade.config.ConsensusProp; import com.ofcoder.klein.consensus.facade.quorum.Quorum; import com.ofcoder.klein.consensus.facade.quorum.QuorumFactory; @@ -53,7 +40,19 @@ import com.ofcoder.klein.consensus.paxos.rpc.vo.PreElectRes; import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.RpcClient; +import com.ofcoder.klein.serializer.Serializer; import com.ofcoder.klein.spi.ExtensionLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Master implement. @@ -74,11 +73,12 @@ public class MasterImpl implements Master { private RpcClient client; private ConsensusProp prop; private final AtomicBoolean electing = new AtomicBoolean(false); - private final AtomicBoolean changing = new AtomicBoolean(false); + private final Serializer serializer; public MasterImpl(final PaxosNode self) { this.self = self; this.memberConfig = MemberRegistry.getInstance().getMemberConfiguration(); + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); } @Override @@ -171,13 +171,14 @@ public void addListener(final Listener listener) { @Override public void searchMaster() { PreElectReq req = PreElectReq.Builder.aPreElectReq() - .memberConfigurationVersion(memberConfig.getVersion()) - .nodeId(self.getSelf().getId()) - .proposalNo(self.getCurProposalNo()) - .build(); + .memberConfigurationVersion(memberConfig.getVersion()) + .nodeId(self.getSelf().getId()) + .proposalNo(self.getCurProposalNo()) + .build(); + byte[] content = serializer.serialize(req); for (Endpoint it : memberConfig.getMembersWithout(self.getSelf().getId())) { try { - PreElectRes res = client.sendRequestSync(it, req); + PreElectRes res = serializer.deserialize(client.sendRequestSync(it, content)); LOG.debug("looking for master, node-{}: {}", it.getId(), res); if (res != null && res.getMaster() != null) { // restartWaitHb(); @@ -209,7 +210,7 @@ private void election() { req.setNodeId(self.getSelf().getId()); CountDownLatch latch = new CountDownLatch(1); - Proposal proposal = new Proposal(MasterSM.GROUP, req); + Proposal proposal = new Proposal(MasterSM.GROUP, serializer.serialize(req), true); RuntimeAccessor.getProposer().propose(proposal, (result, changed) -> { if (result && !changed) { @@ -235,10 +236,10 @@ private void newMaster(final CountDownLatch latch) { PaxosMemberConfiguration memberConfiguration = memberConfig.createRef(); NewMasterReq req = NewMasterReq.Builder.aNewMasterReq() - .nodeId(self.getSelf().getId()) - .proposalNo(self.getCurProposalNo()) - .memberConfigurationVersion(memberConfiguration.getVersion()) - .build(); + .nodeId(self.getSelf().getId()) + .proposalNo(self.getCurProposalNo()) + .memberConfigurationVersion(memberConfiguration.getVersion()) + .build(); Quorum quorum = QuorumFactory.createWriteQuorum(memberConfiguration); AtomicBoolean next = new AtomicBoolean(false); @@ -247,21 +248,22 @@ private void newMaster(final CountDownLatch latch) { handleNewMasterRes(self.getSelf(), masterRes, quorum, next, latch); // for other members + byte[] content = serializer.serialize(req); memberConfiguration.getMembersWithout(self.getSelf().getId()).forEach(it -> - client.sendRequestAsync(it, req, new AbstractInvokeCallback() { - @Override - public void error(final Throwable err) { - quorum.refuse(it); - if (quorum.isGranted() == Quorum.GrantResult.REFUSE && next.compareAndSet(false, true)) { - latch.countDown(); - } + client.sendRequestAsync(it, content, new AbstractInvokeCallback() { + @Override + public void error(final Throwable err) { + quorum.refuse(it); + if (quorum.isGranted() == Quorum.GrantResult.REFUSE && next.compareAndSet(false, true)) { + latch.countDown(); } + } - @Override - public void complete(final NewMasterRes result) { - handleNewMasterRes(it, result, quorum, next, latch); - } - })); + @Override + public void complete(final NewMasterRes result) { + handleNewMasterRes(it, result, quorum, next, latch); + } + })); } private void handleNewMasterRes(final Endpoint it, final NewMasterRes result, final Quorum quorum, final AtomicBoolean next, final CountDownLatch latch) { @@ -272,7 +274,7 @@ private void handleNewMasterRes(final Endpoint it, final NewMasterRes result, fi if (quorum.isGranted() == Quorum.GrantResult.PASS && next.compareAndSet(false, true)) { restartSendHbNow(); - RuntimeAccessor.getProposer().propose(Command.NOOP, (noopResult, dataChange) -> { + RuntimeAccessor.getProposer().propose(NoopCommand.NOOP, (noopResult, dataChange) -> { if (noopResult) { changeMaster(self.getSelf().getId()); } else { @@ -302,18 +304,18 @@ private boolean sendHeartbeat(final boolean probe) { final Quorum quorum = QuorumFactory.createWriteQuorum(memberConfiguration); final Ping req = Ping.Builder.aPing() + .nodeId(self.getSelf().getId()) + .proposalNo(self.getCurProposalNo()) + .memberConfigurationVersion(memberConfiguration.getVersion()) + .nodeState(NodeState.Builder.aNodeState() .nodeId(self.getSelf().getId()) - .proposalNo(self.getCurProposalNo()) - .memberConfigurationVersion(memberConfiguration.getVersion()) - .nodeState(NodeState.Builder.aNodeState() - .nodeId(self.getSelf().getId()) - .maxInstanceId(curInstanceId) - .lastCheckpoint(lastCheckpoint) - .lastAppliedInstanceId(RuntimeAccessor.getLearner().getLastAppliedInstanceId()) - .build()) - .timestampMs(TrueTime.currentTimeMillis()) - .probe(probe) - .build(); + .maxInstanceId(curInstanceId) + .lastCheckpoint(lastCheckpoint) + .lastAppliedInstanceId(RuntimeAccessor.getLearner().getLastAppliedInstanceId()) + .build()) + .timestampMs(TrueTime.currentTimeMillis()) + .probe(probe) + .build(); final CompletableFuture complete = new CompletableFuture<>(); // for self @@ -325,8 +327,9 @@ private boolean sendHeartbeat(final boolean probe) { } // for other members + byte[] content = serializer.serialize(req); memberConfiguration.getMembersWithout(self.getSelf().getId()).forEach(it -> { - client.sendRequestAsync(it, req, new AbstractInvokeCallback() { + client.sendRequestAsync(it, content, new AbstractInvokeCallback() { @Override public void error(final Throwable err) { LOG.debug("heartbeat, node: " + it.getId() + ", " + err.getMessage()); @@ -379,7 +382,7 @@ public boolean onReceiveHeartbeat(final Ping request, final boolean isSelf) { return true; } else { LOG.debug("receive heartbeat from node-{}, result: false. local.master: {}, req.version: {}", request.getNodeId(), - memberConfig, request.getMemberConfigurationVersion()); + memberConfig, request.getMemberConfigurationVersion()); return false; } } @@ -392,18 +395,18 @@ public NewMasterRes onReceiveNewMaster(final NewMasterReq request, final boolean restartWaitHb(); } return NewMasterRes.Builder.aNewMasterRes() - .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) - .curInstanceId(self.getCurInstanceId()) - .lastAppliedId(RuntimeAccessor.getLearner().getLastAppliedInstanceId()) - .granted(true) - .build(); + .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) + .curInstanceId(self.getCurInstanceId()) + .lastAppliedId(RuntimeAccessor.getLearner().getLastAppliedInstanceId()) + .granted(true) + .build(); } else { return NewMasterRes.Builder.aNewMasterRes() - .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) - .curInstanceId(self.getCurInstanceId()) - .lastAppliedId(RuntimeAccessor.getLearner().getLastAppliedInstanceId()) - .granted(false) - .build(); + .checkpoint(RuntimeAccessor.getLearner().getLastCheckpoint()) + .curInstanceId(self.getCurInstanceId()) + .lastAppliedId(RuntimeAccessor.getLearner().getLastAppliedInstanceId()) + .granted(false) + .build(); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposeDone.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposeDone.java index 5afac688..b7fbb6b7 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposeDone.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposeDone.java @@ -43,7 +43,7 @@ public interface ProposeDone { * the key is enter the value of the state machine * the value is state machine output */ - default void applyDone(Map result) { + default void applyDone(Map result) { // for subclass } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposerImpl.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposerImpl.java index 672bc5e4..1b0b8c2f 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposerImpl.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/ProposerImpl.java @@ -16,23 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.core; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Set; -import java.util.Vector; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.lmax.disruptor.BlockingWaitStrategy; @@ -45,16 +28,15 @@ import com.ofcoder.klein.common.disruptor.DisruptorBuilder; import com.ofcoder.klein.common.disruptor.DisruptorExceptionHandler; import com.ofcoder.klein.common.exception.ShutdownException; -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.common.util.ChecksumUtil; import com.ofcoder.klein.common.util.KleinThreadFactory; import com.ofcoder.klein.common.util.ThreadExecutor; import com.ofcoder.klein.consensus.facade.AbstractInvokeCallback; import com.ofcoder.klein.consensus.facade.Command; +import com.ofcoder.klein.consensus.facade.NoopCommand; import com.ofcoder.klein.consensus.facade.config.ConsensusProp; import com.ofcoder.klein.consensus.facade.exception.ConsensusException; import com.ofcoder.klein.consensus.facade.quorum.SingleQuorum; -import com.ofcoder.klein.consensus.facade.sm.SystemOp; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.Proposal; import com.ofcoder.klein.consensus.paxos.core.sm.MemberRegistry; @@ -66,9 +48,25 @@ import com.ofcoder.klein.consensus.paxos.rpc.vo.PrepareRes; import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.RpcClient; +import com.ofcoder.klein.serializer.Serializer; import com.ofcoder.klein.spi.ExtensionLoader; import com.ofcoder.klein.storage.facade.Instance; import com.ofcoder.klein.storage.facade.LogManager; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Set; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Proposer implement. @@ -93,10 +91,12 @@ public class ProposerImpl implements Proposer { private final ConcurrentMap> seenInstances = new ConcurrentHashMap<>(); private final Set runningInstance = Collections.newSetFromMap(new ConcurrentHashMap<>()); private LogManager logManager; + private final Serializer serializer; public ProposerImpl(final PaxosNode self) { this.self = self; this.memberConfig = MemberRegistry.getInstance().getMemberConfiguration(); + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); } @Override @@ -109,12 +109,12 @@ public void init(final ConsensusProp op) { // Disruptor to run propose. proposeDisruptor = DisruptorBuilder.newInstance() - .setRingBufferSize(RUNNING_BUFFER_SIZE) - .setEventFactory(ProposalWithDone::new) - .setThreadFactory(KleinThreadFactory.create("paxos-propose-disruptor-", true)) - .setProducerType(ProducerType.MULTI) - .setWaitStrategy(new BlockingWaitStrategy()) - .build(); + .setRingBufferSize(RUNNING_BUFFER_SIZE) + .setEventFactory(ProposalWithDone::new) + .setThreadFactory(KleinThreadFactory.create("paxos-propose-disruptor-", true)) + .setProducerType(ProducerType.MULTI) + .setWaitStrategy(new BlockingWaitStrategy()) + .build(); ProposeEventHandler eventHandler = new ProposeEventHandler(this.prop.getBatchSize()); proposeDisruptor.handleEventsWith(eventHandler); proposeDisruptor.setDefaultExceptionHandler(new DisruptorExceptionHandler(getClass().getSimpleName())); @@ -208,39 +208,40 @@ private void _accept(final long grantedProposalNo, final ProposeContext ctxt, fi // choose valid proposal, and calculate checksum. List originalProposals = ctxt.getDataWithCallback().stream().map(ProposalWithDone::getProposal).collect(Collectors.toList()); - String originalChecksum = ChecksumUtil.md5(Hessian2Util.serialize(originalProposals)); + String originalChecksum = ChecksumUtil.md5(serializer.serialize(originalProposals)); ctxt.setDataChange(seenInstances.containsKey(ctxt.getInstanceId()) - && CollectionUtils.isNotEmpty(seenInstances.get(ctxt.getInstanceId()).getGrantedValue()) - && !StringUtils.equals(seenInstances.get(ctxt.getInstanceId()).getChecksum(), originalChecksum)); + && CollectionUtils.isNotEmpty(seenInstances.get(ctxt.getInstanceId()).getGrantedValue()) + && !StringUtils.equals(seenInstances.get(ctxt.getInstanceId()).getChecksum(), originalChecksum)); ctxt.setConsensusData(ctxt.isDataChange() ? seenInstances.get(ctxt.getInstanceId()).getGrantedValue() - : originalProposals); + : originalProposals); ctxt.setConsensusChecksum(ctxt.isDataChange() ? seenInstances.get(ctxt.getInstanceId()).getChecksum() : originalChecksum); ctxt.setGrantedProposalNo(grantedProposalNo); final PaxosMemberConfiguration memberConfiguration = ctxt.getMemberConfiguration().createRef(); final AcceptReq req = AcceptReq.Builder.anAcceptReq() - .nodeId(self.getSelf().getId()) - .instanceId(ctxt.getInstanceId()) - .proposalNo(ctxt.getGrantedProposalNo()) - .data(ctxt.getConsensusData()) - .checksum(ctxt.getConsensusChecksum()) - .memberConfigurationVersion(memberConfiguration.getVersion()) - .build(); + .nodeId(self.getSelf().getId()) + .instanceId(ctxt.getInstanceId()) + .proposalNo(ctxt.getGrantedProposalNo()) + .data(ctxt.getConsensusData()) + .checksum(ctxt.getConsensusChecksum()) + .memberConfigurationVersion(memberConfiguration.getVersion()) + .build(); // for self AcceptRes res = RuntimeAccessor.getAcceptor().handleAcceptRequest(req, true); handleAcceptResponse(ctxt, callback, res, self.getSelf()); // for other members + byte[] content = serializer.serialize(req); memberConfiguration.getMembersWithout(self.getSelf().getId()).forEach(it -> { - client.sendRequestAsync(it, req, new AbstractInvokeCallback() { + client.sendRequestAsync(it, content, new AbstractInvokeCallback() { @Override public void error(final Throwable err) { LOG.error("send accept msg to node-{}, proposalNo: {}, instanceId: {}, occur exception, {}", it.getId(), grantedProposalNo, ctxt.getInstanceId(), err.getMessage()); ctxt.getAcceptQuorum().refuse(it); if (ctxt.getAcceptQuorum().isGranted() == SingleQuorum.GrantResult.REFUSE - && ctxt.getAcceptNexted().compareAndSet(false, true)) { + && ctxt.getAcceptNexted().compareAndSet(false, true)) { RuntimeAccessor.getSkipPrepare().compareAndSet(PrepareState.PREPARED, PrepareState.NO_PREPARE); ThreadExecutor.execute(() -> prepare(ctxt.createUntappedRef(), new PrepareCallback())); @@ -259,12 +260,12 @@ public void complete(final AcceptRes result) { private void handleAcceptResponse(final ProposeContext ctxt, final PhaseCallback.AcceptPhaseCallback callback, final AcceptRes result, final Endpoint it) { LOG.info("handling node-{}'s accept response, result: {}, local.proposalNo: {}, instanceId: {}, remote.proposalNo: {}", - result.getNodeId(), result.getResult(), ctxt.getGrantedProposalNo(), ctxt.getInstanceId(), result.getCurProposalNo()); + result.getNodeId(), result.getResult(), ctxt.getGrantedProposalNo(), ctxt.getInstanceId(), result.getCurProposalNo()); self.updateCurProposalNo(result.getCurProposalNo()); self.updateCurInstanceId(result.getCurInstanceId()); if (result.getInstanceState() == Instance.State.CONFIRMED - && ctxt.getAcceptNexted().compareAndSet(false, true)) { + && ctxt.getAcceptNexted().compareAndSet(false, true)) { callback.learn(ctxt, result.getNodeState()); return; } @@ -272,7 +273,7 @@ private void handleAcceptResponse(final ProposeContext ctxt, final PhaseCallback if (result.getResult()) { ctxt.getAcceptQuorum().grant(it); if (ctxt.getAcceptQuorum().isGranted() == SingleQuorum.GrantResult.PASS - && ctxt.getAcceptNexted().compareAndSet(false, true)) { + && ctxt.getAcceptNexted().compareAndSet(false, true)) { // do learn phase and return client. callback.granted(ctxt); } @@ -281,7 +282,7 @@ private void handleAcceptResponse(final ProposeContext ctxt, final PhaseCallback // do prepare phase if (ctxt.getAcceptQuorum().isGranted() == SingleQuorum.GrantResult.REFUSE - && ctxt.getAcceptNexted().compareAndSet(false, true)) { + && ctxt.getAcceptNexted().compareAndSet(false, true)) { RuntimeAccessor.getSkipPrepare().compareAndSet(PrepareState.PREPARED, PrepareState.NO_PREPARE); ThreadExecutor.execute(() -> prepare(ctxt.createUntappedRef(), new PrepareCallback())); } @@ -299,7 +300,7 @@ public void tryBoost(final Long instanceId, final ProposeDone done) { protected Long create() { return instanceId; } - }, Lists.newArrayList(new ProposalWithDone(Command.NOOP, done))); + }, Lists.newArrayList(new ProposalWithDone(NoopCommand.NOOP, done))); prepare(ctxt, new PrepareCallback()); } @@ -381,24 +382,25 @@ private void _prepare(final ProposeContext ctxt, final PhaseCallback.PreparePhas LOG.info("start prepare phase, the {} retry, proposalNo: {}", ctxt.getTimes(), proposalNo); PrepareReq req = PrepareReq.Builder.aPrepareReq() - .nodeId(self.getSelf().getId()) - .proposalNo(proposalNo) - .memberConfigurationVersion(memberConfiguration.getVersion()) - .build(); + .nodeId(self.getSelf().getId()) + .proposalNo(proposalNo) + .memberConfigurationVersion(memberConfiguration.getVersion()) + .build(); // for self PrepareRes prepareRes = RuntimeAccessor.getAcceptor().handlePrepareRequest(req, true); handlePrepareResponse(proposalNo, ctxt, callback, prepareRes, self.getSelf()); // for other members + byte[] content = serializer.serialize(req); memberConfiguration.getMembersWithout(self.getSelf().getId()).forEach(it -> { - client.sendRequestAsync(it, req, new AbstractInvokeCallback() { + client.sendRequestAsync(it, content, new AbstractInvokeCallback() { @Override public void error(final Throwable err) { LOG.error("send prepare msg to node-{}, proposalNo: {}, occur exception, {}", it.getId(), proposalNo, err.getMessage()); ctxt.getPrepareQuorum().refuse(it); if (ctxt.getPrepareQuorum().isGranted() == SingleQuorum.GrantResult.REFUSE - && ctxt.getPrepareNexted().compareAndSet(false, true)) { + && ctxt.getPrepareNexted().compareAndSet(false, true)) { ThreadExecutor.execute(() -> _prepare(ctxt.createUntappedRef(), callback)); } } @@ -433,7 +435,7 @@ private void handlePrepareResponse(final long proposalNo, final ProposeContext c boolean grant = ctxt.getPrepareQuorum().grant(it); LOG.debug("handling node-{}'s prepare response, grant: {}, {}", result.getNodeId(), grant, ctxt.getPrepareQuorum().isGranted()); if (ctxt.getPrepareQuorum().isGranted() == SingleQuorum.GrantResult.PASS - && ctxt.getPrepareNexted().compareAndSet(false, true)) { + && ctxt.getPrepareNexted().compareAndSet(false, true)) { // do accept phase. callback.granted(proposalNo, ctxt); } @@ -443,7 +445,7 @@ private void handlePrepareResponse(final long proposalNo, final ProposeContext c // do prepare phase if (ctxt.getPrepareQuorum().isGranted() == SingleQuorum.GrantResult.REFUSE - && ctxt.getPrepareNexted().compareAndSet(false, true)) { + && ctxt.getPrepareNexted().compareAndSet(false, true)) { ThreadExecutor.execute(() -> _prepare(ctxt.createUntappedRef(), callback)); } @@ -491,9 +493,9 @@ public void onEvent(final ProposalWithDone event, final long sequence, final boo } this.tasks.add(event); - if (event.getProposal().getData() instanceof SystemOp - || (RuntimeAccessor.getMaster().getMaster().getElectState().allowPropose() - && (this.tasks.size() >= batchSize || endOfBatch))) { + if (event.getProposal().getIfSystemOp() + || (RuntimeAccessor.getMaster().getMaster().getElectState().allowPropose() + && (this.tasks.size() >= batchSize || endOfBatch))) { handle(); } } @@ -525,7 +527,7 @@ public void granted(final ProposeContext context) { ProposerImpl.this.seenInstances.remove(context.getInstanceId()); context.getDataWithCallback().forEach(it -> - it.getDone().negotiationDone(true, context.isDataChange())); + it.getDone().negotiationDone(true, context.isDataChange())); ThreadExecutor.execute(() -> { // do confirm diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MasterSM.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MasterSM.java index abfea234..9d66c2de 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MasterSM.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MasterSM.java @@ -16,12 +16,13 @@ */ package com.ofcoder.klein.consensus.paxos.core.sm; -import java.io.Serializable; - +import com.ofcoder.klein.consensus.facade.sm.AbstractSM; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.ofcoder.klein.consensus.facade.sm.AbstractSM; +import java.io.Serializable; /** * master sm. @@ -32,16 +33,19 @@ public class MasterSM extends AbstractSM { public static final String GROUP = "master"; private static final Logger LOG = LoggerFactory.getLogger(MasterSM.class); private final PaxosMemberConfiguration memberConfig; + private final Serializer serializer; public MasterSM() { this.memberConfig = MemberRegistry.getInstance().getMemberConfiguration(); + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); } @Override - public Object apply(final Object data) { + public byte[] apply(final byte[] data) { LOG.info("MasterSM apply, {}", data.getClass().getSimpleName()); - if (data instanceof ElectionOp) { - electMaster((ElectionOp) data); + Object deserialize = serializer.deserialize(data); + if (deserialize instanceof ElectionOp) { + electMaster((ElectionOp) deserialize); } else { throw new IllegalArgumentException("Unknown data type: " + data.getClass().getSimpleName()); } @@ -53,17 +57,18 @@ private void electMaster(final ElectionOp op) { } @Override - public Object makeImage() { - return new Image(); + public byte[] makeImage() { + return new byte[0]; } @Override - public void loadImage(final Object snap) { + public void loadImage(final byte[] snap) { // do nothing. } /** * Fake image. */ - public static class Image implements Serializable { } + public static class Image implements Serializable { + } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MemberManagerSM.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MemberManagerSM.java index 247b08a3..a472300a 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MemberManagerSM.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/core/sm/MemberManagerSM.java @@ -16,6 +16,8 @@ */ package com.ofcoder.klein.consensus.paxos.core.sm; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,16 +32,19 @@ public class MemberManagerSM extends AbstractSM { public static final String GROUP = "member_manager"; private static final Logger LOG = LoggerFactory.getLogger(MemberManagerSM.class); private final PaxosMemberConfiguration memberConfig; + private final Serializer serializer; public MemberManagerSM() { this.memberConfig = MemberRegistry.getInstance().getMemberConfiguration(); + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); } @Override - public Object apply(final Object data) { + public byte[] apply(final byte[] data) { LOG.debug("MemberManagerSM apply, {}", data.getClass().getSimpleName()); - if (data instanceof ChangeMemberOp) { - ChangeMemberOp op = (ChangeMemberOp) data; + Object deserialize = serializer.deserialize(data); + if (deserialize instanceof ChangeMemberOp) { + ChangeMemberOp op = (ChangeMemberOp) deserialize; if (op.getPhase() == ChangeMemberOp.FIRST_PHASE) { memberConfig.seenNewConfig(op.getNewConfig()); } else if (op.getPhase() == ChangeMemberOp.SECOND_PHASE) { @@ -53,16 +58,17 @@ public Object apply(final Object data) { } @Override - public Object makeImage() { - return MemberRegistry.getInstance().getMemberConfiguration().createRef(); + public byte[] makeImage() { + return serializer.serialize(MemberRegistry.getInstance().getMemberConfiguration().createRef()); } @Override - public void loadImage(final Object snap) { + public void loadImage(final byte[] snap) { LOG.info("LOAD SNAP: {}", snap); - if (!(snap instanceof PaxosMemberConfiguration)) { + Object deserialize = serializer.deserialize(snap); + if (!(deserialize instanceof PaxosMemberConfiguration)) { return; } - MemberRegistry.getInstance().loadSnap((PaxosMemberConfiguration) snap); + MemberRegistry.getInstance().loadSnap((PaxosMemberConfiguration) deserialize); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/AcceptProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/AcceptProcessor.java index e630d7c8..2fe459a8 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/AcceptProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/AcceptProcessor.java @@ -16,12 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; @@ -29,6 +23,8 @@ import com.ofcoder.klein.consensus.paxos.rpc.vo.AcceptReq; import com.ofcoder.klein.consensus.paxos.rpc.vo.AcceptRes; import com.ofcoder.klein.rpc.facade.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Accept Processor. @@ -52,12 +48,12 @@ public void handleRequest(final AcceptReq request, final RpcContext context) { if (!MemberRegistry.getInstance().getMemberConfiguration().isValid(request.getNodeId())) { LOG.error("msg type: accept, from nodeId[{}] not in my membership(or i'm null membership), skip this message. ", - request.getNodeId()); + request.getNodeId()); return; } AcceptRes res = RuntimeAccessor.getAcceptor().handleAcceptRequest(request, false); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(res))); + response(res, context); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ConfirmProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ConfirmProcessor.java index c1e3bb83..87f017d7 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ConfirmProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ConfirmProcessor.java @@ -16,19 +16,15 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; -import java.util.HashMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; import com.ofcoder.klein.consensus.paxos.core.sm.MemberRegistry; import com.ofcoder.klein.consensus.paxos.rpc.vo.ConfirmReq; import com.ofcoder.klein.rpc.facade.RpcContext; +import java.util.HashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Confirm Request Processor. @@ -51,11 +47,11 @@ public String service() { public void handleRequest(final ConfirmReq request, final RpcContext context) { if (!MemberRegistry.getInstance().getMemberConfiguration().isValid(request.getNodeId())) { LOG.error("msg type: confirm, from nodeId[{}] not in my membership(or i'm null membership), skip this message. ", - request.getNodeId()); + request.getNodeId()); return; } RuntimeAccessor.getLearner().handleConfirmRequest(request, false); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(new HashMap<>()))); + response(new HashMap<>(), context); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ElasticProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ElasticProcessor.java index 057e0b8e..8fa976ce 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ElasticProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/ElasticProcessor.java @@ -16,13 +16,7 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.common.collect.Lists; -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.facade.Cluster; import com.ofcoder.klein.consensus.paxos.PaxosNode; @@ -30,6 +24,8 @@ import com.ofcoder.klein.consensus.paxos.rpc.vo.ElasticReq; import com.ofcoder.klein.consensus.paxos.rpc.vo.ElasticRes; import com.ofcoder.klein.rpc.facade.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Elastic Processor. @@ -74,8 +70,8 @@ public void handleRequest(final ElasticReq request, final RpcContext context) { ElasticRes res = new ElasticRes(); res.setResult(true); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(res))); + response(res, context); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/HeartbeatProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/HeartbeatProcessor.java index 5e19185b..23f5b51d 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/HeartbeatProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/HeartbeatProcessor.java @@ -16,9 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; @@ -41,7 +38,7 @@ public HeartbeatProcessor(final PaxosNode self) { @Override public void handleRequest(final Ping request, final RpcContext context) { if (RuntimeAccessor.getMaster().onReceiveHeartbeat(request, false)) { - context.response(ByteBuffer.wrap(Hessian2Util.serialize(new Pong()))); + response(new Pong(), context); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/LearnProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/LearnProcessor.java index aace0fcc..4474f7be 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/LearnProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/LearnProcessor.java @@ -16,18 +16,14 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; import com.ofcoder.klein.consensus.paxos.rpc.vo.LearnReq; import com.ofcoder.klein.consensus.paxos.rpc.vo.LearnRes; import com.ofcoder.klein.rpc.facade.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Learn Request Processor. @@ -49,7 +45,7 @@ public String service() { @Override public void handleRequest(final LearnReq request, final RpcContext context) { LearnRes res = RuntimeAccessor.getLearner().handleLearnRequest(request); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(res))); + response(res, context); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/NewMasterProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/NewMasterProcessor.java index a3e5736e..e78f7143 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/NewMasterProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/NewMasterProcessor.java @@ -16,9 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; @@ -40,7 +37,7 @@ public NewMasterProcessor(final PaxosNode self) { @Override public void handleRequest(final NewMasterReq request, final RpcContext context) { NewMasterRes newMasterRes = RuntimeAccessor.getMaster().onReceiveNewMaster(request, false); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(newMasterRes))); + response(newMasterRes, context); } @Override diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PreElectProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PreElectProcessor.java index fbb493f9..bb27c4da 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PreElectProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PreElectProcessor.java @@ -16,9 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; @@ -40,11 +37,9 @@ public PreElectProcessor(final PaxosNode self) { @Override public void handleRequest(final PreElectReq request, final RpcContext context) { - context.response( - ByteBuffer.wrap(Hessian2Util.serialize(PreElectRes.Builder.aPreElectRes().master( - RuntimeAccessor.getMaster().getMaster().getMaster() - ).build())) - ); + response(PreElectRes.Builder.aPreElectRes().master( + RuntimeAccessor.getMaster().getMaster().getMaster() + ).build(), context); } @Override diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PrepareProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PrepareProcessor.java index 62e4125b..4fd8f73a 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PrepareProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/PrepareProcessor.java @@ -16,12 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; @@ -29,6 +23,8 @@ import com.ofcoder.klein.consensus.paxos.rpc.vo.PrepareReq; import com.ofcoder.klein.consensus.paxos.rpc.vo.PrepareRes; import com.ofcoder.klein.rpc.facade.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Prepare Request Processor. @@ -52,11 +48,11 @@ public void handleRequest(final PrepareReq request, final RpcContext context) { if (!MemberRegistry.getInstance().getMemberConfiguration().isValid(request.getNodeId())) { LOG.error("msg type: prepare, from nodeId[{}] not in my membership(or i'm null membership), skip this message. ", - request.getNodeId()); + request.getNodeId()); return; } PrepareRes prepareRes = RuntimeAccessor.getAcceptor().handlePrepareRequest(request, false); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(prepareRes))); + response(prepareRes, context); } } diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/RedirectProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/RedirectProcessor.java index b28f9d76..b992c180 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/RedirectProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/RedirectProcessor.java @@ -16,22 +16,17 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.io.Serializable; -import java.nio.ByteBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.facade.Result; import com.ofcoder.klein.consensus.facade.config.ConsensusProp; -import com.ofcoder.klein.consensus.paxos.UniversalProposeProxy; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.ProposeProxy; +import com.ofcoder.klein.consensus.paxos.UniversalProposeProxy; import com.ofcoder.klein.consensus.paxos.rpc.vo.RedirectReq; import com.ofcoder.klein.consensus.paxos.rpc.vo.RedirectRes; import com.ofcoder.klein.rpc.facade.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Redirect Request Processor. @@ -59,13 +54,14 @@ public void handleRequest(final RedirectReq request, final RpcContext context) { LOG.info("receive redirect msg, redirect: {}", RedirectReq.fmtRedirect(request.getRedirect())); switch (request.getRedirect()) { case RedirectReq.TRANSACTION_REQUEST: - Result proposeResult = directProposeProxy.propose(request.getProposal(), request.isApply()); + Result proposeResult = directProposeProxy.propose(request.getProposal(), request.isApply()); LOG.info("receive transfer request, apply: {}, result: {}", request.isApply(), proposeResult.getState()); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(RedirectRes.Builder - .aRedirectResp() - .proposeResult(proposeResult) - .build() - ))); + RedirectRes res = RedirectRes.Builder + .aRedirectResp() + .proposeResult(proposeResult) + .build(); + + response(res, context); break; default: break; diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/SnapSyncProcessor.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/SnapSyncProcessor.java index 8c04a9b4..b6b7f628 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/SnapSyncProcessor.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/SnapSyncProcessor.java @@ -16,9 +16,6 @@ */ package com.ofcoder.klein.consensus.paxos.rpc; -import java.nio.ByteBuffer; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.consensus.paxos.PaxosNode; import com.ofcoder.klein.consensus.paxos.core.RuntimeAccessor; @@ -40,7 +37,7 @@ public SnapSyncProcessor(final PaxosNode self) { @Override public void handleRequest(final SnapSyncReq request, final RpcContext context) { SnapSyncRes snapSyncRes = RuntimeAccessor.getLearner().handleSnapSyncRequest(request); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(snapSyncRes))); + response(snapSyncRes, context); } @Override diff --git a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/vo/RedirectRes.java b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/vo/RedirectRes.java index 6d3d8bbb..69b3de4d 100644 --- a/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/vo/RedirectRes.java +++ b/klein-consensus/klein-consensus-paxos/src/main/java/com/ofcoder/klein/consensus/paxos/rpc/vo/RedirectRes.java @@ -27,13 +27,13 @@ */ public class RedirectRes implements Serializable { private boolean changeResult; - private Result proposeResult; + private Result proposeResult; public boolean isChangeResult() { return changeResult; } - public Result getProposeResult() { + public Result getProposeResult() { return proposeResult; } @@ -47,7 +47,7 @@ public String toString() { public static final class Builder { private boolean changeResult; - private Result proposeResult; + private Result proposeResult; private Builder() { } @@ -78,7 +78,7 @@ public Builder changeResult(final boolean changeResult) { * @param proposeResult proposeResult * @return Builder */ - public Builder proposeResult(final Result proposeResult) { + public Builder proposeResult(final Result proposeResult) { this.proposeResult = proposeResult; return this; } diff --git a/klein-consensus/klein-consensus-paxos/src/test/java/com/ofcoder/klein/consensus/paxos/ProposalTest.java b/klein-consensus/klein-consensus-paxos/src/test/java/com/ofcoder/klein/consensus/paxos/ProposalTest.java index 97c8e7e6..d49640c9 100644 --- a/klein-consensus/klein-consensus-paxos/src/test/java/com/ofcoder/klein/consensus/paxos/ProposalTest.java +++ b/klein-consensus/klein-consensus-paxos/src/test/java/com/ofcoder/klein/consensus/paxos/ProposalTest.java @@ -1,5 +1,6 @@ package com.ofcoder.klein.consensus.paxos; +import com.ofcoder.klein.serializer.hessian2.Hessian2Util; import junit.framework.TestCase; public class ProposalTest extends TestCase { @@ -8,7 +9,7 @@ public void testGetGroup() { Proposal proposal = new Proposal(); assertNull(proposal.getGroup()); - proposal = new Proposal("group1", "data1"); + proposal = new Proposal("group1", Hessian2Util.serialize("data1"), false); assertEquals("group1", proposal.getGroup()); proposal.setGroup("group2"); diff --git a/klein-core/pom.xml b/klein-core/pom.xml index d27b7597..84fc652e 100644 --- a/klein-core/pom.xml +++ b/klein-core/pom.xml @@ -33,6 +33,10 @@ com.ofcoder.klein.storage.file klein-storage-file + + com.ofcoder.klein.serializer.hessian2 + klein-serializer-hessian2 + org.mapdb mapdb diff --git a/klein-core/src/main/java/com/ofcoder/klein/core/GroupWrapper.java b/klein-core/src/main/java/com/ofcoder/klein/core/GroupWrapper.java index efb52215..99a49dd4 100644 --- a/klein-core/src/main/java/com/ofcoder/klein/core/GroupWrapper.java +++ b/klein-core/src/main/java/com/ofcoder/klein/core/GroupWrapper.java @@ -16,10 +16,9 @@ */ package com.ofcoder.klein.core; -import java.io.Serializable; - import com.ofcoder.klein.consensus.facade.Consensus; import com.ofcoder.klein.consensus.facade.Result; +import com.ofcoder.klein.serializer.hessian2.Hessian2Util; import com.ofcoder.klein.spi.ExtensionLoader; /** @@ -41,11 +40,9 @@ public GroupWrapper(final String group) { * * @param data Client data, type is Serializable * e.g. The input value of the state machine - * @param result type - * @param request type * @return whether success */ - public Result propose(final E data) { + public Result propose(final byte[] data) { return propose(data, false); } @@ -56,12 +53,10 @@ public Result propose(final * e.g. The input value of the state machine * @param apply Whether you need to wait until the state machine is applied * If true, wait until the state machine is applied before returning - * @param result type - * @param request type * @return whether success */ - public Result propose(final E data, final boolean apply) { - return this.consensus.propose(group, data, apply); + public Result propose(final byte[] data, final boolean apply) { + return this.consensus.propose(group, Hessian2Util.serialize(data), apply); } /** @@ -69,11 +64,9 @@ public Result propose(final * * @param data Client data, type is Serializable * e.g. The input value of the state machine - * @param result type - * @param request type * @return whether success */ - public Result read(final E data) { + public Result read(final byte[] data) { return propose(data, true); } } diff --git a/klein-core/src/main/java/com/ofcoder/klein/core/cache/CacheSM.java b/klein-core/src/main/java/com/ofcoder/klein/core/cache/CacheSM.java index 59203b3d..609597a1 100644 --- a/klein-core/src/main/java/com/ofcoder/klein/core/cache/CacheSM.java +++ b/klein-core/src/main/java/com/ofcoder/klein/core/cache/CacheSM.java @@ -20,6 +20,8 @@ import java.util.HashMap; import java.util.Map; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,8 +39,10 @@ public class CacheSM extends AbstractSM { private final Map containers = new HashMap<>(); private final CacheProp cacheProp; private final String temp; + private final Serializer serializer; public CacheSM(final CacheProp cacheProp) { + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); this.cacheProp = cacheProp; this.temp = this.cacheProp.getDataPath() + File.separator + cacheProp.getId() + File.separator + "temp"; File file = new File(temp); @@ -59,20 +63,23 @@ private CacheContainer getCacheContainer(final String cacheName) { } @Override - public Object apply(final Object data) { + public byte[] apply(final byte[] original) { + Object data = serializer.deserialize(original); + if (!(data instanceof CacheMessage)) { LOG.warn("apply data, UNKNOWN PARAMETER TYPE, data type is {}", data.getClass().getName()); return null; } CacheMessage message = (CacheMessage) data; CacheContainer container = getCacheContainer(message.getCacheName()); + Object result; switch (message.getOp()) { case CacheMessage.PUT: container.put(message.getKey(), message.getData(), message.getExpire()); break; case CacheMessage.GET: - Object o = container.get(message.getKey()); - return o; + result = container.get(message.getKey()); + return serializer.serialize(result); case CacheMessage.INVALIDATE: container.remove(message.getKey()); break; @@ -80,9 +87,11 @@ public Object apply(final Object data) { container.clear(); break; case CacheMessage.PUTIFPRESENT: - return container.putIfAbsent(message.getKey(), message.getData(), message.getExpire()); + result = container.putIfAbsent(message.getKey(), message.getData(), message.getExpire()); + return serializer.serialize(result); case CacheMessage.EXIST: - return container.containsKey(message.getKey()); + result = container.containsKey(message.getKey()); + return serializer.serialize(result); default: LOG.warn("apply data, UNKNOWN OPERATION, operation type is {}", message.getOp()); break; @@ -91,15 +100,16 @@ public Object apply(final Object data) { } @Override - public Object makeImage() { + public byte[] makeImage() { Map result = new HashMap<>(); containers.forEach((cacheName, container) -> result.put(cacheName, container.makeImage())); - return result; + return serializer.serialize(result); } @SuppressWarnings("unchecked") @Override - public void loadImage(final Object snap) { + public void loadImage(final byte[] original) { + Object snap = serializer.deserialize(original); if (!(snap instanceof Map)) { return; } diff --git a/klein-core/src/main/java/com/ofcoder/klein/core/cache/KleinCacheImpl.java b/klein-core/src/main/java/com/ofcoder/klein/core/cache/KleinCacheImpl.java index 28c90ef7..d06fa1e7 100644 --- a/klein-core/src/main/java/com/ofcoder/klein/core/cache/KleinCacheImpl.java +++ b/klein-core/src/main/java/com/ofcoder/klein/core/cache/KleinCacheImpl.java @@ -17,10 +17,13 @@ package com.ofcoder.klein.core.cache; import com.ofcoder.klein.common.exception.KleinException; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.serializer.hessian2.Hessian2Util; import com.ofcoder.klein.common.util.TrueTime; import com.ofcoder.klein.consensus.facade.Result; import com.ofcoder.klein.consensus.facade.sm.SMRegistry; import com.ofcoder.klein.core.GroupWrapper; +import com.ofcoder.klein.spi.ExtensionLoader; import java.io.Serializable; import java.util.concurrent.TimeUnit; @@ -33,6 +36,7 @@ public class KleinCacheImpl implements KleinCache { protected GroupWrapper consensus; private final String cacheName; + private final Serializer serializer; /** * Return a new cache container. @@ -41,6 +45,7 @@ public class KleinCacheImpl implements KleinCache { */ public KleinCacheImpl(final String cacheName) { this.cacheName = cacheName; + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); SMRegistry.register(CacheSM.GROUP, new CacheSM(CacheProp.loadIfPresent())); this.consensus = new GroupWrapper(CacheSM.GROUP); } @@ -51,11 +56,11 @@ public boolean exist(final String key) { message.setCacheName(cacheName); message.setKey(key); message.setOp(CacheMessage.EXIST); - Result result = consensus.read(message); + Result result = consensus.read(serializer.serialize(message)); if (!Result.State.SUCCESS.equals(result.getState())) { throw new KleinException("The consensus negotiation result is UNKNOWN. In this case, the operation may or may not be completed. You need to retry or query to confirm"); } - Boolean data = result.getData(); + Boolean data = serializer.deserialize(result.getData()); return data != null && data; } @@ -66,7 +71,7 @@ public boolean put(final String key, final D data) { message.setData(data); message.setKey(key); message.setOp(CacheMessage.PUT); - Result result = consensus.propose(message); + Result result = consensus.propose(serializer.serialize(message)); return Result.State.SUCCESS.equals(result.getState()); } @@ -80,7 +85,7 @@ public Result.State put(final String key, final D data, if (ttl > 0) { message.setExpire(TrueTime.currentTimeMillis() + unit.toMillis(ttl)); } - Result result = consensus.propose(message, apply); + Result result = consensus.propose(Hessian2Util.serialize(message), apply); return result.getState(); } @@ -93,7 +98,7 @@ public boolean put(final String key, final D data, fina message.setOp(CacheMessage.PUT); message.setExpire(TrueTime.currentTimeMillis() + unit.toMillis(ttl)); - Result result = consensus.propose(message); + Result result = consensus.propose(serializer.serialize(message)); return Result.State.SUCCESS.equals(result.getState()); } @@ -104,11 +109,11 @@ public D putIfPresent(final String key, final D data) { message.setData(data); message.setKey(key); message.setOp(CacheMessage.PUTIFPRESENT); - Result result = consensus.propose(message, true); + Result result = consensus.propose(serializer.serialize(message), true); if (!Result.State.SUCCESS.equals(result.getState())) { throw new KleinException("The consensus negotiation result is UNKNOWN. In this case, the operation may or may not be completed. You need to retry or query to confirm. key: " + key); } - return result.getData(); + return serializer.deserialize(result.getData()); } @Override @@ -120,11 +125,11 @@ public D putIfPresent(final String key, final D data, f message.setOp(CacheMessage.PUTIFPRESENT); message.setExpire(TrueTime.currentTimeMillis() + unit.toMillis(ttl)); - Result result = consensus.propose(message, true); + Result result = consensus.propose(serializer.serialize(message), true); if (!Result.State.SUCCESS.equals(result.getState())) { throw new KleinException("The consensus negotiation result is UNKNOWN. In this case, the operation may or may not be completed. You need to retry or query to confirm"); } - return result.getData(); + return serializer.deserialize(result.getData()); } @Override @@ -133,12 +138,12 @@ public D get(final String key) { message.setCacheName(cacheName); message.setKey(key); message.setOp(CacheMessage.GET); - Result result = consensus.read(message); + Result result = consensus.read(serializer.serialize(message)); if (!Result.State.SUCCESS.equals(result.getState())) { throw new KleinException(String.format("The consensus negotiation result is %s. In this case, the operation" + " may or may not be completed. You need to retry or query to confirm", result.getState())); } - return result.getData(); + return serializer.deserialize(result.getData()); } @Override @@ -147,7 +152,7 @@ public void invalidate(final String key) { message.setCacheName(cacheName); message.setKey(key); message.setOp(CacheMessage.INVALIDATE); - Result result = consensus.propose(message); + Result result = consensus.propose(serializer.serialize(message)); } @Override @@ -155,7 +160,7 @@ public void invalidateAll() { CacheMessage message = new CacheMessage(); message.setCacheName(cacheName); message.setOp(CacheMessage.INVALIDATEALL); - Result result = consensus.propose(message); + Result result = consensus.propose(serializer.serialize(message)); } } diff --git a/klein-core/src/main/java/com/ofcoder/klein/core/cache/LruCacheContainer.java b/klein-core/src/main/java/com/ofcoder/klein/core/cache/LruCacheContainer.java index 7e35ad4a..091abb18 100644 --- a/klein-core/src/main/java/com/ofcoder/klein/core/cache/LruCacheContainer.java +++ b/klein-core/src/main/java/com/ofcoder/klein/core/cache/LruCacheContainer.java @@ -29,7 +29,7 @@ import org.mapdb.DataOutput2; import org.mapdb.Serializer; -import com.ofcoder.klein.common.serialization.Hessian2Util; +import com.ofcoder.klein.serializer.hessian2.Hessian2Util; /** * lru cache. diff --git a/klein-core/src/main/java/com/ofcoder/klein/core/lock/KleinLockImpl.java b/klein-core/src/main/java/com/ofcoder/klein/core/lock/KleinLockImpl.java index c1657caa..4e746bec 100644 --- a/klein-core/src/main/java/com/ofcoder/klein/core/lock/KleinLockImpl.java +++ b/klein-core/src/main/java/com/ofcoder/klein/core/lock/KleinLockImpl.java @@ -16,12 +16,14 @@ */ package com.ofcoder.klein.core.lock; -import java.util.concurrent.TimeUnit; - import com.ofcoder.klein.common.util.TrueTime; import com.ofcoder.klein.consensus.facade.Result; import com.ofcoder.klein.consensus.facade.sm.SMRegistry; import com.ofcoder.klein.core.GroupWrapper; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; + +import java.util.concurrent.TimeUnit; /** * lock implement. @@ -31,6 +33,7 @@ public class KleinLockImpl implements KleinLock { protected GroupWrapper consensus; private final String key; + private final Serializer serializer; /** * Return a new lock instance. @@ -41,6 +44,7 @@ public KleinLockImpl(final String key) { this.key = key; SMRegistry.register(LockSM.GROUP, new LockSM()); this.consensus = new GroupWrapper(LockSM.GROUP); + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); } @Override @@ -50,8 +54,9 @@ public boolean acquire(final long ttl, final TimeUnit unit) { message.setOp(LockMessage.LOCK); message.setExpire(TrueTime.currentTimeMillis() + unit.toMillis(ttl)); - Result result = consensus.propose(message, true); - return Result.State.SUCCESS.equals(result.getState()) && (Boolean) result.getData(); + Result result = consensus.propose(serializer.serialize(message), true); + Boolean acquired = serializer.deserialize(result.getData()); + return Result.State.SUCCESS.equals(result.getState()) && acquired; } @Override @@ -61,8 +66,9 @@ public boolean acquire() { message.setOp(LockMessage.LOCK); message.setExpire(LockMessage.TTL_PERPETUITY); - Result result = consensus.propose(message, true); - return Result.State.SUCCESS.equals(result.getState()) && (Boolean) result.getData(); + Result result = consensus.propose(serializer.serialize(message), true); + Boolean acquired = serializer.deserialize(result.getData()); + return Result.State.SUCCESS.equals(result.getState()) && acquired; } @Override @@ -70,6 +76,6 @@ public void release() { LockMessage message = new LockMessage(); message.setKey(key); message.setOp(LockMessage.UNLOCK); - Result result = consensus.propose(message, false); + Result result = consensus.propose(serializer.serialize(message), false); } } diff --git a/klein-core/src/main/java/com/ofcoder/klein/core/lock/LockSM.java b/klein-core/src/main/java/com/ofcoder/klein/core/lock/LockSM.java index 665e788d..55825db6 100644 --- a/klein-core/src/main/java/com/ofcoder/klein/core/lock/LockSM.java +++ b/klein-core/src/main/java/com/ofcoder/klein/core/lock/LockSM.java @@ -16,16 +16,17 @@ */ package com.ofcoder.klein.core.lock; -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.ofcoder.klein.common.util.TrueTime; import com.ofcoder.klein.consensus.facade.sm.AbstractSM; import com.ofcoder.klein.core.cache.CacheSM; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; /** * Lock State Machine. @@ -34,9 +35,11 @@ public class LockSM extends AbstractSM { public static final String GROUP = "lock"; private static final Logger LOG = LoggerFactory.getLogger(CacheSM.class); private final Map locks = new HashMap<>(); + private final Serializer serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); @Override - public Object apply(final Object data) { + public byte[] apply(final byte[] original) { + Object data = serializer.deserialize(original); if (!(data instanceof LockMessage)) { LOG.warn("apply data, UNKNOWN PARAMETER TYPE, data type is {}", data.getClass().getName()); return null; @@ -50,9 +53,9 @@ public Object apply(final Object data) { if (instance.lockState == LockInstance.UNLOCK_STATE || (instance.expire != LockMessage.TTL_PERPETUITY && instance.expire < TrueTime.currentTimeMillis())) { instance.lockState = LockInstance.LOCKED_STATE; instance.expire = message.getExpire(); - return true; + return serializer.serialize(true); } else { - return false; + return serializer.serialize(false); } case LockMessage.UNLOCK: instance.lockState = LockInstance.UNLOCK_STATE; @@ -65,13 +68,14 @@ public Object apply(final Object data) { } @Override - public Object makeImage() { - return locks; + public byte[] makeImage() { + return serializer.serialize(locks); } @SuppressWarnings("unchecked") @Override - public void loadImage(final Object snap) { + public void loadImage(final byte[] original) { + Object snap = serializer.deserialize(original); if (!(snap instanceof Map)) { return; } diff --git a/klein-core/src/test/java/com/ofcoder/klein/core/cache/CacheSMTest.java b/klein-core/src/test/java/com/ofcoder/klein/core/cache/CacheSMTest.java index 4ffaa7c6..93e1112a 100644 --- a/klein-core/src/test/java/com/ofcoder/klein/core/cache/CacheSMTest.java +++ b/klein-core/src/test/java/com/ofcoder/klein/core/cache/CacheSMTest.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; +import com.ofcoder.klein.serializer.hessian2.Hessian2Util; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -31,8 +32,8 @@ public void setUp() throws NoSuchFieldException, IllegalAccessException { MockitoAnnotations.initMocks(this); cacheSM = new CacheSM(new CacheProp()) { @Override - public Object makeImage() { - return mockContainer; + public byte[] makeImage() { + return Hessian2Util.serialize(mockContainer); } }; @@ -53,7 +54,7 @@ public void testApplyWithPutOperation() { message.setData("data"); message.setExpire(1000L); - cacheSM.apply(message); + cacheSM.apply(Hessian2Util.serialize(message)); verify(mockContainer).put(eq("key"), eq("data"), eq(1000L)); } @@ -66,7 +67,8 @@ public void testApplyWithGetOperation() { when(mockContainer.get("key")).thenReturn("data"); - assertEquals("data", cacheSM.apply(message)); + byte[] original = cacheSM.apply(Hessian2Util.serialize(message)); + assertEquals("data", Hessian2Util.deserialize(original)); } @Test @@ -76,7 +78,7 @@ public void testApplyWithInvalidateOperation() { message.setOp(CacheMessage.INVALIDATE); message.setKey("key"); - cacheSM.apply(message); + cacheSM.apply(Hessian2Util.serialize(message)); verify(mockContainer).remove("key"); } @@ -86,7 +88,7 @@ public void testApplyWithInvalidateAllOperation() { message.setCacheName("test"); message.setOp(CacheMessage.INVALIDATEALL); - cacheSM.apply(message); + cacheSM.apply(Hessian2Util.serialize(message)); verify(mockContainer).clear(); } @@ -101,7 +103,8 @@ public void testApplyWithPutIfPresentOperation() { when(mockContainer.putIfAbsent("key", "data", 1000L)).thenReturn(true); - assertEquals(true, cacheSM.apply(message)); + byte[] original = cacheSM.apply(Hessian2Util.serialize(message)); + assertEquals(true, Hessian2Util.deserialize(original)); } @Test @@ -113,13 +116,14 @@ public void testApplyWithExistOperation() { when(mockContainer.containsKey("key")).thenReturn(true); - assertEquals(true, cacheSM.apply(message)); + byte[] original = cacheSM.apply(Hessian2Util.serialize(message)); + assertEquals(true, Hessian2Util.deserialize(original)); } @Test public void testApplyWithUnknownMessage() { - assertNull(cacheSM.apply(new Object())); + assertNull(cacheSM.apply(Hessian2Util.serialize(new Object()))); verify(mockContainer, never()).put(any(), any(), anyLong()); verify(mockContainer, never()).get(any()); verify(mockContainer, never()).remove(any()); diff --git a/klein-core/src/test/java/com/ofcoder/klein/core/cache/FileMapTest.java b/klein-core/src/test/java/com/ofcoder/klein/core/cache/FileMapTest.java index c8fbc670..37e72a9b 100644 --- a/klein-core/src/test/java/com/ofcoder/klein/core/cache/FileMapTest.java +++ b/klein-core/src/test/java/com/ofcoder/klein/core/cache/FileMapTest.java @@ -24,7 +24,6 @@ import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.NotNull; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.mapdb.DB; import org.mapdb.DBMaker; @@ -33,7 +32,7 @@ import org.mapdb.Serializer; import com.google.common.collect.Maps; -import com.ofcoder.klein.common.serialization.Hessian2Util; +import com.ofcoder.klein.serializer.hessian2.Hessian2Util; import junit.framework.TestCase; /** diff --git a/klein-jepsen/klein-jepsen-server/pom.xml b/klein-jepsen/klein-jepsen-server/pom.xml index ec34c969..e556f61d 100644 --- a/klein-jepsen/klein-jepsen-server/pom.xml +++ b/klein-jepsen/klein-jepsen-server/pom.xml @@ -35,6 +35,10 @@ jackson-databind ${jackson.databind.version} + + com.ofcoder.klein.serializer.hessian2 + klein-serializer-hessian2 + @@ -119,8 +123,10 @@ - - + + com.ofcoder.klein.jepsen.server.KleinServer diff --git a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/JepsenClient.java b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/JepsenClient.java index 6207d474..0ff2144c 100644 --- a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/JepsenClient.java +++ b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/JepsenClient.java @@ -16,19 +16,9 @@ */ package com.ofcoder.klein.jepsen.server; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -import com.ofcoder.klein.rpc.facade.exception.ConnectionException; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.ofcoder.klein.KleinProp; -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.common.util.ChecksumUtil; import com.ofcoder.klein.jepsen.server.rpc.GetReq; import com.ofcoder.klein.jepsen.server.rpc.PutReq; @@ -36,7 +26,15 @@ import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.InvokeParam; import com.ofcoder.klein.rpc.facade.RpcProcessor; +import com.ofcoder.klein.rpc.facade.exception.ConnectionException; import com.ofcoder.klein.rpc.grpc.GrpcClient; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; +import java.io.UnsupportedEncodingException; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * jepsen‘s client. @@ -51,6 +49,7 @@ public class JepsenClient { .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); private final Endpoint endpoint; private final GrpcClient client; + private final Serializer serializer; public JepsenClient(final String node) { String id = StringUtils.remove(node, "n"); @@ -61,6 +60,8 @@ public JepsenClient(final String node) { client = new GrpcClient(kleinProp.getRpcProp()); client.createConnection(endpoint); + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); + } /** @@ -80,12 +81,12 @@ public boolean put(final Integer value) throws UnsupportedEncodingException { InvokeParam param = InvokeParam.Builder.anInvokeParam() .service(req.getClass().getSimpleName()) .method(RpcProcessor.KLEIN) - .data(ByteBuffer.wrap(Hessian2Util.serialize(req))).build(); + .data(serializer.serialize(req)).build(); try { LOG.info("seq: {}, put: {} on node: {}", req.getSeq(), value, endpoint.getId()); // see: com.ofcoder.klein.consensus.facade.Result.State - String result = client.sendRequestSync(endpoint, param, 3000); + String result = serializer.deserialize(client.sendRequestSync(endpoint, serializer.serialize(param), 3000)); LOG.info("seq: {}, put: {} on node: {}, result: {}", req.getSeq(), value, endpoint.getId(), result); if (!"SUCCESS".equals(result)) { throw new IllegalArgumentException("seq: " + req.getSeq() + ", put: " + value + " on node: " + endpoint.getId() + ", " + result); @@ -114,11 +115,11 @@ public Object get() throws UnsupportedEncodingException { InvokeParam param = InvokeParam.Builder.anInvokeParam() .service(req.getClass().getSimpleName()) .method(RpcProcessor.KLEIN) - .data(ByteBuffer.wrap(Hessian2Util.serialize(req))).build(); + .data(serializer.serialize(req)).build(); try { LOG.info("seq: {}, get: {} on node: {}", req.getSeq(), key, endpoint.getId()); - Resp resp = client.sendRequestSync(endpoint, param, 3000); + Resp resp = serializer.deserialize(client.sendRequestSync(endpoint, serializer.serialize(param), 3000)); LOG.info("seq: {}, get: {} on node: {}, result: {}", req.getSeq(), key, endpoint.getId(), resp); if (resp == null || !resp.isS()) { throw new IllegalArgumentException("seq: " + req.getSeq() + ", get: " + key + " on node: " + endpoint.getId() + ", result is null"); diff --git a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/ExistsProcessor.java b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/ExistsProcessor.java index c127d3c6..19058eb1 100644 --- a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/ExistsProcessor.java +++ b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/ExistsProcessor.java @@ -16,13 +16,10 @@ */ package com.ofcoder.klein.jepsen.server.rpc; -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.core.cache.KleinCache; import com.ofcoder.klein.rpc.facade.RpcContext; -import java.nio.ByteBuffer; - /** * cache exists request processor. * @@ -36,8 +33,9 @@ public ExistsProcessor(final KleinCache cache) { } @Override - public void handleRequest(final ExistsReq request, final RpcContext context) { - context.response(ByteBuffer.wrap(Hessian2Util.serialize(cache.exist(request.getKey())))); + public void handleRequest(final ExistsReq request, final RpcContext rpcContext) { + boolean exist = cache.exist(request.getKey()); + response(exist, rpcContext); } @Override diff --git a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/GetProcessor.java b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/GetProcessor.java index 7d998bec..1c7385bf 100644 --- a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/GetProcessor.java +++ b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/GetProcessor.java @@ -16,17 +16,13 @@ */ package com.ofcoder.klein.jepsen.server.rpc; -import java.io.Serializable; -import java.nio.ByteBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.ofcoder.klein.common.exception.KleinException; -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.core.cache.KleinCache; import com.ofcoder.klein.rpc.facade.RpcContext; +import java.io.Serializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * cache get request processor. @@ -43,16 +39,16 @@ public GetProcessor(final KleinCache cache) { } @Override - public void handleRequest(final GetReq request, final RpcContext context) { + public void handleRequest(final GetReq request, final RpcContext rpcContext) { try { LOG.info("get operator, begin, seq: {}", request.getSeq()); Serializable javaBean = cache.get(request.getKey()); LOG.info("get operator, end, seq: {}, result: {}", request.getSeq(), javaBean); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(new Resp(true, javaBean)))); + response(new Resp(true, javaBean), rpcContext); } catch (KleinException e) { LOG.error(e.getMessage()); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(new Resp(false, null)))); LOG.info("get operator, end, seq: {}, result: err", request.getSeq()); + response(new Resp(false, null), rpcContext); } } diff --git a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/InvalidateProcessor.java b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/InvalidateProcessor.java index 9a1c7cf8..a49abd61 100644 --- a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/InvalidateProcessor.java +++ b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/InvalidateProcessor.java @@ -16,13 +16,10 @@ */ package com.ofcoder.klein.jepsen.server.rpc; -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; import com.ofcoder.klein.core.cache.KleinCache; import com.ofcoder.klein.rpc.facade.RpcContext; -import java.nio.ByteBuffer; - /** * cache invalidate request processor. * @@ -37,9 +34,9 @@ public InvalidateProcessor(final KleinCache cache) { } @Override - public void handleRequest(final InvalidateReq request, final RpcContext context) { + public void handleRequest(final InvalidateReq request, final RpcContext rpcContext) { cache.invalidate(request.getKey()); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(true))); + response(true, rpcContext); } @Override diff --git a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/PutProcessor.java b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/PutProcessor.java index 2c10a077..262786ae 100644 --- a/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/PutProcessor.java +++ b/klein-jepsen/klein-jepsen-server/src/main/java/com/ofcoder/klein/jepsen/server/rpc/PutProcessor.java @@ -16,16 +16,12 @@ */ package com.ofcoder.klein.jepsen.server.rpc; -import java.nio.ByteBuffer; - -import com.ofcoder.klein.consensus.facade.Result; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.consensus.facade.AbstractRpcProcessor; +import com.ofcoder.klein.consensus.facade.Result; import com.ofcoder.klein.core.cache.KleinCache; import com.ofcoder.klein.rpc.facade.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * cache put request processor. @@ -41,16 +37,16 @@ public PutProcessor(final KleinCache cache) { } @Override - public void handleRequest(final PutReq request, final RpcContext context) { + public void handleRequest(final PutReq request, final RpcContext rpcContext) { try { LOG.info("put operator, begin, seq: {}", request.getSeq()); Result.State put = cache.put(request.getKey(), request.getData(), false, request.getTtl(), request.getUnit()); LOG.info("put operator, end, seq: {}, result: {}", request.getSeq(), put); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(put.name()))); + response(put.name(), rpcContext); } catch (Exception e) { LOG.error(e.getMessage()); - context.response(ByteBuffer.wrap(Hessian2Util.serialize(Result.State.UNKNOWN.name()))); LOG.info("put operator, err, seq: {}, result: err", request.getSeq()); + response(Result.State.UNKNOWN.name(), rpcContext); } } diff --git a/klein-rpc/klein-rpc-facade/pom.xml b/klein-rpc/klein-rpc-facade/pom.xml index 625bd039..ff15354f 100644 --- a/klein-rpc/klein-rpc-facade/pom.xml +++ b/klein-rpc/klein-rpc-facade/pom.xml @@ -19,8 +19,4 @@ 8 UTF-8 - - - - \ No newline at end of file diff --git a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeCallback.java b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeCallback.java index 58a1a52e..e059f5b6 100644 --- a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeCallback.java +++ b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeCallback.java @@ -16,8 +16,6 @@ */ package com.ofcoder.klein.rpc.facade; -import java.nio.ByteBuffer; - /** * Rpc Invoke Callback. * @@ -36,5 +34,5 @@ public interface InvokeCallback { * * @param result response */ - void complete(ByteBuffer result); + void complete(byte[] result); } diff --git a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeParam.java b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeParam.java index b2420b69..4a237a77 100644 --- a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeParam.java +++ b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/InvokeParam.java @@ -16,7 +16,7 @@ */ package com.ofcoder.klein.rpc.facade; -import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.Objects; /** @@ -27,7 +27,7 @@ public class InvokeParam { private String service; private String method; - private ByteBuffer data; + private byte[] data; /** * get service name. @@ -70,7 +70,7 @@ public void setMethod(final String method) { * * @return invoke data */ - public ByteBuffer getData() { + public byte[] getData() { return data; } @@ -79,7 +79,7 @@ public ByteBuffer getData() { * * @param data invoke data */ - public void setData(final ByteBuffer data) { + public void setData(final byte[] data) { this.data = data; } @@ -92,27 +92,27 @@ public boolean equals(final Object o) { return false; } InvokeParam that = (InvokeParam) o; - return Objects.equals(service, that.service) && Objects.equals(method, that.method) && Objects.equals(data, that.data); + return Objects.equals(service, that.service) && Objects.equals(method, that.method) && Arrays.equals(data, that.data); } @Override public int hashCode() { - return Objects.hash(service, method, data); + return Objects.hash(service, method, Arrays.hashCode(data)); } @Override public String toString() { return "InvokeParam{" - + "service='" + service + '\'' - + ", method='" + method + '\'' - + ", data=" + data - + '}'; + + "service='" + service + '\'' + + ", method='" + method + '\'' + + ", data=" + data.length + + '}'; } public static final class Builder { private String service; private String method; - private ByteBuffer data; + private byte[] data; private Builder() { } @@ -154,7 +154,7 @@ public Builder method(final String method) { * @param data data * @return Builder */ - public Builder data(final ByteBuffer data) { + public Builder data(final byte[] data) { this.data = data; return this; } diff --git a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcClient.java b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcClient.java index 47ac89e8..ff12073f 100644 --- a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcClient.java +++ b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcClient.java @@ -16,15 +16,10 @@ */ package com.ofcoder.klein.rpc.facade; -import java.io.Serializable; -import java.nio.ByteBuffer; - +import com.ofcoder.klein.spi.SPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.ofcoder.klein.common.serialization.Hessian2Util; -import com.ofcoder.klein.spi.SPI; - /** * grpc client for send request. * @@ -75,7 +70,7 @@ public interface RpcClient { * @param request invoke data and service info * @param callback invoke callback */ - default void sendRequestAsync(Endpoint target, Serializable request, InvokeCallback callback) { + default void sendRequestAsync(Endpoint target, byte[] request, InvokeCallback callback) { sendRequestAsync(target, request, callback, requestTimeout()); } @@ -87,11 +82,11 @@ default void sendRequestAsync(Endpoint target, Serializable request, InvokeCallb * @param callback invoke callback * @param timeoutMs invoke timeout */ - default void sendRequestAsync(Endpoint target, Serializable request, InvokeCallback callback, long timeoutMs) { + default void sendRequestAsync(Endpoint target, byte[] request, InvokeCallback callback, long timeoutMs) { InvokeParam param = InvokeParam.Builder.anInvokeParam() - .service(request.getClass().getSimpleName()) - .method(RpcProcessor.KLEIN) - .data(ByteBuffer.wrap(Hessian2Util.serialize(request))).build(); + .service(request.getClass().getSimpleName()) + .method(RpcProcessor.KLEIN) + .data(request).build(); sendRequestAsync(target, param, callback, timeoutMs); } @@ -111,10 +106,9 @@ default void sendRequestAsync(Endpoint target, Serializable request, InvokeCallb * @param target target * @param request invoke data and service info * @param timeoutMs invoke timeout - * @param result type * @return invoke result */ - R sendRequestSync(Endpoint target, InvokeParam request, long timeoutMs); + byte[] sendRequestSync(Endpoint target, InvokeParam request, long timeoutMs); /** * send request for sync. @@ -122,14 +116,13 @@ default void sendRequestAsync(Endpoint target, Serializable request, InvokeCallb * @param target target * @param request invoke data and service info * @param timeoutMs invoke timeout - * @param result type * @return invoke result */ - default R sendRequestSync(Endpoint target, Serializable request, long timeoutMs) { + default byte[] sendRequestSync(Endpoint target, byte[] request, long timeoutMs) { InvokeParam param = InvokeParam.Builder.anInvokeParam() - .service(request.getClass().getSimpleName()) - .method(RpcProcessor.KLEIN) - .data(ByteBuffer.wrap(Hessian2Util.serialize(request))).build(); + .service(request.getClass().getSimpleName()) + .method(RpcProcessor.KLEIN) + .data(request).build(); return sendRequestSync(target, param, timeoutMs); } @@ -138,10 +131,9 @@ default R sendRequestSync(Endpoint target, Serializable request, long timeou * * @param target target * @param request invoke data and service info - * @param result type * @return invoke result */ - default R sendRequestSync(Endpoint target, Serializable request) { + default byte[] sendRequestSync(Endpoint target, byte[] request) { return sendRequestSync(target, request, requestTimeout()); } diff --git a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcContext.java b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcContext.java index 02f372b9..a0c4fd9c 100644 --- a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcContext.java +++ b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcContext.java @@ -16,8 +16,6 @@ */ package com.ofcoder.klein.rpc.facade; -import java.nio.ByteBuffer; - /** * Rpc Context. * @@ -29,7 +27,7 @@ public interface RpcContext { * * @param msg response data */ - void response(ByteBuffer msg); + void response(byte[] msg); /** * get caller info. diff --git a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcProcessor.java b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcProcessor.java index 98e5f6ef..628c1962 100644 --- a/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcProcessor.java +++ b/klein-rpc/klein-rpc-facade/src/main/java/com/ofcoder/klein/rpc/facade/RpcProcessor.java @@ -16,8 +16,6 @@ */ package com.ofcoder.klein.rpc.facade; -import java.nio.ByteBuffer; - /** * message processor. * @@ -49,6 +47,6 @@ default String method() { * @param request request param * @param context rpc context */ - void handleRequest(ByteBuffer request, RpcContext context); + void handleRequest(byte[] request, RpcContext context); } diff --git a/klein-rpc/klein-rpc-grpc/pom.xml b/klein-rpc/klein-rpc-grpc/pom.xml index 5f5b9cc5..85dae417 100644 --- a/klein-rpc/klein-rpc-grpc/pom.xml +++ b/klein-rpc/klein-rpc-grpc/pom.xml @@ -39,8 +39,10 @@ ${protobuf.plugin.version} klein-rpc - com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier} - io.grpc:protoc-gen-grpc-java:${io.grpc.version}:exe:${os.detected.classifier} + com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier} + + io.grpc:protoc-gen-grpc-java:${io.grpc.version}:exe:${os.detected.classifier} + ${project.basedir}/src/main/resources ${project.basedir}/src/main/java false @@ -65,7 +67,6 @@ klein-rpc-facade - com.google.protobuf protobuf-java diff --git a/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcClient.java b/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcClient.java index ddc66bd0..c19194e5 100644 --- a/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcClient.java +++ b/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcClient.java @@ -17,7 +17,6 @@ package com.ofcoder.klein.rpc.grpc; import com.google.protobuf.DynamicMessage; -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.common.util.ThreadExecutor; import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.InvokeCallback; @@ -36,16 +35,14 @@ import io.grpc.MethodDescriptor; import io.grpc.stub.ClientCalls; import io.grpc.stub.StreamObserver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Grpc Client. @@ -79,10 +76,10 @@ public void createConnection(final Endpoint endpoint) { private ManagedChannel newChannel(final Endpoint endpoint) { final ManagedChannel ch = ManagedChannelBuilder.forAddress(endpoint.getIp(), endpoint.getPort()) - .usePlaintext() - .directExecutor() - .maxInboundMessageSize(prop.getMaxInboundMsgSize()) - .build(); + .usePlaintext() + .directExecutor() + .maxInboundMessageSize(prop.getMaxInboundMsgSize()) + .build(); ch.notifyWhenStateChanged(ConnectivityState.IDLE, () -> onStateChanged(endpoint, ch)); return ch; } @@ -132,8 +129,8 @@ public void sendRequestAsync(final Endpoint target, final InvokeParam request, f } @Override - public R sendRequestSync(final Endpoint target, final InvokeParam request, final long timeoutMs) { - final CompletableFuture future = new CompletableFuture<>(); + public byte[] sendRequestSync(final Endpoint target, final InvokeParam request, final long timeoutMs) { + final CompletableFuture future = new CompletableFuture<>(); invokeAsync(target, request, new InvokeCallback() { @Override @@ -142,14 +139,13 @@ public void error(final Throwable err) { } @Override - public void complete(final ByteBuffer result) { + public void complete(final byte[] result) { future.complete(result); } }, timeoutMs); try { - ByteBuffer result = future.get(timeoutMs, TimeUnit.MILLISECONDS); - return Hessian2Util.deserialize(result.array()); + return future.get(timeoutMs, TimeUnit.MILLISECONDS); } catch (final TimeoutException e) { future.cancel(true); throw new InvokeTimeoutException(e.getMessage(), e); @@ -194,7 +190,7 @@ private void invokeAsync(final Endpoint endpoint, final InvokeParam invokeParam, final Channel ch = getCheckedChannel(endpoint); if (ch == null) { ThreadExecutor.execute(() -> - callback.error(new ConnectionException(String.format("connection not available, %s", endpoint)))); + callback.error(new ConnectionException(String.format("connection not available, %s", endpoint)))); return; } @@ -202,17 +198,19 @@ private void invokeAsync(final Endpoint endpoint, final InvokeParam invokeParam, final DynamicMessage response = MessageHelper.buildMessage(); final CallOptions callOpts = CallOptions.DEFAULT.withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS); final MethodDescriptor methodDescriptor = MessageHelper.createMarshallerMethodDescriptor(invokeParam.getService(), - invokeParam.getMethod(), - MethodDescriptor.MethodType.UNARY, - request, - response); + invokeParam.getMethod(), + MethodDescriptor.MethodType.UNARY, + request, + response); ClientCalls.asyncUnaryCall(ch.newCall(methodDescriptor, callOpts), request, new StreamObserver() { @Override public void onNext(final DynamicMessage value) { - ByteBuffer respData = MessageHelper.getDataFromDynamicMessage(value); - ThreadExecutor.execute(() -> callback.complete(respData)); + byte[] respData = MessageHelper.getDataFromDynamicMessage(value); + ThreadExecutor.execute(() -> { + callback.complete(respData); + }); } @Override diff --git a/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcServer.java b/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcServer.java index 06665d5a..2f76c153 100644 --- a/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcServer.java +++ b/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/GrpcServer.java @@ -16,13 +16,6 @@ */ package com.ofcoder.klein.rpc.grpc; -import java.io.IOException; -import java.net.SocketAddress; -import java.nio.ByteBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.protobuf.DynamicMessage; import com.ofcoder.klein.common.exception.StartupException; import com.ofcoder.klein.rpc.facade.RpcContext; @@ -38,6 +31,10 @@ import io.grpc.ServerServiceDefinition; import io.grpc.stub.ServerCalls; import io.grpc.util.MutableHandlerRegistry; +import java.io.IOException; +import java.net.SocketAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Grpc Server. @@ -52,10 +49,11 @@ public class GrpcServer implements RpcServer { public GrpcServer(final RpcProp op) { server = ServerBuilder.forPort(op.getPort()) - .fallbackHandlerRegistry(handlerRegistry) - .directExecutor() - .maxInboundMessageSize(op.getMaxInboundMsgSize()) - .build(); + .fallbackHandlerRegistry(handlerRegistry) + .directExecutor() + .maxInboundMessageSize(op.getMaxInboundMsgSize()) + .build(); + try { server.start(); } catch (IOException e) { @@ -66,37 +64,37 @@ public GrpcServer(final RpcProp op) { @Override public void registerProcessor(final RpcProcessor processor) { final MethodDescriptor method = MessageHelper.createMarshallerMethodDescriptor( - processor.service(), - processor.method(), - MethodDescriptor.MethodType.UNARY, - MessageHelper.buildMessage(), - MessageHelper.buildMessage(ByteBuffer.wrap(new byte[0]))); + processor.service(), + processor.method(), + MethodDescriptor.MethodType.UNARY, + MessageHelper.buildMessage(), + MessageHelper.buildMessage(new byte[0])); final ServerCallHandler handler = - ServerCalls.asyncUnaryCall((request, responseObserver) -> { - final SocketAddress remoteAddress = RemoteAddressInterceptor.getRemoteAddress(); - ByteBuffer msg = MessageHelper.getDataFromDynamicMessage(request); - processor.handleRequest(msg, new RpcContext() { - @Override - public void response(final ByteBuffer msg) { - final DynamicMessage res = MessageHelper.buildMessage(msg); - responseObserver.onNext(res); - responseObserver.onCompleted(); - } - - @Override - public String getRemoteAddress() { - // Rely on GRPC's capabilities, not magic (netty channel) - return remoteAddress != null ? remoteAddress.toString() : null; - } - }); + ServerCalls.asyncUnaryCall((request, responseObserver) -> { + final SocketAddress remoteAddress = RemoteAddressInterceptor.getRemoteAddress(); + byte[] msg = MessageHelper.getDataFromDynamicMessage(request); + processor.handleRequest(msg, new RpcContext() { + @Override + public void response(final byte[] msg) { + final DynamicMessage res = MessageHelper.buildMessage(msg); + responseObserver.onNext(res); + responseObserver.onCompleted(); + } + @Override + public String getRemoteAddress() { + // Rely on GRPC's capabilities, not magic (netty channel) + return remoteAddress != null ? remoteAddress.toString() : null; + } }); + }); + final ServerServiceDefinition serviceDef = ServerServiceDefinition - .builder(processor.service()) - .addMethod(method, handler) - .build(); + .builder(processor.service()) + .addMethod(method, handler) + .build(); this.handlerRegistry.addService(ServerInterceptors.intercept(serviceDef, new RemoteAddressInterceptor())); } diff --git a/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/MessageHelper.java b/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/MessageHelper.java index 331622e7..5bcd8eca 100644 --- a/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/MessageHelper.java +++ b/klein-rpc/klein-rpc-grpc/src/main/java/com/ofcoder/klein/rpc/grpc/MessageHelper.java @@ -16,14 +16,6 @@ */ package com.ofcoder.klein.rpc.grpc; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import com.google.protobuf.DescriptorProtos; @@ -32,6 +24,11 @@ import com.google.protobuf.ExtensionRegistryLite; import com.ofcoder.klein.rpc.facade.exception.RpcException; import io.grpc.MethodDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Message Helper. @@ -52,9 +49,9 @@ public static Descriptors.Descriptor buildMarshallerDescriptor() { DescriptorProtos.DescriptorProto.Builder jsonMarshaller = DescriptorProtos.DescriptorProto.newBuilder(); jsonMarshaller.setName(GrpcConstants.JSON_DESCRIPTOR_PROTO_NAME); jsonMarshaller.addFieldBuilder() - .setName(GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NAME) - .setNumber(1) - .setType(DescriptorProtos.FieldDescriptorProto.Type.TYPE_BYTES); + .setName(GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NAME) + .setNumber(1) + .setType(DescriptorProtos.FieldDescriptorProto.Type.TYPE_BYTES); // build File Descriptor Proto DescriptorProtos.FileDescriptorProto.Builder fileDescriptorProtoBuilder = DescriptorProtos.FileDescriptorProto.newBuilder(); @@ -63,7 +60,7 @@ public static Descriptors.Descriptor buildMarshallerDescriptor() { DescriptorProtos.FileDescriptorProto fileDescriptorProto = fileDescriptorProtoBuilder.build(); try { Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor - .buildFrom(fileDescriptorProto, new Descriptors.FileDescriptor[0]); + .buildFrom(fileDescriptorProto, new Descriptors.FileDescriptor[0]); return fileDescriptor.findMessageTypeByName(GrpcConstants.JSON_DESCRIPTOR_PROTO_NAME); } catch (Descriptors.DescriptorValidationException e) { LOG.error("dynamic build JsonMarshaller descriptor is fail: {}", e.getMessage()); @@ -77,10 +74,10 @@ public static Descriptors.Descriptor buildMarshallerDescriptor() { * @param request request data * @return DynamicMessage */ - public static DynamicMessage buildMessage(final ByteBuffer request) { + public static DynamicMessage buildMessage(final byte[] request) { Descriptors.Descriptor jsonDescriptor = buildMarshallerDescriptor(); DynamicMessage.Builder jsonDynamicMessage = DynamicMessage.newBuilder(jsonDescriptor); - jsonDynamicMessage.setField(jsonDescriptor.findFieldByName(GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NAME), request.array()); + jsonDynamicMessage.setField(jsonDescriptor.findFieldByName(GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NAME), request); return jsonDynamicMessage.build(); } @@ -101,7 +98,7 @@ public static DynamicMessage buildMessage() { * @param message message * @return data */ - public static ByteBuffer getDataFromDynamicMessage(final DynamicMessage message) { + public static byte[] getDataFromDynamicMessage(final DynamicMessage message) { for (Map.Entry entry : message.getAllFields().entrySet()) { Descriptors.FieldDescriptor key = entry.getKey(); Object value = entry.getValue(); @@ -109,10 +106,10 @@ public static ByteBuffer getDataFromDynamicMessage(final DynamicMessage message) String fullName = key.getFullName(); String jsonMessageFullName = GrpcConstants.JSON_DESCRIPTOR_PROTO_NAME + "." + GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NAME; if (jsonMessageFullName.equals(fullName)) { - return ByteBuffer.wrap(((ByteString) value).toByteArray()); + return ((ByteString) value).toByteArray(); } } - return ByteBuffer.wrap(new byte[0]); + return new byte[0]; } /** @@ -133,11 +130,11 @@ public static MethodDescriptor createMarshallerM MethodDescriptor methodDescriptor = METHOD_DESCRIPTOR_CACHE.get(serviceName + methodName); if (methodDescriptor == null) { methodDescriptor = MethodDescriptor.newBuilder() - .setType(methodType) - .setFullMethodName(MethodDescriptor.generateFullMethodName(serviceName, methodName)) - .setRequestMarshaller(new DynamicMessageMarshaller(request.getDescriptorForType())) - .setResponseMarshaller(new DynamicMessageMarshaller(response.getDescriptorForType())) - .build(); + .setType(methodType) + .setFullMethodName(MethodDescriptor.generateFullMethodName(serviceName, methodName)) + .setRequestMarshaller(new DynamicMessageMarshaller(request.getDescriptorForType())) + .setResponseMarshaller(new DynamicMessageMarshaller(response.getDescriptorForType())) + .build(); METHOD_DESCRIPTOR_CACHE.put(serviceName + methodName, methodDescriptor); } @@ -156,8 +153,8 @@ private DynamicMessageMarshaller(final Descriptors.Descriptor messageDescriptor) public DynamicMessage parse(final InputStream inputStream) { try { return DynamicMessage.newBuilder(messageDescriptor) - .mergeFrom(inputStream, ExtensionRegistryLite.getEmptyRegistry()) - .build(); + .mergeFrom(inputStream, ExtensionRegistryLite.getEmptyRegistry()) + .build(); } catch (IOException e) { throw new RuntimeException("Unable to merge from the supplied input stream", e); } diff --git a/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/GrpcClientTest.java b/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/GrpcClientTest.java index b1e6f6d6..887b0a45 100644 --- a/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/GrpcClientTest.java +++ b/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/GrpcClientTest.java @@ -1,15 +1,5 @@ package com.ofcoder.klein.rpc.grpc; -import java.nio.ByteBuffer; -import java.util.concurrent.CountDownLatch; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; import com.ofcoder.klein.rpc.facade.Endpoint; import com.ofcoder.klein.rpc.facade.InvokeCallback; import com.ofcoder.klein.rpc.facade.InvokeParam; @@ -19,6 +9,13 @@ import com.ofcoder.klein.rpc.facade.config.RpcProp; import com.ofcoder.klein.rpc.grpc.ext.HelloProcessor; import com.ofcoder.klein.spi.ExtensionLoader; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CountDownLatch; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author 释慧利 @@ -33,7 +30,7 @@ public class GrpcClientTest { @Before public void setup() { RpcProp prop = new RpcProp(); - rpcServer = ExtensionLoader.getExtensionLoader(RpcServer.class).register("grpc",prop); + rpcServer = ExtensionLoader.getExtensionLoader(RpcServer.class).register("grpc", prop); rpcClient = ExtensionLoader.getExtensionLoader(RpcClient.class).register("grpc", prop); rpcServer.registerProcessor(processor); } @@ -47,9 +44,9 @@ public void shutdown() { @Test public void testSendRequest() throws InterruptedException { InvokeParam param = InvokeParam.Builder.anInvokeParam() - .service("".getClass().getSimpleName()) - .method(RpcProcessor.KLEIN) - .data(ByteBuffer.wrap(Hessian2Util.serialize("I'm Klein"))).build(); + .service("".getClass().getSimpleName()) + .method(RpcProcessor.KLEIN) + .data("I'm Klein".getBytes(StandardCharsets.UTF_8)).build(); CountDownLatch latch = new CountDownLatch(2); @@ -61,8 +58,8 @@ public void error(Throwable err) { } @Override - public void complete(ByteBuffer result) { - LOG.info("receive server message: {}", (Object) Hessian2Util.deserialize(result.array())); + public void complete(byte[] result) { + LOG.info("receive server message: {}", new String(result, StandardCharsets.UTF_8)); latch.countDown(); } }, 5000); @@ -77,8 +74,8 @@ public void error(Throwable err) { } @Override - public void complete(ByteBuffer result) { - LOG.info("receive server message: {}", (Object) Hessian2Util.deserialize(result.array())); + public void complete(byte[] result) { + LOG.info("receive server message: {}", new String(result, StandardCharsets.UTF_8)); latch.countDown(); } }, 5000); diff --git a/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/ext/HelloProcessor.java b/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/ext/HelloProcessor.java index 268a5e2f..65d13814 100644 --- a/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/ext/HelloProcessor.java +++ b/klein-rpc/klein-rpc-grpc/src/test/java/com/ofcoder/klein/rpc/grpc/ext/HelloProcessor.java @@ -2,12 +2,10 @@ import com.ofcoder.klein.rpc.facade.RpcContext; import com.ofcoder.klein.rpc.facade.RpcProcessor; -import com.ofcoder.klein.common.serialization.Hessian2Util; +import java.nio.charset.StandardCharsets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.nio.ByteBuffer; - /** * @author 释慧利 */ @@ -20,9 +18,9 @@ public String service() { } @Override - public void handleRequest(ByteBuffer request, RpcContext context) { + public void handleRequest(byte[] request, RpcContext context) { - LOG.info("receive client message: {}", (Object) Hessian2Util.deserialize(request.array())); - context.response(ByteBuffer.wrap(Hessian2Util.serialize("hello, klein"))); + LOG.info("receive client message: {}", new String(request, StandardCharsets.UTF_8)); + context.response("hello, klein".getBytes(StandardCharsets.UTF_8)); } } diff --git a/klein-serializer/klein-serializer-facade/pom.xml b/klein-serializer/klein-serializer-facade/pom.xml new file mode 100644 index 00000000..3c9c9b58 --- /dev/null +++ b/klein-serializer/klein-serializer-facade/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.ofcoder.klein.serializer + klein-serializer + 0.0.8 + + + klein-serializer-facade + com.ofcoder.klein.serializer.facade + 0.0.8 + jar + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/klein-serializer/klein-serializer-facade/src/main/java/com/ofcoder/klein/serializer/Serializer.java b/klein-serializer/klein-serializer-facade/src/main/java/com/ofcoder/klein/serializer/Serializer.java new file mode 100644 index 00000000..e8e60636 --- /dev/null +++ b/klein-serializer/klein-serializer-facade/src/main/java/com/ofcoder/klein/serializer/Serializer.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ofcoder.klein.serializer; + +import com.ofcoder.klein.spi.SPI; + +/** + * Serializer. + * + */ +@SPI +public interface Serializer { + /** + * Encode object to byte[]. + * + * @param t the t + * @return the byte [ ] + */ + byte[] serialize(Object t); + + /** + * Decode t from byte[]. + * + * @param result type + * @param bytes the bytes + * @return the t + */ + R deserialize(byte[] bytes); +} diff --git a/klein-serializer/klein-serializer-hessian2/pom.xml b/klein-serializer/klein-serializer-hessian2/pom.xml new file mode 100644 index 00000000..7cf96415 --- /dev/null +++ b/klein-serializer/klein-serializer-hessian2/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.ofcoder.klein.serializer + klein-serializer + 0.0.8 + + + klein-serializer-hessian2 + com.ofcoder.klein.serializer.hessian2 + 0.0.8 + jar + + + 8 + 8 + UTF-8 + + + + + com.caucho + hessian + + + com.ofcoder.klein.serializer.facade + klein-serializer-facade + + + \ No newline at end of file diff --git a/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/Hessian2Serializer.java b/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/Hessian2Serializer.java new file mode 100644 index 00000000..3aeb78d4 --- /dev/null +++ b/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/Hessian2Serializer.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ofcoder.klein.serializer.hessian2; + +import com.caucho.hessian.io.Hessian2Input; +import com.ofcoder.klein.common.exception.SerializationException; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.Join; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * Hessian Serializer. + * + * @author hang.li + */ +@Join +public class Hessian2Serializer implements Serializer { + private static final Logger LOGGER = LoggerFactory.getLogger(Hessian2Serializer.class); + + @Override + public byte[] serialize(final Object t) { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + KleinHessian2Output ho = new KleinHessian2Output(baos)) { + ho.writeObject(t); + ho.flush(); + return baos.toByteArray(); + } catch (Exception ex) { + throw new SerializationException(ex.getMessage(), ex); + } + } + + @Override + @SuppressWarnings("unchecked") + public R deserialize(final byte[] bytes) { + try (ByteArrayInputStream is = new ByteArrayInputStream(bytes)) { + Hessian2Input input = new Hessian2Input(is); + Object obj = input.readObject(); + input.close(); + return (R) obj; + } catch (IOException e) { + LOGGER.error("Hessian decode error:{}", e.getMessage(), e); + throw new SerializationException("Failed to deserialize object", e); + } + } +} diff --git a/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/Hessian2Util.java b/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/Hessian2Util.java new file mode 100644 index 00000000..9e42cb1d --- /dev/null +++ b/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/Hessian2Util.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ofcoder.klein.serializer.hessian2; + +import com.ofcoder.klein.serializer.Serializer; + +/** + * Hessian util. + * + * @author far.liu + */ +public class Hessian2Util { + + private static final Serializer HESSIAN2 = new Hessian2Serializer(); + + /** + * serialize object. + * + * @param javaBean object + * @param java object type + * @return serialized data + */ + public static byte[] serialize(final T javaBean) { + return HESSIAN2.serialize(javaBean); + } + + /** + * deserialize data to java object. + * + * @param serializeData serialized data + * @param java object type + * @return java object + */ + @SuppressWarnings("unchecked") + public static T deserialize(final byte[] serializeData) { + return HESSIAN2.deserialize(serializeData); + } +} diff --git a/klein-storage/klein-storage-file/src/test/java/com/ofcoder/klein/storage/file/MetaDataDTO.java b/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/KleinHessian2Output.java similarity index 64% rename from klein-storage/klein-storage-file/src/test/java/com/ofcoder/klein/storage/file/MetaDataDTO.java rename to klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/KleinHessian2Output.java index 02855f2d..72cbd458 100644 --- a/klein-storage/klein-storage-file/src/test/java/com/ofcoder/klein/storage/file/MetaDataDTO.java +++ b/klein-serializer/klein-serializer-hessian2/src/main/java/com/ofcoder/klein/serializer/hessian2/KleinHessian2Output.java @@ -14,30 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ofcoder.klein.storage.file; +package com.ofcoder.klein.serializer.hessian2; -import com.ofcoder.klein.storage.facade.LogManager; +import com.caucho.hessian.io.Hessian2Output; +import java.io.OutputStream; /** - * @author 释慧利 + * implements AutoCloseable for Hessian2Output. */ -public class MetaDataDTO implements LogManager.MetaData { - private int id; - private String name; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; +public class KleinHessian2Output extends Hessian2Output implements AutoCloseable { + public KleinHessian2Output(final OutputStream os) { + super(os); } } diff --git a/klein-serializer/klein-serializer-hessian2/src/main/resources/META-INF/services/com.ofcoder.klein.serializer.Serializer b/klein-serializer/klein-serializer-hessian2/src/main/resources/META-INF/services/com.ofcoder.klein.serializer.Serializer new file mode 100644 index 00000000..e45af563 --- /dev/null +++ b/klein-serializer/klein-serializer-hessian2/src/main/resources/META-INF/services/com.ofcoder.klein.serializer.Serializer @@ -0,0 +1 @@ +hessian2=com.ofcoder.klein.serializer.hessian2.Hessian2Serializer \ No newline at end of file diff --git a/klein-serializer/klein-serializer-hessian2/src/test/java/com/ofcoder/klein/serializer/hessian2/Hessian2UtilTest.java b/klein-serializer/klein-serializer-hessian2/src/test/java/com/ofcoder/klein/serializer/hessian2/Hessian2UtilTest.java new file mode 100644 index 00000000..71dae5e8 --- /dev/null +++ b/klein-serializer/klein-serializer-hessian2/src/test/java/com/ofcoder/klein/serializer/hessian2/Hessian2UtilTest.java @@ -0,0 +1,20 @@ +package com.ofcoder.klein.serializer.hessian2; + +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; +import org.junit.Assert; + +import junit.framework.TestCase; + +public class Hessian2UtilTest extends TestCase { + + public void testSerialize() { + Serializer hessian2 = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); + + String resource = "Hello Klein"; + byte[] serialize = hessian2.serialize(resource); + Assert.assertNotNull(serialize); + String deserialize = (String) hessian2.deserialize(serialize); + Assert.assertEquals(deserialize, resource); + } +} \ No newline at end of file diff --git a/klein-serializer/klein-serializer-protobuf/pom.xml b/klein-serializer/klein-serializer-protobuf/pom.xml new file mode 100644 index 00000000..76bf6c62 --- /dev/null +++ b/klein-serializer/klein-serializer-protobuf/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.ofcoder.klein.serializer + klein-serializer + 0.0.8 + + + klein-serializer-protobuf + com.ofcoder.klein.serializer.protobuf + 0.0.8 + jar + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/klein-serializer/pom.xml b/klein-serializer/pom.xml new file mode 100644 index 00000000..951bbc0b --- /dev/null +++ b/klein-serializer/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + com.ofcoder.klein + klein + 0.0.8 + + + klein-serializer + 0.0.8 + com.ofcoder.klein.serializer + + pom + + klein-serializer-protobuf + klein-serializer-hessian2 + klein-serializer-facade + + + + 8 + 8 + UTF-8 + + + + + com.ofcoder.klein.common + klein-common + + + com.ofcoder.klein.spi + klein-spi + + + \ No newline at end of file diff --git a/klein-storage/klein-storage-facade/pom.xml b/klein-storage/klein-storage-facade/pom.xml index 06eeda5a..67c03b1a 100644 --- a/klein-storage/klein-storage-facade/pom.xml +++ b/klein-storage/klein-storage-facade/pom.xml @@ -20,4 +20,12 @@ UTF-8 + + + + com.ofcoder.klein.serializer.facade + klein-serializer-facade + + + \ No newline at end of file diff --git a/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/LogManager.java b/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/LogManager.java index 045d4681..92055445 100644 --- a/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/LogManager.java +++ b/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/LogManager.java @@ -16,12 +16,11 @@ */ package com.ofcoder.klein.storage.facade; +import com.ofcoder.klein.spi.SPI; import java.io.Serializable; import java.util.List; import java.util.concurrent.locks.ReentrantReadWriteLock; -import com.ofcoder.klein.spi.SPI; - /** * Manage logs generated by the consensus system. * diff --git a/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/Snap.java b/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/Snap.java index aa6db3a2..9e0ec899 100644 --- a/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/Snap.java +++ b/klein-storage/klein-storage-facade/src/main/java/com/ofcoder/klein/storage/facade/Snap.java @@ -25,12 +25,12 @@ */ public class Snap implements Serializable { private long checkpoint; - private Object snap; + private byte[] snap; public Snap() { } - public Snap(final long checkpoint, final Object snap) { + public Snap(final long checkpoint, final byte[] snap) { this.checkpoint = checkpoint; this.snap = snap; } @@ -59,8 +59,8 @@ public void setCheckpoint(final long checkpoint) { * * @return snapshot */ - public Object getSnap() { - return snap; + public byte[] getSnap() { + return snap.clone(); } /** @@ -68,7 +68,7 @@ public Object getSnap() { * * @param snap snapshot */ - public void setSnap(final Object snap) { - this.snap = snap; + public void setSnap(final byte[] snap) { + this.snap = snap.clone(); } } diff --git a/klein-storage/klein-storage-file/src/main/java/com/ofcoder/klein/storage/file/FileLogManager.java b/klein-storage/klein-storage-file/src/main/java/com/ofcoder/klein/storage/file/FileLogManager.java index b4e54cee..9c655c88 100644 --- a/klein-storage/klein-storage-file/src/main/java/com/ofcoder/klein/storage/file/FileLogManager.java +++ b/klein-storage/klein-storage-file/src/main/java/com/ofcoder/klein/storage/file/FileLogManager.java @@ -16,6 +16,20 @@ */ package com.ofcoder.klein.storage.file; +import com.ofcoder.klein.common.util.StreamUtil; +import com.ofcoder.klein.serializer.Serializer; +import com.ofcoder.klein.spi.ExtensionLoader; +import com.ofcoder.klein.spi.Join; +import com.ofcoder.klein.storage.facade.Instance; +import com.ofcoder.klein.storage.facade.LogManager; +import com.ofcoder.klein.storage.facade.Snap; +import com.ofcoder.klein.storage.facade.config.StorageProp; +import com.ofcoder.klein.storage.facade.exception.LockException; +import com.ofcoder.klein.storage.facade.exception.StorageException; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -29,20 +43,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ofcoder.klein.common.serialization.Hessian2Util; -import com.ofcoder.klein.common.util.StreamUtil; -import com.ofcoder.klein.spi.Join; -import com.ofcoder.klein.storage.facade.Instance; -import com.ofcoder.klein.storage.facade.LogManager; -import com.ofcoder.klein.storage.facade.Snap; -import com.ofcoder.klein.storage.facade.config.StorageProp; -import com.ofcoder.klein.storage.facade.exception.LockException; -import com.ofcoder.klein.storage.facade.exception.StorageException; - /** * Jvm LogManager. * @@ -60,8 +60,10 @@ public class FileLogManager

implements LogManager

{ private ConcurrentMap locks = new ConcurrentHashMap<>(); private MetaData metadata; + private final Serializer serializer; public FileLogManager(final StorageProp op) { + this.serializer = ExtensionLoader.getExtensionLoader(Serializer.class).register("hessian2"); runningInstances = new ConcurrentHashMap<>(); confirmedInstances = new ConcurrentHashMap<>(); @@ -69,7 +71,7 @@ public FileLogManager(final StorageProp op) { selfPath = op.getDataPath(); File selfFile = new File(selfPath); if (!selfFile.exists()) { - boolean mkdir = selfFile.mkdirs(); + boolean ignored = selfFile.mkdirs(); // do nothing for mkdir result } @@ -132,15 +134,12 @@ public MetaData loadMetaData(final MetaData defaultValue) { this.metadata = defaultValue; return this.metadata; } - FileInputStream lastIn = null; - try { - lastIn = new FileInputStream(file); - this.metadata = Hessian2Util.deserialize(IOUtils.toByteArray(lastIn)); + + try (FileInputStream lastIn = new FileInputStream(file);) { + this.metadata = serializer.deserialize(IOUtils.toByteArray(lastIn)); return this.metadata; } catch (IOException e) { throw new StorageException("loadMetaData, " + e.getMessage(), e); - } finally { - StreamUtil.close(lastIn); } } @@ -148,7 +147,7 @@ private void saveMetaData() { FileOutputStream mateOut = null; try { mateOut = new FileOutputStream(metaPath); - IOUtils.write(Hessian2Util.serialize(this.metadata), mateOut); + IOUtils.write(serializer.serialize(this.metadata), mateOut); } catch (IOException e) { throw new StorageException("save snap, " + e.getMessage(), e); } finally { @@ -158,6 +157,7 @@ private void saveMetaData() { @Override public void saveSnap(final String group, final Snap snap) { + LOG.debug("save snap, group: {}, checkpoint: {}", group, snap.getCheckpoint()); String bastPath = selfPath + File.separator + group + File.separator; File snapFile = new File(bastPath + snap.getCheckpoint()); if (snapFile.exists()) { @@ -165,7 +165,7 @@ public void saveSnap(final String group, final Snap snap) { } File baseDir = new File(bastPath); if (!baseDir.exists()) { - boolean mkdir = baseDir.mkdirs(); + boolean ignored = baseDir.mkdirs(); } File lastFile = new File(bastPath + "last"); @@ -175,8 +175,8 @@ public void saveSnap(final String group, final Snap snap) { try { lastOut = new FileOutputStream(lastFile); snapOut = new FileOutputStream(snapFile); - IOUtils.write(Hessian2Util.serialize(snap), snapOut); - IOUtils.write(Hessian2Util.serialize(snapFile.getPath()), lastOut); + IOUtils.write(serializer.serialize(snap), snapOut); + IOUtils.write(serializer.serialize(snapFile.getPath()), lastOut); } catch (IOException e) { throw new StorageException("save snap, " + e.getMessage(), e); } finally { @@ -206,9 +206,9 @@ public Snap getLastSnap(final String group) { FileInputStream snapIn = null; try { lastIn = new FileInputStream(file); - String deserialize = Hessian2Util.deserialize(IOUtils.toByteArray(lastIn)); + String deserialize = serializer.deserialize(IOUtils.toByteArray(lastIn)); snapIn = new FileInputStream(deserialize); - lastSnap = Hessian2Util.deserialize(IOUtils.toByteArray(snapIn)); + lastSnap = serializer.deserialize(IOUtils.toByteArray(snapIn)); return lastSnap; } catch (IOException e) { throw new StorageException("get last snap, " + e.getMessage(), e); diff --git a/klein-storage/klein-storage-file/src/test/java/com/ofcoder/klein/storage/file/FileLogManagerTest.java b/klein-storage/klein-storage-file/src/test/java/com/ofcoder/klein/storage/file/FileLogManagerTest.java index a6871362..0ce79b7a 100644 --- a/klein-storage/klein-storage-file/src/test/java/com/ofcoder/klein/storage/file/FileLogManagerTest.java +++ b/klein-storage/klein-storage-file/src/test/java/com/ofcoder/klein/storage/file/FileLogManagerTest.java @@ -1,31 +1,30 @@ package com.ofcoder.klein.storage.file; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - import com.google.common.collect.Lists; import com.ofcoder.klein.spi.ExtensionLoader; import com.ofcoder.klein.storage.facade.Instance; import com.ofcoder.klein.storage.facade.LogManager; +import com.ofcoder.klein.storage.facade.Snap; import com.ofcoder.klein.storage.facade.config.StorageProp; import com.ofcoder.klein.storage.facade.exception.LockException; +import java.util.List; +import java.util.Random; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; public class FileLogManagerTest { - LogManager join; + LogManager logManager; @Before public void setUp() { - join = ExtensionLoader.getExtensionLoader(LogManager.class).register("file", new StorageProp()); + logManager = ExtensionLoader.getExtensionLoader(LogManager.class).register("file", new StorageProp()); } @After public void shutdown() { - join.shutdown(); + logManager.shutdown(); } @Test(expected = LockException.class) @@ -35,12 +34,12 @@ public void testUpdateInstance_noLock() { instance.setInstanceId(1); instance.setState(Instance.State.PREPARED); instance.setGrantedValue(Lists.newArrayList("Zzz")); - join.updateInstance(instance); + logManager.updateInstance(instance); } @Test() public void testGetInstance() { - Instance nil = join.getInstance(1); + Instance nil = logManager.getInstance(1); Assert.assertNull(nil); Instance instance = new Instance<>(); @@ -49,11 +48,11 @@ public void testGetInstance() { instance.setState(Instance.State.PREPARED); instance.setGrantedValue(Lists.newArrayList("Zzz")); - join.getLock(instance.getInstanceId()).writeLock().lock(); - join.updateInstance(instance); - join.getLock(instance.getInstanceId()).writeLock().unlock(); + logManager.getLock(instance.getInstanceId()).writeLock().lock(); + logManager.updateInstance(instance); + logManager.getLock(instance.getInstanceId()).writeLock().unlock(); - Instance actual = join.getInstance(1); + Instance actual = logManager.getInstance(1); Assert.assertNotNull(actual); @@ -78,14 +77,14 @@ public void testGetInstanceNoConfirm() { instance2.setState(Instance.State.CONFIRMED); instance2.setGrantedValue(Lists.newArrayList("Zzz")); - join.getLock(instance1.getInstanceId()).writeLock().lock(); - join.updateInstance(instance1); - join.getLock(instance1.getInstanceId()).writeLock().unlock(); - join.getLock(instance2.getInstanceId()).writeLock().lock(); - join.updateInstance(instance2); - join.getLock(instance2.getInstanceId()).writeLock().unlock(); + logManager.getLock(instance1.getInstanceId()).writeLock().lock(); + logManager.updateInstance(instance1); + logManager.getLock(instance1.getInstanceId()).writeLock().unlock(); + logManager.getLock(instance2.getInstanceId()).writeLock().lock(); + logManager.updateInstance(instance2); + logManager.getLock(instance2.getInstanceId()).writeLock().unlock(); - List instanceNoConfirm = join.getInstanceNoConfirm(); + List instanceNoConfirm = logManager.getInstanceNoConfirm(); Assert.assertNotNull(instanceNoConfirm); Assert.assertEquals(1, instanceNoConfirm.size()); Instance actual = (Instance) instanceNoConfirm.get(0); @@ -97,7 +96,20 @@ public void testGetInstanceNoConfirm() { } @Test - public void testLoadMetaData(){ + public void testSaveSnapAndGetLastSnap() { + Snap snap = new Snap(new Random().nextLong(), new byte[] {0x1, 0x13, 0x12, 0x3, 0x3}); + Snap snap2 = new Snap(new Random().nextLong(), new byte[] {0x1, 0x13, 0x12, 0x3, 0x2}); + String group = "Test"; + logManager.saveSnap(group, snap); + Snap lastSnap = logManager.getLastSnap(group); + Assert.assertEquals(snap, lastSnap); + + logManager.saveSnap(group, snap2); + lastSnap = logManager.getLastSnap(group); + + Assert.assertEquals(snap2, lastSnap); + Assert.assertNotEquals(snap, lastSnap); } + } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 96ed394b..d6833458 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ klein-common klein-example klein-jepsen + klein-serializer @@ -99,6 +100,16 @@ klein-storage-facade ${project.version} + + com.ofcoder.klein.serializer.facade + klein-serializer-facade + ${project.version} + + + com.ofcoder.klein.serializer.hessian2 + klein-serializer-hessian2 + ${project.version} + com.ofcoder.klein.spi klein-spi