/** * Unpack notifications from the binary form and link it with sending node (this information should be transferred * aside from the packed notification to not to produce redundant copies of it, all notifications from the same * node are packed together). Use {@link #pack(Collection)} to get packed binary. * * @param from node that has send notifications * @param packed representation * @return * @throws IOException */ static List<Notification> unpack(NodeInfo from, byte[] packed) throws IOException { ArrayList<Notification> notifications = new ArrayList<>(); Boss.Reader r = new Boss.Reader(packed); try { while (true) { // boss reader throws EOFException Notification n = read(from, r); if( n != null ) notifications.add(n); } } catch (EOFException x) { // normal, all data decoded } catch (InvocationTargetException | IllegalAccessException | InstantiationException | NullPointerException | NoSuchMethodException e) { throw new IOException("Failed to decoded notification", e); } return notifications; }
/** * Pack collection of notifications to binary array. Note that all notification packed together should be from the * same node, e.g. having the same {@link NodeInfo} (see {@link #getFrom()}, so from data is not packed to this * array and snould be transfered outside it. * * @param notifications notificatins to pack * * @return */ static byte[] pack(Collection<Notification> notifications) { Boss.Writer writer = new Boss.Writer(); try { for (Notification n : notifications) { write(writer, n); } return writer.toByteArray(); } catch (IOException e) { throw new RuntimeException("failed to pack notification", e); } }
public static void write(Boss.Writer writer, Notification n) throws IOException { writer.write(n.getTypeCode()); n.writeTo(writer); }
@Test public void packUnpack() throws Exception { NodeInfo ni = new NodeInfo(TestKeys.publicKey(0),1, "test1", "localhost", 17101, 17102, 17104); HashId id1 = HashId.createRandom(); ZonedDateTime now = ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS); ZonedDateTime expiresAt = now.plusDays(30); ItemResult ir1 = new ItemResult(ItemState.PENDING, false, now, expiresAt); ItemResult ir2 = new ItemResult(ItemState.REVOKED, true, now, expiresAt); ItemNotification n1 = new ItemNotification(ni, id1, ir1, true); ItemNotification n2 = new ItemNotification(ni, id1, ir1, false); ItemNotification n3 = new ItemNotification(ni, id1, ir1, true); byte[] packed = Notification.pack(asList(n1, n2, n3)); List<Notification> l = Notification.unpack(ni, packed); assertEquals(3, l.size()); ItemNotification n = (ItemNotification) l.get(0); assertEquals(n, n1); n = (ItemNotification) l.get(1); assertEquals(n, n2); n = (ItemNotification) l.get(2); assertEquals(n, n3); }
public static Notification read(NodeInfo from, Boss.Reader r) throws IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { int code = r.readInt(); Class<? extends Notification> nclass = classes.get(code); if( nclass != null ) { Constructor c = nclass.getDeclaredConstructor(); c.setAccessible(true); Notification n = (Notification) c.newInstance(); n.readFrom(r); n.from = from; return n; } else { System.out.println("*** unknown notification class code: "+code); return null; } }
if(to == null) { to = myInfo; from = notification.getFrom(); } else { from = myInfo;
private final byte[] packNotifications(NodeInfo from, Collection<Notification> notifications) { Boss.Writer w = new Boss.Writer(); try { w.write(1) // packet type code .write(from.getNumber()) // from number .write(notifications.size()); // count notifications notifications.forEach(n -> { try { Notification.write(w, n); } catch (IOException e) { throw new RuntimeException("notificaiton pack failure", e); } }); return w.toByteArray(); } catch (IOException e) { throw new RuntimeException("notificaiton pack failure", e); } }
nn.add(Notification.read(from, r));
private final byte[] packNotifications(NodeInfo from, Collection<Notification> notifications) { Boss.Writer w = new Boss.Writer(); try { w.write(1) // packet type code .write(from.getNumber()) // from number .write(notifications.size()); // count notifications notifications.forEach(n -> { try { Notification.write(w, n); } catch (IOException e) { throw new RuntimeException("notificaiton pack failure", e); } }); return w.toByteArray(); } catch (IOException e) { throw new RuntimeException("notificaiton pack failure", e); } }
private List<Notification> unpack(byte[] packedNotifications) throws IOException { List<Notification> nn = new ArrayList<>(); try { // packet type code Boss.Reader r = new Boss.Reader(packedNotifications); if (r.readInt() != 1) throw new IOException("invalid packed notification type code"); // from node number int number = r.readInt(); NodeInfo from = getInfo(number); if (from == null) throw new IOException("unknown node number: " + number); // number of notifications in the packet int count = r.readInt(); if (count < 0 || count > 1000) throw new IOException("unvalid packed notifications count: " + count); for (int i = 0; i < count; i++) { nn.add(Notification.read(from, r)); } return nn; } catch (Exception e) { e.printStackTrace(); System.err.println("failed to unpack notification: " + e); throw new IOException("failed to unpack notifications"); } }