1 /*
2  * Created: Apr 15, 2013
3  */
4 package org.xerial.snappy;
5 
6 import java.util.Random;
7 
8 /**
9  * Generates random data with specific expected snappy performance characteristics.
10  * <p/>
11  * <p>
12  * This has been copied from <a href="https://github.com/dain/snappy"> dain's snappy</a> implementation..
13  * </p>
14  */
15 public class RandomGenerator
16 {
17 
18     public final byte[] data;
19     public int position;
20 
RandomGenerator(double compressionRatio)21     public RandomGenerator(double compressionRatio)
22     {
23         // We use a limited amount of data over and over again and ensure
24         // that it is larger than the compression window (32KB), and also
25         // large enough to serve all typical value sizes we want to write.
26         Random rnd = new Random(301);
27         data = new byte[1048576 + 100];
28         for (int i = 0; i < 1048576; i += 100) {
29             // Add a short fragment that is as compressible as specified ratio
30             System.arraycopy(compressibleData(rnd, compressionRatio, 100), 0,
31                     data, i, 100);
32         }
33     }
34 
getNextPosition(int length)35     public int getNextPosition(int length)
36     {
37         if (position + length > data.length) {
38             position = 0;
39             assert (length < data.length);
40         }
41         int result = position;
42         position += length;
43         return result;
44     }
45 
46     private static byte[] compressibleData(Random random,
47             double compressionRatio, int length)
48     {
49         int raw = (int) (length * compressionRatio);
50         if (raw < 1) {
51             raw = 1;
52         }
53         byte[] rawData = generateRandomData(random, raw);
54 
55         // Duplicate the random data until we have filled "length" bytes
56         byte[] dest = new byte[length];
57         for (int i = 0; i < length; ) {
58             int chunkLength = Math.min(rawData.length, length - i);
59             System.arraycopy(rawData, 0, dest, i, chunkLength);
60             i += chunkLength;
61         }
62         return dest;
63     }
64 
65     private static byte[] generateRandomData(Random random, int length)
66     {
67         byte[] rawData = new byte[length];
68         for (int i = 0; i < rawData.length; i++) {
69             rawData[i] = (byte) random.nextInt(256);
70         }
71         return rawData;
72     }
73 }