Mercurial > hg > Database > Alice
changeset 525:30a74eee59c7 dispose
working TestRemoteAlice
author | Nozomi Teruya <e125769@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 16 Apr 2015 20:33:53 +0900 |
parents | 061478079bc7 |
children | 928907206d21 |
files | src/main/java/alice/codesegment/InputDataSegment.java src/main/java/alice/codesegment/OutputDataSegment.java src/main/java/alice/daemon/Connection.java src/main/java/alice/daemon/IncomingTcpConnection.java src/main/java/alice/daemon/IncomingUdpConnection.java src/main/java/alice/datasegment/Command.java src/main/java/alice/datasegment/CompressedRemoteDataSegmentManager.java src/main/java/alice/datasegment/DataSegment.java src/main/java/alice/datasegment/ReceiveData.java src/main/java/alice/datasegment/Receiver.java src/main/java/alice/test/codesegment/remote/RemoteIncrement.java src/main/java/alice/test/codesegment/remote/RemoteStartCodeSegment.java |
diffstat | 12 files changed, 250 insertions(+), 77 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/alice/codesegment/InputDataSegment.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/codesegment/InputDataSegment.java Thu Apr 16 20:33:53 2015 +0900 @@ -38,7 +38,7 @@ DataSegment.getCompressedLocal().peek(receiver, cs, true); } else { if (DataSegment.contains(receiver.managerKey)) {//remoteの場合 - DataSegment.get(receiver.managerKey).peek(receiver, cs, true);//remoteはあとで考える。DataSegment.connect + DataSegment.get(receiver.managerKey + "!").peek(receiver, cs, true); } } } else { @@ -62,7 +62,7 @@ DataSegment.getCompressedLocal().peek(receiver, cs, false); } else { if (DataSegment.contains(receiver.managerKey)) { - DataSegment.get(receiver.managerKey).peek(receiver, cs, false); + DataSegment.get(receiver.managerKey + "!").peek(receiver, cs, false); } } } else { @@ -79,22 +79,44 @@ public void quickTake(Receiver receiver) { cs.register(receiver); - if (receiver.managerKey==null){ - DataSegment.getLocal().take(receiver, cs, true); + + if (receiver.compressedFlag){ + if (receiver.managerKey==null){ + DataSegment.getCompressedLocal().take(receiver, cs, true); + } else { + if (DataSegment.contains(receiver.managerKey)) { + DataSegment.get(receiver.managerKey + "!").take(receiver, cs, true); + } + } } else { - if (DataSegment.contains(receiver.managerKey)) { - DataSegment.get(receiver.managerKey).take(receiver, cs, true); + if (receiver.managerKey==null){ + DataSegment.getLocal().take(receiver, cs, true); + } else { + if (DataSegment.contains(receiver.managerKey)) { + DataSegment.get(receiver.managerKey).take(receiver, cs, true); + } } } } public void take(Receiver receiver) { cs.register(receiver); - if (receiver.managerKey==null){ - DataSegment.getLocal().take(receiver, cs, false); + + if (receiver.compressedFlag){ + if (receiver.managerKey==null){ + DataSegment.getCompressedLocal().take(receiver, cs, false); + } else { + if (DataSegment.contains(receiver.managerKey)) { + DataSegment.get(receiver.managerKey + "!").take(receiver, cs, false); + } + } } else { - if (DataSegment.contains(receiver.managerKey)) { - DataSegment.get(receiver.managerKey).take(receiver, cs, false); + if (receiver.managerKey==null){ + DataSegment.getLocal().take(receiver, cs, false); + } else { + if (DataSegment.contains(receiver.managerKey)) { + DataSegment.get(receiver.managerKey).take(receiver, cs, false); + } } } } @@ -131,9 +153,10 @@ public Receiver create(CommandType type) { return new Receiver(this, type); }//Receiverを作成 + public Receiver create(CommandType type, boolean compressFlag) {//追加 return new Receiver(this, type, compressFlag); - }//Receiverを作成 + } public void recommand(Receiver receiver) { // TODO why only local?
--- a/src/main/java/alice/codesegment/OutputDataSegment.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/codesegment/OutputDataSegment.java Thu Apr 16 20:33:53 2015 +0900 @@ -17,16 +17,29 @@ * input→ds変更→outputのときコピーを防ぐ */ public void flip(Receiver receiver) { - DataSegment.getLocal().put(receiver.key, receiver.getReceiveData(), false); + if (receiver.isCompressed()){ + DataSegment.getCompressedLocal().put(receiver.key, receiver.getReceiveData(), false); + } else { + DataSegment.getLocal().put(receiver.key, receiver.getReceiveData(), false); + } } public void flip(Receiver receiver, CommandType type) { switch (type) { case PUT: - DataSegment.getLocal().put(receiver.key, receiver.getReceiveData(), false);//localなら全部false。 + if (receiver.isCompressed()){ + DataSegment.getCompressedLocal().put(receiver.key, receiver.getReceiveData(), false);//localなら全部false。 + } else { + DataSegment.getLocal().put(receiver.key, receiver.getReceiveData(), false); + } break; case UPDATE: - DataSegment.getLocal().update(receiver.key, receiver.getReceiveData(), false); + if (receiver.isCompressed()){ + DataSegment.getCompressedLocal().update(receiver.key, receiver.getReceiveData(), false); + } else { + DataSegment.getLocal().update(receiver.key, receiver.getReceiveData(), false); + } + break; default: break; @@ -38,12 +51,24 @@ } public void put(String key, Object val) { - ReceiveData rData = new ReceiveData(val, false, false); + ReceiveData rData = new ReceiveData(val); + DataSegment.getLocal().put(key, rData, false); + } + + public void put(String key, Object val, boolean cFlag) {//追加 + ReceiveData rData = new ReceiveData(val); + rData.setCompressFlag(cFlag); DataSegment.getLocal().put(key, rData, false); } public void update(String key, Object val) { - ReceiveData rData = new ReceiveData(val, false, false); + ReceiveData rData = new ReceiveData(val); + DataSegment.getLocal().update(key, rData, false); + } + + public void update(String key, Object val, boolean cFlag) {//追加 + ReceiveData rData = new ReceiveData(val); + rData.setCompressFlag(cFlag); DataSegment.getLocal().update(key, rData, false); } @@ -52,16 +77,30 @@ */ public void put(String managerKey, String key, ReceiveData rData) { if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - DataSegment.get(managerKey).put(key, rData, false); + if (rData.compressed()){ + DataSegment.get(managerKey + "!").put(key, rData, false); + } else { + DataSegment.get(managerKey).put(key, rData, false); + } + } else { put(key, rData); } } public void put(String managerKey, String key, Object val) { + put(managerKey, key, val, false); + } + + public void put(String managerKey, String key, Object val, boolean cFlag) {//追加 if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - ReceiveData rData = new ReceiveData(val, true, false);///false false - DataSegment.get(managerKey).put(key, rData, false); + ReceiveData rData = new ReceiveData(val); + rData.setCompressFlag(cFlag); + if (cFlag){ + DataSegment.get(managerKey + "!").put(key, rData, false); + } else { + DataSegment.get(managerKey).put(key, rData, false); + } } else { put(key, val); } @@ -69,16 +108,29 @@ public void quickPut(String managerKey, String key, ReceiveData rData) { if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - DataSegment.get(managerKey).put(key, rData, true); + if (rData.compressed()){ + DataSegment.get(managerKey + "!").put(key, rData, true); + } else { + DataSegment.get(managerKey).put(key, rData, true); + } } else { put(key, rData); } } public void quickPut(String managerKey, String key, Object val) { + quickPut(managerKey, key, val, false); + } + + public void quickPut(String managerKey, String key, Object val, boolean cFlag) {//追加 if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - ReceiveData rData = new ReceiveData(val, false, false); - DataSegment.get(managerKey).put(key, rData, true); + ReceiveData rData = new ReceiveData(val); + rData.setCompressFlag(cFlag); + if (cFlag){ + DataSegment.get(managerKey + "!").put(key, rData, true); + } else { + DataSegment.get(managerKey).put(key, rData, true); + } } else { put(key, val); } @@ -86,16 +138,29 @@ public void update(String managerKey, String key, ReceiveData rData) { if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - DataSegment.get(managerKey).update(key, rData, false); + if (rData.compressed()){ + DataSegment.get(managerKey + "!").update(key, rData, false); + } else { + DataSegment.get(managerKey).update(key, rData, false); + } } else { update(key, rData); } } public void update(String managerKey, String key, Object val) { + update(managerKey, key, val, false); + } + + public void update(String managerKey, String key, Object val, boolean cFlag) {//追加 if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - ReceiveData rData = new ReceiveData(val, true, false);///false, false - DataSegment.get(managerKey).update(key, rData, false); + ReceiveData rData = new ReceiveData(val); + rData.setCompressFlag(cFlag); + if(cFlag){ + DataSegment.get(managerKey + "!").update(key, rData, false); + } else { + DataSegment.get(managerKey).update(key, rData, false); + } } else { update(key, val); } @@ -103,16 +168,29 @@ public void quickUpdate(String managerKey, String key, ReceiveData rData) { if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - DataSegment.get(managerKey).update(key, rData, true); + if (rData.compressed()){ + DataSegment.get(managerKey + "!").update(key, rData, true); + } else { + DataSegment.get(managerKey).update(key, rData, true); + } } else { update(key, rData); } } public void quickUpdate(String managerKey, String key, Object val) { + quickUpdate(managerKey, key, val, false); + } + + public void quickUpdate(String managerKey, String key, Object val, boolean cFlag) {//追加 if (!managerKey.equals("local") && DataSegment.contains(managerKey)){ - ReceiveData rData = new ReceiveData(val, false, false); - DataSegment.get(managerKey).update(key, rData, true); + ReceiveData rData = new ReceiveData(val); + rData.setCompressFlag(cFlag); + if (cFlag){ + DataSegment.get(managerKey + "!").update(key, rData, true); + } else { + DataSegment.get(managerKey).update(key, rData, true); + } } else { update(key, val); }
--- a/src/main/java/alice/daemon/Connection.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/daemon/Connection.java Thu Apr 16 20:33:53 2015 +0900 @@ -57,7 +57,7 @@ public void putConnectionInfo() { if (name!=null){ ConnectionInfo c = new ConnectionInfo(name, socket); - ReceiveData rData = new ReceiveData(c, false, false); + ReceiveData rData = new ReceiveData(c); DataSegment.getLocal().put("_DISCONNECT", rData, false); if (sendManager) { SendOption option = new SendOption(false, false);
--- a/src/main/java/alice/daemon/IncomingTcpConnection.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/daemon/IncomingTcpConnection.java Thu Apr 16 20:33:53 2015 +0900 @@ -58,7 +58,8 @@ switch (type) { case UPDATE: case PUT: - rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt()), msg.compressed, msg.serialized); + rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt())); + rData.setCompressFlag(msg.compressed); if (msg.setTime) { rData.setTime = true; rData.time = msg.time; @@ -79,7 +80,8 @@ break; case REPLY: cmd = manager.getAndRemoveCmd(msg.seq); - rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt()), msg.compressed, msg.serialized); + rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt())); + rData.setCompressFlag(msg.compressed); Command rCmd = new Command(type, null, null, rData, msg.index, msg.seq, null, null, ""); cmd.cs.ids.reply(cmd.receiver, rCmd); break; @@ -88,7 +90,7 @@ DataSegment.get(reverseKey).response(msg.key); break; case RESPONSE: - rData = new ReceiveData(new RespondData(reverseKey, System.currentTimeMillis()), false, false); + rData = new ReceiveData(new RespondData(reverseKey, System.currentTimeMillis())); DataSegment.getLocal().put(msg.key, rData, false); break; default:
--- a/src/main/java/alice/daemon/IncomingUdpConnection.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/daemon/IncomingUdpConnection.java Thu Apr 16 20:33:53 2015 +0900 @@ -46,7 +46,8 @@ switch (type) { case UPDATE: case PUT: - rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt()), msg.compressed, msg.serialized); + rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt())); + rData.setCompressFlag(msg.compressed); cmd = new Command(type, null, null, rData, 0, 0, null, null, reverseKey); getLocalDataSegmentManager().getDataSegmentKey(msg.key).runCommand(cmd); break; @@ -62,7 +63,8 @@ break; case REPLY: cmd = manager.getAndRemoveCmd(msg.seq); - rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt()), msg.compressed, msg.serialized); + rData = new ReceiveData(unpacker.getSerializedByteArray(unpacker.readInt())); + rData.setCompressFlag(msg.compressed); Command rCmd = new Command(type, null, null, rData, msg.index, msg.seq, null, null, ""); cmd.cs.ids.reply(cmd.receiver, rCmd); break; @@ -71,7 +73,7 @@ DataSegment.get(reverseKey).response(msg.key); break; case RESPONSE: - rData = new ReceiveData(new RespondData(reverseKey, System.currentTimeMillis()), false, false); + rData = new ReceiveData(new RespondData(reverseKey, System.currentTimeMillis())); DataSegment.getLocal().put(msg.key, rData, false); break; default:
--- a/src/main/java/alice/datasegment/Command.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/datasegment/Command.java Thu Apr 16 20:33:53 2015 +0900 @@ -1,13 +1,9 @@ package alice.datasegment; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.BlockingQueue; -import java.util.zip.Deflater; -import java.util.zip.DeflaterOutputStream; -import org.apache.log4j.Logger; import org.msgpack.MessagePack; import alice.codesegment.CodeSegment; @@ -32,8 +28,6 @@ private boolean quickFlag = false;//SEDAを挟まずに処理を行うかどうか。trueだとリモート private boolean compressFlag = false;//trueだったら圧縮する必要がある - private Logger logger = Logger.getLogger("MessagePack"); - /** * for PEEK/TAKE */ @@ -79,7 +73,7 @@ /** * @return serialized ByteBuffer */ - public ByteBuffer convert() {//メッセージパックでbyteArrayに変換 + public ByteBuffer convert() {//byteArrayに変換 ByteBuffer buf = null; MessagePack msg = SingletonMessage.getInstance(); try { @@ -100,24 +94,14 @@ case UPDATE: case PUT: case REPLY://ReceiveDataからREPLYするDSを取得 - if (rData.compressed()) {//圧縮されている場合:各フラグの状態とDS本体を取得 - // have already converted - data = (byte[]) rData.getObj(); - compressed = rData.compressed(); - serialized = rData.serialized();//シリアライズされているか=Remoteから送られてきたか - } else {//圧縮されていない場合:状態にあわせてDS本体を取得し各フラグを立てる - if (!rData.serialized() && !rData.isByteArray()) { - data = msg.write(rData.getObj());//シリアライズ - serialized = true; - } else { // rData is RAW ByteArray or already serialized - data = (byte[]) rData.getObj(); - serialized = rData.serialized(); - } - if (compressFlag) {//圧縮する ここはあとで消す - data = rData.zip(data); - compressed = true; - } + if (rData.serialized()) {//純粋なオブジェクトの場合 + data = msg.write(rData.getObj());//シリアライズ + serialized = true; + } else { // rData is RAW ByteArray or already serialized ///or Compressed + data = rData.asByteArray(); + serialized = rData.serialized(); } + CommandMessage cm = new CommandMessage(type.id, index, seq, key, false, serialized, compressed); if (rData.setTime) {//AliceVNCの計測用(消してもいい) cm.setTime = true; @@ -133,15 +117,11 @@ buf.put(dataSize); buf.put(data); - //System.out.print("messagePack = " + Integer.toHexString(buf.getInt() & 0xff)); - logger.debug("messagePack = " + Integer.toHexString(buf.getInt() & 0xff)); - break; default://PEEK, TAKE, RemoveならCommandMessageとそのサイズのみセット header = msg.write(new CommandMessage(type.id, index, seq, key, quickFlag, false, compressFlag)); buf = ByteBuffer.allocate(header.length); buf.put(header); - //System.out.print("messagePack = " + Integer.toHexString(buf.getInt() & 0xff)); break; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/alice/datasegment/CompressedRemoteDataSegmentManager.java Thu Apr 16 20:33:53 2015 +0900 @@ -0,0 +1,54 @@ +package alice.datasegment; + +import alice.daemon.Connection; +import alice.daemon.IncomingTcpConnection; +import alice.daemon.OutboundTcpConnection; +import org.apache.log4j.Logger; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; + +/** + * Created by e125769 on 4/11/15. + */ +public class CompressedRemoteDataSegmentManager extends RemoteDataSegmentManager { + + public CompressedRemoteDataSegmentManager(){} + + public CompressedRemoteDataSegmentManager(final String connectionKey, final String reverseKey, final String hostName, final int port) { + logger = Logger.getLogger(connectionKey); + connection = new Connection(); + connection.name = connectionKey; + final RemoteDataSegmentManager manager = this; + //new Thread(replyThread, "RemoteDataSegmentManager-" + connectionKey).start(); + new Thread("Connect-" + connectionKey) { + public void run() { + boolean connect = true; + do { + try { + SocketChannel sc = SocketChannel.open(new InetSocketAddress(hostName, port)); + connection.socket = sc.socket(); + connection.socket.setTcpNoDelay(true); + connect = false; + logger.info("Connect to " + connection.getInfoString()); + } catch (IOException e) { + try { + Thread.sleep(50); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + } while (connect); + IncomingTcpConnection in = new IncomingTcpConnection(connection, manager, reverseKey); + in.setName(reverseKey+"-IncomingTcp"); + in.setPriority(MAX_PRIORITY); + in.start(); + OutboundTcpConnection out = new OutboundTcpConnection(connection); + out.setName(connectionKey+"-OutboundTcp"); + out.setPriority(MAX_PRIORITY); + out.start(); + } + }.start(); + } +}
--- a/src/main/java/alice/datasegment/DataSegment.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/datasegment/DataSegment.java Thu Apr 16 20:33:53 2015 +0900 @@ -4,6 +4,7 @@ import alice.daemon.IncomingTcpConnection; import alice.datasegment.MulticastDataSegmentManager.SocketType; +import org.apache.log4j.Logger; public class DataSegment { @@ -34,8 +35,17 @@ } public static RemoteDataSegmentManager connect(String connectionKey, String reverseKey, String hostName, int port) { + if (connectionKey.matches(".*!.*")){//!が含まれていたらエラーを返して終了 + Logger logger = Logger.getLogger("DataSegment"); + logger.error("You can't use '!' for DataSegmentManager name."); + System.exit(0); + } RemoteDataSegmentManager manager = new RemoteDataSegmentManager(connectionKey, reverseKey, hostName, port); + CompressedRemoteDataSegmentManager compresedManager = new CompressedRemoteDataSegmentManager(connectionKey + "!", reverseKey, hostName, port); + register(connectionKey, manager); + register(connectionKey + "!", compresedManager); + return manager; }
--- a/src/main/java/alice/datasegment/ReceiveData.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/datasegment/ReceiveData.java Thu Apr 16 20:33:53 2015 +0900 @@ -1,7 +1,6 @@ package alice.datasegment; -import java.io.ByteArrayOutputStream; -import java.io.IOException; +import java.io.*; import java.nio.ByteBuffer; import java.util.zip.*; @@ -18,6 +17,7 @@ private byte[] zMessagePack;//byteArray(compressed)のDS private Class<?> clazz; private Logger logger = Logger.getLogger("MessagePack"); + private boolean compressFlag = false; public long time;//測定用 public boolean setTime = false; @@ -25,13 +25,17 @@ /** * コンストラクタ。Object型のDSと圧縮のメタ情報を受け取る。 - * put/update用? + * put/update/reply用? * @param obj DS本体(Object) */ - public ReceiveData(Object obj, boolean cFlag, boolean sFlag) { + public ReceiveData(Object obj) { val = obj; - if (cFlag){ - messagePack = (byte[])val; + if (compressFlag){ + try { + messagePack = asByteArray();//(byte[]) val; だとキャストできない + } catch (IOException e) { + e.printStackTrace(); + } ByteBuffer buf = null; try { @@ -64,15 +68,15 @@ } - public boolean isByteArray(){//byteArrayフラグの状態を取得するメソッド - return messagePack != null; + public boolean isByteArray(){ + return messagePack != null | zMessagePack != null; } - public boolean compressed(){//compressedフラグの状態を取得するメソッド + public boolean compressed(){ return zMessagePack != null; } - public boolean serialized(){//serializedフラグの状態を取得するメソッド + public boolean serialized(){ return val != null; } @@ -131,7 +135,7 @@ if (val == null) { this.clazz = clazz; - return SingletonMessage.getInstance().read(b, clazz); + return SingletonMessage.getInstance().read(b, clazz);//messagePackから解凍 } else { return (T) val; } @@ -174,4 +178,18 @@ return os.toByteArray(); } + public byte[] asByteArray() throws IOException{ + ByteArrayOutputStream buff = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(buff); + out.writeObject(this.val); + byte[] bytes = buff.toByteArray(); + out.close(); + buff.close(); + return bytes; + } + + public void setCompressFlag(boolean cFlag){ + compressFlag = cFlag; + } + }
--- a/src/main/java/alice/datasegment/Receiver.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/datasegment/Receiver.java Thu Apr 16 20:33:53 2015 +0900 @@ -15,7 +15,7 @@ public int index; public String from; public CommandType type; - public String managerKey;//localかremoteか? + public String managerKey;//DSMを一意に特定。localかremoteか、どのremoteからか。 public String key; public boolean compressedFlag = false; @@ -121,4 +121,8 @@ public ReceiveData getReceiveData() { return data; } + + public boolean isCompressed(){ + return data.compressed(); + } }
--- a/src/main/java/alice/test/codesegment/remote/RemoteIncrement.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/test/codesegment/remote/RemoteIncrement.java Thu Apr 16 20:33:53 2015 +0900 @@ -6,7 +6,7 @@ public class RemoteIncrement extends CodeSegment { - public Receiver num = ids.create(CommandType.TAKE); + public Receiver num = ids.create(CommandType.TAKE);//true でCompressedDSMからtake /** * Increment DataSegment value up to 10 @@ -21,6 +21,7 @@ cs.num.setKey("remote", "num"); ods.put("local", "num", num); + //ods.put("remote", "num", num, true); } -} +} \ No newline at end of file
--- a/src/main/java/alice/test/codesegment/remote/RemoteStartCodeSegment.java Fri Apr 10 17:56:55 2015 +0900 +++ b/src/main/java/alice/test/codesegment/remote/RemoteStartCodeSegment.java Thu Apr 16 20:33:53 2015 +0900 @@ -10,6 +10,7 @@ cs.num.setKey("remote", "num"); ods.put("local", "num", 0); + //ods.put("remote", "num", 0, true); } }