Titan Core Initial Contribution
[deliverable/titan.core.git] / JNI / jnimw.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "jnimw.h"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <memory.h>
13 #include <string.h>
14 #include <errno.h>
15
16 #include "../core/Logger.hh"
17
18 using mctr::MainController;
19 using namespace jnimw;
20
21 Jnimw *Jnimw::userInterface;
22 bool Jnimw::has_status_message_pending;
23 int Jnimw::pipe_size;
24
25 /**
26 * The last MC state. It is needed by status_change(), as
27 * status change message is written to the pipe when any status (MC, TC, HC) was changed AND
28 * ( currently there is no status change message on the pipe (signalled by has_status_message_pending)
29 * OR MC state is changed )
30 */
31 mctr::mc_state_enum last_mc_state;
32
33 pthread_mutex_t Jnimw::mutex = PTHREAD_MUTEX_INITIALIZER;
34
35 /**
36 * Config data, which was created by Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1cfg_1file()
37 * by a JNI request, and the result will be used by
38 * Java_org_eclipse_titan_executor_jni_JNIMiddleWare_configure().
39 * This is done this way to use process_config_read_file() for processing the config file
40 * instead of processing it on the Java side.
41 */
42 config_data Jnimw::mycfg;
43
44 void Jnimw::lock()
45 {
46 int result = pthread_mutex_lock(&mutex);
47 if (result > 0) {
48 fatal_error("Jni middleware::lock: "
49 "pthread_mutex_lock failed with code %d.", result);
50 }
51 }
52
53 void Jnimw::unlock()
54 {
55 int result = pthread_mutex_unlock(&mutex);
56 if (result > 0) {
57 fatal_error("Jni middleware:::unlock: "
58 "pthread_mutex_unlock failed with code %d.", result);
59 }
60 }
61
62 void Jnimw::fatal_error(const char *fmt, ...)
63 {
64 va_list ap;
65 va_start(ap, fmt);
66 vfprintf(stderr, fmt, ap);
67 va_end(ap);
68 if (errno != 0) fprintf(stderr, " (%s)", strerror(errno));
69 putc('\n', stderr);
70 exit(EXIT_FAILURE);
71 }
72
73 int Jnimw::enterLoop(int, char*[]) {
74 return EXIT_SUCCESS;
75 }
76
77 Jnimw::Jnimw()
78 {
79 pipe_buffer = NULL;
80 pipe_fd[0] = -1;
81 pipe_fd[1] = -1;
82
83 create_pipe();
84 FD_ZERO(&readfds);
85 FD_SET(pipe_fd[0], &readfds);
86
87 has_status_message_pending = false;
88 last_mc_state = mctr::MC_INACTIVE;
89 pipe_size = 0;
90
91 if (pthread_mutex_init(&mutex, NULL))
92 fatal_error("Jni middleware::constructor: pthread_mutex_init failed.");
93
94 }
95
96 Jnimw::~Jnimw()
97 {
98 destroy_pipe();
99 pthread_mutex_destroy(&mutex);
100 }
101
102
103 void strreverse(char* begin, char* end) {
104 char aux;
105 while(end>begin){
106 aux=*end, *end--=*begin, *begin++=aux;
107 }
108 }
109
110 /**
111 * Ansi C "itoa" based on Kernighan & Ritchie's "Ansi C":
112 */
113 void itoa(int value, char* str) {
114 static char num[] = "0123456789";
115 char* wstr=str;
116
117 // Conversion. Number is reversed.
118 do *wstr++ = num[value%10]; while(value/=10);
119 *wstr='\0';
120
121 // Reverse string
122 strreverse(str,wstr-1);
123 }
124
125 void create_packet_header(const int source_length, char* dest, char method_id) {
126 char packet_size[6];
127 dest[0] = method_id;
128 itoa(source_length, packet_size);
129 int i;
130 for(i = 1; i < 6; i++) dest[i] = '0';
131 dest[6] = '\0';
132 int j = strlen(packet_size);
133 for(i = 0; i < j; i++) dest[5-i] = packet_size[j-i-1];
134 }
135
136 char* stuffer(const char* msg){
137 char* msg_stuffed = (char*) malloc(strlen(msg)*2);
138 int i = 0;
139 int j = 0;
140 while(msg[i] != '\0') {
141 if(msg[i] != '|' && msg[i] != '\\') {
142 msg_stuffed[j++] = msg[i];
143 } else {
144 msg_stuffed[j++] = '\\';
145 msg_stuffed[j++] = msg[i];
146 }
147 i++;
148 }
149 msg_stuffed[j] = '\0';
150
151 return msg_stuffed;
152 }
153
154 //----------------------------------------------------------------------------
155 // USERINTERFACE
156
157 void Jnimw::status_change()
158 {
159 lock();
160 mctr::mc_state_enum mc_state = MainController::get_state();
161 if(last_mc_state != mc_state || !has_status_message_pending){
162 char str[7];
163 sprintf( str,"S%02d000", mc_state );
164 write_pipe( str );
165 }
166 has_status_message_pending = true;
167 last_mc_state = mc_state;
168 unlock();
169 }
170
171 //----------------------------------------------------------------------------
172 // USERINTERFACE
173
174 void Jnimw::error(int severity, const char* msg)
175 {
176 char *msg_stuffed = stuffer(msg);
177 expstring_t pipe_s;
178
179 // creating packet header
180 char packet_header[7];
181 expstring_t tmp;
182 tmp = mprintf("%d|%s", severity, msg_stuffed);
183 create_packet_header(strlen(tmp), packet_header, 'E');
184
185 pipe_s = mprintf("%s%s", packet_header, tmp);
186 free(msg_stuffed);
187
188 write_pipe(pipe_s);
189 }
190
191 //----------------------------------------------------------------------------
192 // USERINTERFACE
193
194 void Jnimw::notify(const struct timeval* time, const char* source,
195 int severity, const char* msg)
196 {
197 char *source_stuffed = stuffer(source);
198 char *msg_stuffed = stuffer(msg);
199 expstring_t pipe_s;
200
201 // creating packet header
202 char packet_header[7];
203 expstring_t tmp;
204 tmp = mprintf("%ld|%ld|%s|%d|%s", time->tv_sec, time->tv_usec, source_stuffed, severity, msg_stuffed);
205 create_packet_header(strlen(tmp), packet_header, 'N');
206
207 pipe_s = mprintf("%s%s", packet_header, tmp);
208 write_pipe(pipe_s);
209 free(source_stuffed);
210 free(msg_stuffed);
211 Free(tmp);
212 Free(pipe_s);
213 }
214
215 void Jnimw::create_pipe()
216 {
217 if (pipe(pipe_fd)){
218 printf("Jnimw::create_pipes(): pipe system call failed.\n");
219 }
220 }
221
222 void Jnimw::destroy_pipe()
223 {
224 close(pipe_fd[0]);
225 pipe_fd[0] = -1;
226 close(pipe_fd[1]);
227 pipe_fd[1] = -1;
228 }
229
230 bool Jnimw::is_pipe_readable(){
231 // TODO maybe this could get faster
232 timeval time;
233 time.tv_sec = 0;
234 time.tv_usec = 0;
235 fd_set read_set;
236 FD_ZERO(&read_set);
237 FD_SET(pipe_fd[0], &read_set);
238 int ret = select(pipe_fd[0] + 1 , &read_set, NULL, NULL, &time);
239 return ret > 0;
240 }
241
242 char* Jnimw::read_pipe()
243 {
244 select(pipe_fd[0] + 1 , &readfds, NULL, NULL, NULL);
245 lock();
246
247 pipe_buffer = (char*)malloc(7);
248 int ret = read(pipe_fd[0], pipe_buffer, 6);
249 if(ret != 6){
250 printf("Malformed packet arrived!\n");
251 }
252
253 pipe_size-= ret;
254
255 if(pipe_buffer[0] == 'S'){
256 has_status_message_pending = false;
257
258 unlock();
259 return pipe_buffer;
260 }
261
262 int packet_size = (pipe_buffer[1]-48) * 10000 + (pipe_buffer[2]-48) * 1000 +
263 (pipe_buffer[3]-48) * 100 + (pipe_buffer[4]-48) * 10 + (pipe_buffer[5]-48);
264
265 pipe_buffer = (char*)realloc(pipe_buffer, packet_size + 7);
266
267 ret = read(pipe_fd[0],pipe_buffer + 6, packet_size);
268 if(ret != packet_size){
269 printf("Jnimw::read_pipe(): read system call failed\n");
270 }
271 pipe_buffer[packet_size + 6] = '\0';
272
273 pipe_size-=ret;
274
275 unlock();
276 return pipe_buffer;
277 }
278
279 void Jnimw::write_pipe(const char *buf)
280 {
281 if (write(pipe_fd[1], buf, strlen(buf)) < 0){
282 printf("Jnimw::write_pipe(): write system call failed\n");
283 }
284
285 pipe_size+=strlen(buf);
286 }
This page took 0.184334 seconds and 6 git commands to generate.