litl  0.1.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
litl_split.c
Go to the documentation of this file.
1 /* -*- c-file-style: "GNU" -*- */
2 /*
3  * Copyright © Télécom SudParis.
4  * See COPYING in top-level directory.
5  */
6 
7 #define _GNU_SOURCE
8 #include <stdlib.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 
13 #include "litl_split.h"
14 
15 static litl_trace_split_t* __arch;
16 
17 /*
18  * Opens an archive of traces
19  */
20 static void __litl_split_open_archive(const char *arch_name) {
21  __arch = malloc(sizeof(litl_trace_split_t));
22 
23  // open an archive of traces
24  if ((__arch->f_handle = open(arch_name, O_RDONLY)) < 0) {
25  fprintf(stderr, "Cannot open %s\n", arch_name);
26  exit(EXIT_FAILURE);
27  }
28 
29  // allocate buffer for read/write ops
30  __arch->buffer_size = 16 * 1024 * 1024; // 16 MB
31  __arch->buffer = (litl_buffer_t) malloc(__arch->buffer_size);
32 }
33 
34 /*
35  * Initializes a structure that stores triples from the trace header
36  */
37 static void __litl_split_read_header() {
38  int res __attribute__ ((__unused__));
39 
40  litl_size_t header_size, general_header_size;
41  general_header_size = sizeof(litl_general_header_t);
42 
43  // read a general header
44  header_size = general_header_size;
45  __arch->header_buffer_ptr = (litl_buffer_t) malloc(header_size);
46  res = read(__arch->f_handle, __arch->header_buffer_ptr, header_size);
47  __arch->header_buffer = __arch->header_buffer_ptr;
48 
49  // get the number of processes
50  __arch->trace_header = (litl_general_header_t *) __arch->header_buffer;
51  __arch->nb_processes = __arch->trace_header->nb_processes;
52 
53  if (__arch->nb_processes == 1) {
54  printf(
55  "The given trace is not an archive. Therefore, there is nothing to split.\n");
56  exit(EXIT_SUCCESS);
57  }
58 
59  // Yes, we work with an archive of trace. So, we increase the header size
60  // and relocate the header buffer
61  header_size += __arch->nb_processes * sizeof(litl_process_header_t);
62  __arch->header_buffer_ptr = (litl_buffer_t) realloc(__arch->header_buffer_ptr,
63  header_size);
64 
65  // read headers of all processes
66  res = read(__arch->f_handle, __arch->header_buffer_ptr + general_header_size,
67  header_size - general_header_size);
68  if (res == -1) {
69  perror("Could not read the archive header!");
70  exit(EXIT_FAILURE);
71  }
72  __arch->header_buffer = __arch->header_buffer_ptr;
73  __arch->trace_header = (litl_general_header_t *) __arch->header_buffer;
74  __arch->header_buffer += general_header_size;
75 
76  // for splitting: one process into one trace file
77  __arch->trace_header->nb_processes = 1;
78 }
79 
80 /*
81  * Writes each trace from an archive into a separate trace file
82  */
83 static void __litl_split_extract_traces(const char *dir) {
84  int trace_out, res __attribute__ ((__unused__));
85  char* trace_name;
86  litl_size_t buffer_size;
87  litl_med_size_t general_header_size, process_header_size;
88 
89  general_header_size = sizeof(litl_general_header_t);
90  process_header_size = sizeof(litl_process_header_t);
91 
92  while (__arch->nb_processes-- != 0) {
93  // get a process header
95  __arch->header_buffer += process_header_size;
96 
97  res = asprintf(&trace_name, "%s/%s", dir,
98  __arch->process_header->process_name);
99 
100  // create and open a new trace file
101  if ((trace_out = open(trace_name, O_WRONLY | O_CREAT, 0644)) < 0) {
102  fprintf(stderr, "Cannot create and open %s\n",
103  __arch->process_header->process_name);
104  exit(EXIT_FAILURE);
105  }
106 
107  // write a general trace header
108  res = write(trace_out, __arch->trace_header, general_header_size);
109 
110  // write a process header
111  buffer_size = __arch->process_header->offset;
112  __arch->process_header->offset = general_header_size + process_header_size;
113  res = write(trace_out, __arch->process_header, process_header_size);
114 
115  // set a file pointer to the position of the current process
116  lseek(__arch->f_handle, buffer_size, SEEK_SET);
117 
118  // read data and write to a separate trace
119  while (__arch->process_header->trace_size) {
120  buffer_size =
121  __arch->process_header->trace_size > __arch->buffer_size ?
122  __arch->buffer_size : __arch->process_header->trace_size;
123 
124  res = read(__arch->f_handle, __arch->buffer, buffer_size);
125 
126  res = write(trace_out, __arch->buffer, buffer_size);
127 
128  __arch->process_header->trace_size -= buffer_size;
129  }
130 
131  free(trace_name);
132  close(trace_out);
133  }
134 }
135 
136 /*
137  * Closes the archive and free the allocated memory
138  */
139 static void __litl_split_close_archive() {
140  close(__arch->f_handle);
141  __arch->f_handle = -1;
142 
143  free(__arch->header_buffer_ptr);
144  free(__arch->buffer);
145  free(__arch);
146 }
147 
148 void litl_split_archive(const char *arch_name, const char *output_dir) {
149 
150  // open an archive of traces and allocate memory for a buffer
151  __litl_split_open_archive(arch_name);
152 
153  // get info from the archive's header
154  __litl_split_read_header();
155 
156  // split the archive
157  __litl_split_extract_traces(output_dir);
158 
159  // close the archive and free the allocated memory
160  __litl_split_close_archive();
161 }
litl_buffer_t header_buffer_ptr
Definition: litl_types.h:420
void litl_split_archive(const char *arch_name, const char *output_dir)
Extracts each trace from an archive into a separate trace file.
Definition: litl_split.c:148
litl_size_t buffer_size
Definition: litl_types.h:428
litl_split Provides a set of functions for extracting trace files from an archive of traces ...
A data structure for splitting an archive of traces.
Definition: litl_types.h:417
litl_med_size_t nb_processes
Definition: litl_types.h:425
litl_buffer_t header_buffer
Definition: litl_types.h:421
A general data structure that corresponds to the header of a trace file.
Definition: litl_types.h:258
litl_med_size_t nb_processes
Definition: litl_types.h:250
litl_buffer_t buffer
Definition: litl_types.h:427
uint8_t * litl_buffer_t
A data type for storing sets of events.
Definition: litl_types.h:133
litl_process_header_t * process_header
Definition: litl_types.h:423
litl_general_header_t * trace_header
Definition: litl_types.h:422
litl_offset_t offset
Definition: litl_types.h:264
uint16_t litl_med_size_t
An auxiliary data type for the optimized storage of data.
Definition: litl_types.h:150
uint32_t litl_size_t
An auxiliary data type for storing data.
Definition: litl_types.h:145
A general data structure that corresponds to the header of a trace file.
Definition: litl_types.h:247
litl_data_t process_name[256]
Definition: litl_types.h:259
litl_trace_size_t trace_size
Definition: litl_types.h:263