private void writeRepeatedDelta(final int delta, final int repeatCount, final DataOutputStream dataStream) throws IOException { if (repeatCount > 1) { if (repeatCount > MAX_BYTE_REPEAT_COUNT) { dataStream.writeByte(TimelineOpcode.REPEATED_DELTA_TIME_SHORT.getOpcodeIndex()); dataStream.writeShort(repeatCount); } else if (repeatCount == 2) { dataStream.writeByte(delta); } else { dataStream.writeByte(TimelineOpcode.REPEATED_DELTA_TIME_BYTE.getOpcodeIndex()); dataStream.writeByte(repeatCount); } } dataStream.writeByte(delta); }
@Test(groups = "fast") public void testTimeCombineTimesError6() throws Exception { checkCombinedTimelines("ff4f95ac73fe471e00fe301e", "ff4f95ba83fe471e00fe311e", "ff4f95d595", "ff4f95e297fe091e"); checkCombinedTimelines("ff4f95ac7afe461e1d01fe301e", "ff4f95ba8afe471e00fe041e1ffe2b1e", "ff4f95d59d", "ff4f95e281fe0a1e"); checkCombinedTimelines("ff4f95aca4fe461e00fe311e", "ff4f95bab4fe461e00fe261e1f1dfe0a1e", "ff4f95d5a8", "ff4f95e28cfe091e"); checkCombinedTimelines("ff4f95ac88fe471e00fe311e", "ff4f95bab6fe461e00fe321e", "ff4f95d5aa", "ff4f95e28efe091eff4f95e4e6fe0a1e"); checkCombinedTimelines("ff4f95e394ff4f95e4fcfe0e1e5afe341e00fe221e", "ff4f95f12cfe551e00fe221e", "ff4f95ff3cfe551e00fe231e", "ff4f960d6afe541e00fe231e"); checkCombinedTimelines("ff4f95e396ff4f95e4fefe0e1e5afe341e00fe271e", "ff4f95f1c4fe501e00fe281e", "ff4f95fff2fe4f1e00fe281e", "ff4f960e02fe4f1e00fe291e"); }
@Override public DateTime getNextTime() { final int nextTime = getNextTimeInternal(); if (nextTime == -1) { throw new IllegalStateException(String.format("In DecodedSampleOutputProcessor.getNextTime(), got -1 from timeCursor.getNextTimeInternal()")); } else { return DateTimeUtils.dateTimeFromUnixSeconds(nextTime); } } }
unencodedTimes2.add(DateTimeUtils.dateTimeFromUnixSeconds(firstTime + sampleCount * 100 + i * 100)); final byte[] compressedTimes1 = timelineCoder.compressDateTimes(unencodedTimes1); final byte[] compressedTimes2 = timelineCoder.compressDateTimes(unencodedTimes2); Assert.assertEquals(compressedTimes1.length, 8); Assert.assertEquals(compressedTimes1[0] & 0xff, TimelineOpcode.FULL_TIME.getOpcodeIndex()); Assert.assertEquals(compressedTimes1[5] & 0xff, TimelineOpcode.REPEATED_DELTA_TIME_BYTE.getOpcodeIndex()); Assert.assertEquals(compressedTimes1[6] & 0xff, 9); Assert.assertEquals(compressedTimes1[7] & 0xff, 100); Assert.assertEquals(compressedTimes2.length, 8); Assert.assertEquals(compressedTimes2[0] & 0xff, TimelineOpcode.FULL_TIME.getOpcodeIndex()); Assert.assertEquals(compressedTimes2[5] & 0xff, TimelineOpcode.REPEATED_DELTA_TIME_BYTE.getOpcodeIndex()); Assert.assertEquals(compressedTimes2[6] & 0xff, 9); Assert.assertEquals(compressedTimes2[7] & 0xff, 100); timesList.add(compressedTimes1); timesList.add(compressedTimes2); final byte[] combinedTimes = timelineCoder.combineTimelines(timesList, null); Assert.assertEquals(combinedTimes.length, 8); Assert.assertEquals(combinedTimes[0] & 0xff, TimelineOpcode.FULL_TIME.getOpcodeIndex()); Assert.assertEquals(combinedTimes[5] & 0xff, TimelineOpcode.REPEATED_DELTA_TIME_BYTE.getOpcodeIndex()); Assert.assertEquals(combinedTimes[6] & 0xff, 19); Assert.assertEquals(combinedTimes[7] & 0xff, 100); Assert.assertEquals(timelineCoder.countTimeBytesSamples(combinedTimes), 20);
private void checkCombinedTimelines(final String... timelines) throws Exception { final List<byte[]> timeParts = new ArrayList<byte[]>(); for (final String timeline : timelines) { timeParts.add(Hex.decodeHex(timeline.toCharArray())); } int sampleCount = 0; int byteCount = 0; for (final byte[] timePart : timeParts) { byteCount += timePart.length; sampleCount += timelineCoder.countTimeBytesSamples(timePart); } final byte[] concatedTimes = new byte[byteCount]; int offset = 0; for (final byte[] timePart : timeParts) { final int length = timePart.length; System.arraycopy(timePart, 0, concatedTimes, offset, length); offset += length; } final byte[] newCombined = timelineCoder.combineTimelines(timeParts, null); final int newCombinedLength = timelineCoder.countTimeBytesSamples(newCombined); final DefaultTimelineCursor concatedCursor = new DefaultTimelineCursor(concatedTimes, sampleCount); final DefaultTimelineCursor combinedCursor = new DefaultTimelineCursor(newCombined, sampleCount); for (int i = 0; i < sampleCount; i++) { final DateTime concatedTime = concatedCursor.getNextTime(); final DateTime combinedTime = combinedCursor.getNextTime(); Assert.assertEquals(combinedTime, concatedTime); } Assert.assertEquals(newCombinedLength, sampleCount); } }
@Test(groups = "fast") public void testTimeRangeSampleProcessor() throws Exception { final DateTime startTime = new DateTime(dateFormatter.parseDateTime("2012-03-23T17:35:11.000Z")); final DateTime endTime = new DateTime(dateFormatter.parseDateTime("2012-03-23T17:35:17.000Z")); final int sampleCount = 2; final List<DateTime> dateTimes = ImmutableList.<DateTime>of(startTime, endTime); final byte[] compressedTimes = timelineCoder.compressDateTimes(dateTimes); final TimelineCursor cursor = new DefaultTimelineCursor(compressedTimes, sampleCount); Assert.assertEquals(cursor.getNextTime(), startTime); Assert.assertEquals(cursor.getNextTime(), endTime); // 2 x the value 12: REPEAT_BYTE, SHORT, 2, SHORT, 12 (2 bytes) final byte[] samples = new byte[]{(byte) 0xff, 2, 2, 0, 12}; final AtomicInteger samplesCount = new AtomicInteger(0); sampleCoder.scan(samples, compressedTimes, sampleCount, new TimeRangeSampleProcessor(startTime, endTime) { @Override public void processOneSample(final DateTime time, final SampleOpcode opcode, final Object value) { if (samplesCount.get() == 0) { Assert.assertEquals(DateTimeUtils.unixSeconds(time), DateTimeUtils.unixSeconds(startTime)); } else { Assert.assertEquals(DateTimeUtils.unixSeconds(time), DateTimeUtils.unixSeconds(endTime)); } samplesCount.incrementAndGet(); } }); Assert.assertEquals(samplesCount.get(), sampleCount); }
unencodedTimes2.add(DateTimeUtils.dateTimeFromUnixSeconds(firstTime + sampleCount * 100 + i * 100)); final byte[] compressedTimes1 = timelineCoder.compressDateTimes(unencodedTimes1); final byte[] compressedTimes2 = timelineCoder.compressDateTimes(unencodedTimes2); Assert.assertEquals(compressedTimes1.length, 8); Assert.assertEquals(compressedTimes1[0] & 0xff, TimelineOpcode.FULL_TIME.getOpcodeIndex()); Assert.assertEquals(compressedTimes1[5] & 0xff, TimelineOpcode.REPEATED_DELTA_TIME_BYTE.getOpcodeIndex()); Assert.assertEquals(compressedTimes1[6] & 0xff, sampleCount - 1); Assert.assertEquals(compressedTimes1[7] & 0xff, 100); Assert.assertEquals(compressedTimes2.length, 8); Assert.assertEquals(compressedTimes2[0] & 0xff, TimelineOpcode.FULL_TIME.getOpcodeIndex()); Assert.assertEquals(compressedTimes2[5] & 0xff, TimelineOpcode.REPEATED_DELTA_TIME_BYTE.getOpcodeIndex()); Assert.assertEquals(compressedTimes2[6] & 0xff, sampleCount - 1); Assert.assertEquals(compressedTimes2[7] & 0xff, 100); timesList.add(compressedTimes1); timesList.add(compressedTimes2); final byte[] combinedTimes = timelineCoder.combineTimelines(timesList, null); Assert.assertEquals(combinedTimes.length, 9); Assert.assertEquals(combinedTimes[0] & 0xff, TimelineOpcode.FULL_TIME.getOpcodeIndex()); Assert.assertEquals(combinedTimes[5] & 0xff, TimelineOpcode.REPEATED_DELTA_TIME_SHORT.getOpcodeIndex()); Assert.assertEquals(combinedTimes[6] & 0xff, 1); Assert.assertEquals(combinedTimes[7] & 0xff, sampleCount * 2 - 1 - 256);
@Test(groups = "fast") public void testBasicEncodeDecode() throws Exception { final DateTime firstTime = DateTimeUtils.dateTimeFromUnixSeconds(1000000); final List<DateTime> unencodedTimes = makeSomeTimes(firstTime); final byte[] compressedTimes = timelineCoder.compressDateTimes(unencodedTimes); //System.out.printf("Compressed times: %s\n", new String(Hex.encodeHex(compressedTimes))); final List<DateTime> decompressedTimes = timelineCoder.decompressDateTimes(compressedTimes); Assert.assertEquals(decompressedTimes.size(), unencodedTimes.size()); for (int i = 0; i < unencodedTimes.size(); i++) { Assert.assertEquals(decompressedTimes.get(i), unencodedTimes.get(i)); } }
@Test(groups = "fast") public void testMaxDeltaTime() throws Exception { for (final TimelineOpcode opcode : TimelineOpcode.values()) { Assert.assertTrue(opcode.getOpcodeIndex() >= TimelineOpcode.MAX_DELTA_TIME); } } }
final ByteArrayInputStream byteStream = new ByteArrayInputStream(samples); final DataInputStream inputStream = new DataInputStream(byteStream); final TimelineCursor timeCursor = new DefaultTimelineCursor(times, sampleCount); int sampleNumber = 0; while (true) { processor.processSamples(timeCursor, repeatCount, replacementOpcode, value); sampleNumber += repeatCount; timeCursor.skipToSampleNumber(sampleNumber); break; default:
/** * Process sampleCount sequential samples with identical values. sampleCount will usually be 1, * but may be larger than 1. Implementors may just loop processing identical values, but some * implementations may optimize adding a bunch of repeated values * * @param timeCursor a TimeCursor instance, which supplies successive int UNIX times * @param sampleCount the count of sequential, identical values * @param opcode the opcode of the sample value, which may not be a REPEAT opcode * @param value the value of this kind of sample over the sampleCount samples */ @Override public void processSamples(final TimelineCursor timeCursor, final int sampleCount, final SampleOpcode opcode, final Object value) { for (int i = 0; i < sampleCount; i++) { // Check if the sample is in the right time range final DateTime sampleTime = timeCursor.getNextTime(); if ((startTime == null || !sampleTime.isBefore(startTime)) && ((endTime == null || !sampleTime.isAfter(endTime)))) { processOneSample(sampleTime, opcode, value); } } }
@Test(groups = "fast") public void testCombiningTimesError() throws Exception { final byte[] times1 = Hex.decodeHex("ff10000001fe0310ff1000011bfe0310".toCharArray()); final byte[] times2 = Hex.decodeHex("ff10000160".toCharArray()); final List<byte[]> timesList = new ArrayList<byte[]>(); timesList.add(times1); timesList.add(times2); final byte[] combinedTimes = timelineCoder.combineTimelines(timesList, null); final String hexCombinedTimes = new String(Hex.encodeHex(combinedTimes)); //System.out.printf("Combined times: %s\n", hexCombinedTimes); Assert.assertEquals(hexCombinedTimes, "ff10000001fe0310eafe031015"); }
@Test(groups = "fast") public void testRepeats() throws Exception { final DateTime firstTime = DateTimeUtils.dateTimeFromUnixSeconds(1293846); final List<DateTime> unencodedTimes = makeSomeTimes(firstTime); final byte[] compressedTimes = timelineCoder.compressDateTimes(unencodedTimes); final List<DateTime> decompressedTimes = timelineCoder.decompressDateTimes(compressedTimes); Assert.assertEquals(decompressedTimes.size(), unencodedTimes.size()); for (int i = 0; i < unencodedTimes.size(); i++) { Assert.assertEquals(decompressedTimes.get(i), unencodedTimes.get(i)); } }
private void writeTime(final int lastTime, final int newTime, final DataOutputStream dataStream) throws IOException { if (newTime > lastTime) { final int delta = (newTime - lastTime); if (delta <= TimelineOpcode.MAX_DELTA_TIME) { dataStream.writeByte(delta); } else { dataStream.writeByte(TimelineOpcode.FULL_TIME.getOpcodeIndex()); dataStream.writeInt(newTime); } } else if (newTime == lastTime) { dataStream.writeByte(0); } } }
@Override public void processSamples(final TimelineCursor timeCursor, final int sampleCount, final SampleOpcode opcode, final Object value) { if (builder.length() > 0) { builder.append(", "); } final DateTime timestamp = timeCursor.getNextTime(); builder.append("at ").append(timestamp.toString("yyyy-MM-dd HH:mm:ss")).append(" "); if (sampleCount > 1) { builder.append(sampleCount).append(" of "); } builder.append(opcode.name().toLowerCase()); switch (opcode) { case NULL: case DOUBLE_ZERO: case INT_ZERO: break; default: builder.append("(").append(String.valueOf(value)).append(")"); break; } }
@Test(groups = "fast") public void testTimeCombineTimesError3() throws Exception { checkCombinedTimelines("ff4f9224ecfe091e", "ff4f922618fe071e78fe111e78fe111e78fe111e78fe111efe02005afe121e78fe031e", "ff4f923428fe0d1e7dfe111e78fe111e78fe111e78fe0b1e00fe061e78fe111e", "ff4f92427cfe111e78fe111e78fe111e78fe111e82fe041e1d01fe0c1e78fe0e1e"); }
@Test(groups = "fast") public void testTimeCombineTimesError1() throws Exception { checkCombinedTimelines("ff4f91fb14fe631e00fe151e", "ff4f920942"); }
@Test(groups = "fast") public void testTimeCombineTimesError4() throws Exception { checkCombinedTimelines("ff4f95ba83fe021e", "ff4f95d595", "ff4f95e297fe021e"); }
@Test(groups = "fast") public void testTimeCombineTimesError2() throws Exception { checkCombinedTimelines("ff4f922618fe111e78fe111efe02005a", "ff4f923428"); }
@Test(groups = "fast") public void testTimeCombineTimesError5() throws Exception { checkCombinedTimelines("ff00000100", "ff00000200"); }