Sync with 5.4.0
[deliverable/titan.core.git] / JNI / jnimw.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
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
18using mctr::MainController;
19using namespace jnimw;
20
21Jnimw *Jnimw::userInterface;
22bool Jnimw::has_status_message_pending;
23int 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 */
31mctr::mc_state_enum last_mc_state;
32
33pthread_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 */
42config_data Jnimw::mycfg;
43
44void 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
53void 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
62void 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
73int Jnimw::enterLoop(int, char*[]) {
74 return EXIT_SUCCESS;
75}
76
77Jnimw::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
96Jnimw::~Jnimw()
97{
98 destroy_pipe();
99 pthread_mutex_destroy(&mutex);
100}
101
102
103void 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 */
113void 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
125void 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
136char* 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
157void 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
174void 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
194void 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
215void Jnimw::create_pipe()
216{
217 if (pipe(pipe_fd)){
218 printf("Jnimw::create_pipes(): pipe system call failed.\n");
219 }
220}
221
222void 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
230bool 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
242char* 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
279void 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.052472 seconds and 5 git commands to generate.