@@ -62,205 +62,36 @@ const javaColumnHeader string = `
6262 * ColumnHeader contains information about a given column in the resulting trace file.
6363 *
6464 * @param name Name of the column, as found in the trace file.
65- * @param bytesPerElement Bytes required for each element in the column.
65+ * @param bitwidth Max number of bits required for any element in the column.
6666 */
67- public record ColumnHeader(String name, int register, long bytesPerElement, long length) { }
67+ public record ColumnHeader(String name, int register, int bitwidth, int length) { }
6868`
6969
7070// nolint
71- const javaAddMetadataSignature string = `
72- /**
73- * Add an item of metadata to this trace.
74- */
75- public void addMetadata(String key, Object value);
76- `
77-
78- // nolint
79- const javaOpenSignature string = `
80- /**
81- * Construct a new trace which will be written to a given file.
82- *
83- * @param file File into which the trace will be written. Observe any previous contents of this file will be lost.
84- * @return Trace object to use for writing column data.
85- *
86- * @throws IOException If an I/O error occurs.
87- */
88- public void open(RandomAccessFile file, List<ColumnHeader> rawHeaders) throws IOException;
89- `
90-
91- // nolint
92- const javaTraceOpen string = `
71+ const javaColumn string = `
9372 /**
94- * Construct a new trace which will be written to a given file.
95- *
96- * @param file File into which the trace will be written. Observe any previous contents of this file will be lost.
97- * @return Trace object to use for writing column data.
73+ * Column provides an interface for writing column data into the resulting trace file.
9874 *
99- * @throws IOException If an I/O error occurs.
10075 */
101- public void open(RandomAccessFile file, List<ColumnHeader> rawHeaders) throws IOException {
102- // Convert metadata into JSON bytes
103- byte[] metadataBytes = getMetadataBytes(metadata);
104- // Construct trace file header bytes
105- byte[] header = constructTraceFileHeader(metadataBytes);
106- // Align headers according to register indices.
107- ColumnHeader[] columnHeaders = alignHeaders(rawHeaders);
108- // Determine file size
109- long headerSize = determineColumnHeadersSize(columnHeaders) + header.length;
110- long dataSize = determineColumnDataSize(columnHeaders);
111- file.setLength(headerSize + dataSize);
112- // Write headers
113- writeHeaders(file,header,columnHeaders,headerSize);
114- // Initialise buffers
115- MappedByteBuffer[] buffers = initialiseByteBuffers(file,columnHeaders,headerSize);
116- // Done
117- this.open(buffers);
118- }
119-
120- /**
121- * Construct trace file header containing the given metadata bytes.
122- *
123- * @param metadata Metadata bytes to be embedded in the trace file.
124- *
125- * @return bytes making up the header.
126- */
127- private static byte[] constructTraceFileHeader(byte[] metadata) {
128- ByteBuffer buffer = ByteBuffer.allocate(16 + metadata.length);
129- // File identifier
130- buffer.put(new byte[]{'z','k','t','r','a','c','e','r'});
131- // Major version
132- buffer.putShort((short) 1);
133- // Minor version
134- buffer.putShort((short) 0);
135- // Metadata length
136- buffer.putInt(metadata.length);
137- // Metadata
138- buffer.put(metadata);
139- // Done
140- return buffer.array();
76+ public interface Column {
77+ public void write(boolean value);
78+ public void write(long value);
79+ public void write(byte[] value);
14180 }
81+ `
14282
83+ // nolint
84+ const javaAddMetadataSignature string = `
14385 /**
144- * Align headers ensures that the order in which columns are seen matches the order found in the trace schema.
145- *
146- * @param headers The headers to be aligned.
147- * @return The aligned headers.
86+ * Get static metadata stored within this trace during compilation.
14887 */
149- private static ColumnHeader[] alignHeaders(List<ColumnHeader> headers) {
150- ColumnHeader[] alignedHeaders = new ColumnHeader[{ninputs}];
151- //
152- for(ColumnHeader header : headers) {
153- alignedHeaders[header.register()] = header;
154- }
155- //
156- return alignedHeaders;
157- }
158-
159- /**
160- * Precompute the size of the trace file in order to memory map the buffers.
161- *
162- * @param headers Set of headers for the columns being written.
163- * @return Number of bytes requires for the trace file header.
164- */
165- private static long determineColumnHeadersSize(ColumnHeader[] headers) {
166- long nBytes = 4; // column count
167-
168- for (ColumnHeader header : headers) {
169- if(header != null) {
170- nBytes += 2; // name length
171- nBytes += header.name().length();
172- nBytes += 1; // byte per element
173- nBytes += 4; // element count
174- }
175- }
176-
177- return nBytes;
178- }
179-
180- /**
181- * Precompute the size of the trace file in order to memory map the buffers.
182- *
183- * @param headers Set of headers for the columns being written.
184- * @return Number of bytes required for storing all column data, excluding the header.
185- */
186- private static long determineColumnDataSize(ColumnHeader[] headers) {
187- long nBytes = 0;
188-
189- for (ColumnHeader header : headers) {
190- if(header != null) {
191- nBytes += header.length() * header.bytesPerElement();
192- }
193- }
194-
195- return nBytes;
196- }
197-
198- /**
199- * Write header information for the trace file.
200- *
201- * @param file Trace file being written.
202- * @param header Trace file header
203- * @param headers Column headers.
204- * @param size Overall size of the header.
205- */
206- private static void writeHeaders(RandomAccessFile file, byte[] header, ColumnHeader[] headers, long size) throws IOException {
207- final var buffer = file.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, size);
208- // Write trace file header
209- buffer.put(header);
210- // Write column count as uint32
211- buffer.putInt(countHeaders(headers));
212- // Write column headers one-by-one
213- for(ColumnHeader h : headers) {
214- if(h != null) {
215- buffer.putShort((short) h.name().length());
216- buffer.put(h.name().getBytes());
217- buffer.put((byte) h.bytesPerElement());
218- buffer.putInt((int) h.length());
219- }
220- }
221- }
222-
223- /**
224- * Initialise one memory mapped byte buffer for each column to be written in the trace.
225- * @param headers Set of headers for the columns being written.
226- * @param headerSize Space required at start of trace file for header.
227- * @return Buffer array with one entry per header.
228- */
229- private static MappedByteBuffer[] initialiseByteBuffers(RandomAccessFile file, ColumnHeader[] headers,
230- long headerSize) throws IOException {
231- MappedByteBuffer[] buffers = new MappedByteBuffer[{ninputs}];
232- long offset = headerSize;
233- for(int i=0;i<headers.length;i++) {
234- if(headers[i] != null) {
235- // Determine size (in bytes) required to store all elements of this column.
236- long length = headers[i].length() * headers[i].bytesPerElement();
237- // Preallocate space for this column.
238- buffers[i] = file.getChannel().map(FileChannel.MapMode.READ_WRITE, offset, length);
239- //
240- offset += length;
241- }
242- }
243- return buffers;
244- }
245-
246- /**
247- * Counter number of active (i.e. non-null) headers. A header can be null if
248- * it represents a column in a module which is not activated for this trace.
249- */
250- private static int countHeaders(ColumnHeader[] headers) throws IOException {
251- int count = 0;
252- for(ColumnHeader h : headers) {
253- if(h != null) { count++; }
254- }
255- return count;
256- }
88+ public Map<String,Object> getMetaData();
89+ `
25790
91+ // nolint
92+ const javaOpenSignature string = `
25893 /**
259- * Object writer is used for generating JSON byte strings .
94+ * Open this trace file for the given set of columns .
26095 */
261- private static final ObjectWriter objectWriter = new ObjectMapper().writer();
262-
263- public static byte[] getMetadataBytes(Map<String, Object> metadata) throws IOException {
264- return objectWriter.writeValueAsBytes(metadata);
265- }
96+ public void open(Column[] columns);
26697`
0 commit comments