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