protected void reconnect() { if (retries <= 0) { Flog.log("Giving up!"); context.shutdown(); return; } delay = Math.min(10000, Math.round((float) 1.5 * delay)); Flog.log("Connection lost. Reconnecting in %sms", delay); context.setTimeout( delay, new Runnable() { @Override public void run() { Flog.log("Attempting to reconnect."); connect(); } }); }
public void send_patch(String current) { String before_md5; String textPatch; String after_md5; String previous = buf; before_md5 = md5; after_md5 = DigestUtils.md5Hex(current); LinkedList<diff_match_patch.Patch> patches = dmp.patch_make(previous, current); textPatch = dmp.patch_toText(patches); set(current, after_md5); if (before_md5.equals(after_md5)) { Flog.log("Not patching %s because no change.", path); return; } outbound.patch(textPatch, before_md5, this); }
@Override public void channelUnregistered(final ChannelHandlerContext ctx) { Flog.log("Disconnected from %s", ctx.channel().remoteAddress()); reconnect(); }
@Override public void channelInactive(final ChannelHandlerContext ctx) throws Exception { Flog.log("Channel is now inactive."); }
@Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { Flog.log("%s", evt.toString()); }
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { Flog.log("Connected to %s", ctx.channel().remoteAddress()); handler.on_connect(); }
public void patch(final FlooPatch res) { final TextBuf b = this; Flog.info("Got _on_patch"); String text; String md5FromDoc; final Document d; String oldText = buf; VirtualFile virtualFile = b.getVirtualFile(); if (virtualFile == null) { Flog.warn("VirtualFile is null, no idea what do do. Aborting everything %s", this); getBuf(); return; } d = Buf.getDocumentForVirtualFile(virtualFile); if (d == null) { Flog.warn("Document not found for %s", virtualFile); getBuf(); return; } String viewText; if (virtualFile.exists()) { viewText = d.getText(); if (viewText.equals(oldText)) { b.forced_patch = false; } else if (!b.forced_patch) { b.forced_patch = true; oldText = viewText; b.send_patch(viewText); Flog.warn("Sending force patch for %s. this is dangerous!", b.path); } } else { viewText = oldText; } b.cancelTimeout(); String md5Before = DigestUtils.md5Hex(viewText); if (!md5Before.equals(res.md5_before)) { Flog.warn("starting md5s don't match for %s. this is dangerous!", b.path); } List<diff_match_patch.Patch> patches = dmp.patch_fromText(res.patch); final Object[] results = dmp.patch_apply((LinkedList<diff_match_patch.Patch>) patches, oldText); final String patchedContents = (String) results[0]; final boolean[] patchesClean = (boolean[]) results[1]; final FlooPatchPosition[] positions = (FlooPatchPosition[]) results[2]; for (boolean clean : patchesClean) { if (!clean) { Flog.log("Patch not clean for %s. Sending get_buf and setting readonly.", d); getBuf(); return; } } // XXX: If patchedContents have carriage returns this will be a problem: String md5After = DigestUtils.md5Hex(patchedContents); if (!md5After.equals(res.md5_after)) { Flog.info("MD5 after mismatch (ours %s remote %s)", md5After, res.md5_after); } if (!d.isWritable()) { d.setReadOnly(false); } if (!ReadonlyStatusHandler.ensureDocumentWritable(context.project, d)) { Flog.info("Document: %s is not writable.", d); return; } final Editor[] editors = EditorFactory.getInstance().getEditors(d, context.project); final HashMap<ScrollingModel, Integer[]> original = new HashMap<ScrollingModel, Integer[]>(); for (Editor editor : editors) { if (editor.isDisposed()) { continue; } ScrollingModel scrollingModel = editor.getScrollingModel(); original.put( scrollingModel, new Integer[] { scrollingModel.getHorizontalScrollOffset(), scrollingModel.getVerticalScrollOffset() }); } for (FlooPatchPosition flooPatchPosition : positions) { int start = Math.max(0, flooPatchPosition.start); int end_ld = Math.max(start + flooPatchPosition.end, start); end_ld = Math.min(end_ld, d.getTextLength()); String contents = NEW_LINE.matcher(flooPatchPosition.text).replaceAll("\n"); Throwable e = null; try { Listener.flooDisable(); d.replaceString(start, end_ld, contents); } catch (Throwable exception) { e = exception; } finally { Listener.flooEnable(); } if (e != null) { Flog.warn(e); getBuf(); return; } } text = d.getText(); md5FromDoc = DigestUtils.md5Hex(text); if (!md5FromDoc.equals(res.md5_after)) { Flog.info("md5FromDoc mismatch (ours %s remote %s)", md5FromDoc, res.md5_after); b.setGetBufTimeout(); } for (Map.Entry<ScrollingModel, Integer[]> entry : original.entrySet()) { ScrollingModel model = entry.getKey(); Integer[] offsets = entry.getValue(); model.scrollHorizontally(offsets[0]); model.scrollVertically(offsets[1]); } b.set(text, md5FromDoc); Flog.log("Patched %s", res.path); }