nxt_java.c (1532:4b4d0c3ce94b) nxt_java.c (1684:a10e10f3071f)
1
2/*
3 * Copyright (C) NGINX, Inc.
4 */
5
6
7#include <jni.h>
8

--- 22 unchanged lines hidden (view full) ---

31
32static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
33 nxt_common_app_conf_t *conf);
34static nxt_int_t nxt_java_start(nxt_task_t *task,
35 nxt_process_data_t *data);
36static void nxt_java_request_handler(nxt_unit_request_info_t *req);
37static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws);
38static void nxt_java_close_handler(nxt_unit_request_info_t *req);
1
2/*
3 * Copyright (C) NGINX, Inc.
4 */
5
6
7#include <jni.h>
8

--- 22 unchanged lines hidden (view full) ---

31
32static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
33 nxt_common_app_conf_t *conf);
34static nxt_int_t nxt_java_start(nxt_task_t *task,
35 nxt_process_data_t *data);
36static void nxt_java_request_handler(nxt_unit_request_info_t *req);
37static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws);
38static void nxt_java_close_handler(nxt_unit_request_info_t *req);
39static int nxt_java_ready_handler(nxt_unit_ctx_t *ctx);
40static void *nxt_java_thread_func(void *main_ctx);
41static int nxt_java_init_threads(nxt_java_app_conf_t *c);
42static void nxt_java_join_threads(nxt_unit_ctx_t *ctx,
43 nxt_java_app_conf_t *c);
39
40static uint32_t compat[] = {
41 NXT_VERNUM, NXT_DEBUG,
42};
43
44char *nxt_java_modules;
45
44
45static uint32_t compat[] = {
46 NXT_VERNUM, NXT_DEBUG,
47};
48
49char *nxt_java_modules;
50
51static pthread_t *nxt_java_threads;
52static pthread_attr_t *nxt_java_thread_attr;
46
53
54
47#define NXT_STRING(x) _NXT_STRING(x)
48#define _NXT_STRING(x) #x
49
50NXT_EXPORT nxt_app_module_t nxt_app_module = {
51 sizeof(compat),
52 compat,
53 nxt_string("java"),
54 NXT_STRING(NXT_JAVA_VERSION),
55 nxt_java_mounts,
56 nxt_nitems(nxt_java_mounts),
57 nxt_java_setup,
58 nxt_java_start,
59};
60
61typedef struct {
55#define NXT_STRING(x) _NXT_STRING(x)
56#define _NXT_STRING(x) #x
57
58NXT_EXPORT nxt_app_module_t nxt_app_module = {
59 sizeof(compat),
60 compat,
61 nxt_string("java"),
62 NXT_STRING(NXT_JAVA_VERSION),
63 nxt_java_mounts,
64 nxt_nitems(nxt_java_mounts),
65 nxt_java_setup,
66 nxt_java_start,
67};
68
69typedef struct {
62 JNIEnv *env;
63 jobject ctx;
70 JavaVM *jvm;
71 jobject cl;
72 jobject ctx;
73 nxt_java_app_conf_t *conf;
64} nxt_java_data_t;
65
66
67static nxt_int_t
68nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
69 nxt_common_app_conf_t *conf)
70{
71 char *path, *relpath, *p, *rootfs;

--- 325 unchanged lines hidden (view full) ---

397 }
398
399 classpath = nxt_java_newURLs(env, classpath_count, classpath_arr);
400 if (classpath == NULL) {
401 nxt_alert(task, "nxt_java_newURLs failed");
402 goto env_failed;
403 }
404
74} nxt_java_data_t;
75
76
77static nxt_int_t
78nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
79 nxt_common_app_conf_t *conf)
80{
81 char *path, *relpath, *p, *rootfs;

--- 325 unchanged lines hidden (view full) ---

407 }
408
409 classpath = nxt_java_newURLs(env, classpath_count, classpath_arr);
410 if (classpath == NULL) {
411 nxt_alert(task, "nxt_java_newURLs failed");
412 goto env_failed;
413 }
414
405 java_data.env = env;
415 java_data.jvm = jvm;
416 java_data.cl = cl;
406 java_data.ctx = nxt_java_startContext(env, c->webapp, classpath);
417 java_data.ctx = nxt_java_startContext(env, c->webapp, classpath);
418 java_data.conf = c;
407
408 if ((*env)->ExceptionCheck(env)) {
409 nxt_alert(task, "Unhandled exception in application start");
410 (*env)->ExceptionDescribe(env);
411 return NXT_ERROR;
412 }
413
419
420 if ((*env)->ExceptionCheck(env)) {
421 nxt_alert(task, "Unhandled exception in application start");
422 (*env)->ExceptionDescribe(env);
423 return NXT_ERROR;
424 }
425
426 rc = nxt_java_init_threads(c);
427 if (nxt_slow_path(rc == NXT_UNIT_ERROR)) {
428 return NXT_ERROR;
429 }
430
414 nxt_unit_default_init(task, &java_init);
415
416 java_init.callbacks.request_handler = nxt_java_request_handler;
417 java_init.callbacks.websocket_handler = nxt_java_websocket_handler;
418 java_init.callbacks.close_handler = nxt_java_close_handler;
431 nxt_unit_default_init(task, &java_init);
432
433 java_init.callbacks.request_handler = nxt_java_request_handler;
434 java_init.callbacks.websocket_handler = nxt_java_websocket_handler;
435 java_init.callbacks.close_handler = nxt_java_close_handler;
436 java_init.callbacks.ready_handler = nxt_java_ready_handler;
419 java_init.request_data_size = sizeof(nxt_java_request_data_t);
420 java_init.data = &java_data;
437 java_init.request_data_size = sizeof(nxt_java_request_data_t);
438 java_init.data = &java_data;
439 java_init.ctx_data = env;
421 java_init.shm_limit = app_conf->shm_limit;
422
423 ctx = nxt_unit_init(&java_init);
424 if (nxt_slow_path(ctx == NULL)) {
425 nxt_alert(task, "nxt_unit_init() failed");
426 return NXT_ERROR;
427 }
428
429 rc = nxt_unit_run(ctx);
440 java_init.shm_limit = app_conf->shm_limit;
441
442 ctx = nxt_unit_init(&java_init);
443 if (nxt_slow_path(ctx == NULL)) {
444 nxt_alert(task, "nxt_unit_init() failed");
445 return NXT_ERROR;
446 }
447
448 rc = nxt_unit_run(ctx);
430 if (nxt_slow_path(rc != NXT_UNIT_OK)) {
431 /* TODO report error */
432 }
433
449
450 nxt_java_join_threads(ctx, c);
451
434 nxt_java_stopContext(env, java_data.ctx);
435
436 if ((*env)->ExceptionCheck(env)) {
437 (*env)->ExceptionDescribe(env);
438 }
439
440 nxt_unit_done(ctx);
441
442 (*jvm)->DestroyJavaVM(jvm);
443
452 nxt_java_stopContext(env, java_data.ctx);
453
454 if ((*env)->ExceptionCheck(env)) {
455 (*env)->ExceptionDescribe(env);
456 }
457
458 nxt_unit_done(ctx);
459
460 (*jvm)->DestroyJavaVM(jvm);
461
444 exit(0);
462 exit(rc);
445
446 return NXT_OK;
447
448env_failed:
449
450 if ((*env)->ExceptionCheck(env)) {
451 (*env)->ExceptionDescribe(env);
452 }

--- 6 unchanged lines hidden (view full) ---

459nxt_java_request_handler(nxt_unit_request_info_t *req)
460{
461 JNIEnv *env;
462 jobject jreq, jresp;
463 nxt_java_data_t *java_data;
464 nxt_java_request_data_t *data;
465
466 java_data = req->unit->data;
463
464 return NXT_OK;
465
466env_failed:
467
468 if ((*env)->ExceptionCheck(env)) {
469 (*env)->ExceptionDescribe(env);
470 }

--- 6 unchanged lines hidden (view full) ---

477nxt_java_request_handler(nxt_unit_request_info_t *req)
478{
479 JNIEnv *env;
480 jobject jreq, jresp;
481 nxt_java_data_t *java_data;
482 nxt_java_request_data_t *data;
483
484 java_data = req->unit->data;
467 env = java_data->env;
485 env = req->ctx->data;
468 data = req->data;
469
470 jreq = nxt_java_newRequest(env, java_data->ctx, req);
471 if (jreq == NULL) {
472 nxt_unit_req_alert(req, "failed to create Request instance");
473
474 if ((*env)->ExceptionCheck(env)) {
475 (*env)->ExceptionDescribe(env);

--- 62 unchanged lines hidden (view full) ---

538
539
540static void
541nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws)
542{
543 void *b;
544 JNIEnv *env;
545 jobject jbuf;
486 data = req->data;
487
488 jreq = nxt_java_newRequest(env, java_data->ctx, req);
489 if (jreq == NULL) {
490 nxt_unit_req_alert(req, "failed to create Request instance");
491
492 if ((*env)->ExceptionCheck(env)) {
493 (*env)->ExceptionDescribe(env);

--- 62 unchanged lines hidden (view full) ---

556
557
558static void
559nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws)
560{
561 void *b;
562 JNIEnv *env;
563 jobject jbuf;
546 nxt_java_data_t *java_data;
547 nxt_java_request_data_t *data;
548
564 nxt_java_request_data_t *data;
565
549 java_data = ws->req->unit->data;
550 env = java_data->env;
566 env = ws->req->ctx->data;
551 data = ws->req->data;
552
553 b = malloc(ws->payload_len);
554 if (b != NULL) {
555 nxt_unit_websocket_read(ws, b, ws->payload_len);
556
557 jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len);
558 if (jbuf != NULL) {

--- 14 unchanged lines hidden (view full) ---

573 nxt_unit_websocket_done(ws);
574}
575
576
577static void
578nxt_java_close_handler(nxt_unit_request_info_t *req)
579{
580 JNIEnv *env;
567 data = ws->req->data;
568
569 b = malloc(ws->payload_len);
570 if (b != NULL) {
571 nxt_unit_websocket_read(ws, b, ws->payload_len);
572
573 jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len);
574 if (jbuf != NULL) {

--- 14 unchanged lines hidden (view full) ---

589 nxt_unit_websocket_done(ws);
590}
591
592
593static void
594nxt_java_close_handler(nxt_unit_request_info_t *req)
595{
596 JNIEnv *env;
581 nxt_java_data_t *java_data;
582 nxt_java_request_data_t *data;
583
597 nxt_java_request_data_t *data;
598
584 java_data = req->unit->data;
585 env = java_data->env;
599 env = req->ctx->data;
586 data = req->data;
587
588 nxt_java_Request_close(env, data->jreq);
589
590 (*env)->DeleteGlobalRef(env, data->jresp);
591 (*env)->DeleteGlobalRef(env, data->jreq);
592
593 nxt_unit_request_done(req, NXT_UNIT_OK);
594}
595
600 data = req->data;
601
602 nxt_java_Request_close(env, data->jreq);
603
604 (*env)->DeleteGlobalRef(env, data->jresp);
605 (*env)->DeleteGlobalRef(env, data->jreq);
606
607 nxt_unit_request_done(req, NXT_UNIT_OK);
608}
609
610
611static int
612nxt_java_ready_handler(nxt_unit_ctx_t *ctx)
613{
614 int res;
615 uint32_t i;
616 nxt_java_data_t *java_data;
617 nxt_java_app_conf_t *c;
618
619 /* Worker thread context. */
620 if (!nxt_unit_is_main_ctx(ctx)) {
621 return NXT_UNIT_OK;
622 }
623
624 java_data = ctx->unit->data;
625 c = java_data->conf;
626
627 if (c->threads <= 1) {
628 return NXT_UNIT_OK;
629 }
630
631 for (i = 0; i < c->threads - 1; i++) {
632 res = pthread_create(&nxt_java_threads[i], nxt_java_thread_attr,
633 nxt_java_thread_func, ctx);
634
635 if (nxt_fast_path(res == 0)) {
636 nxt_unit_debug(ctx, "thread #%d created", (int) (i + 1));
637
638 } else {
639 nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)",
640 (int) (i + 1), strerror(res), res);
641
642 return NXT_UNIT_ERROR;
643 }
644 }
645
646 return NXT_UNIT_OK;
647}
648
649
650static void *
651nxt_java_thread_func(void *data)
652{
653 int rc;
654 JavaVM *jvm;
655 JNIEnv *env;
656 nxt_unit_ctx_t *main_ctx, *ctx;
657 nxt_java_data_t *java_data;
658
659 main_ctx = data;
660
661 nxt_unit_debug(main_ctx, "worker thread start");
662
663 java_data = main_ctx->unit->data;
664 jvm = java_data->jvm;
665
666 rc = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
667 if (rc != JNI_OK) {
668 nxt_unit_alert(main_ctx, "failed to attach Java VM: %d", (int) rc);
669 return NULL;
670 }
671
672 nxt_java_setContextClassLoader(env, java_data->cl);
673
674 ctx = nxt_unit_ctx_alloc(main_ctx, env);
675 if (nxt_slow_path(ctx == NULL)) {
676 goto fail;
677 }
678
679 (void) nxt_unit_run(ctx);
680
681 nxt_unit_done(ctx);
682
683fail:
684
685 (*jvm)->DetachCurrentThread(jvm);
686
687 nxt_unit_debug(NULL, "worker thread end");
688
689 return NULL;
690}
691
692
693static int
694nxt_java_init_threads(nxt_java_app_conf_t *c)
695{
696 int res;
697 static pthread_attr_t attr;
698
699 if (c->threads <= 1) {
700 return NXT_UNIT_OK;
701 }
702
703 if (c->thread_stack_size > 0) {
704 res = pthread_attr_init(&attr);
705 if (nxt_slow_path(res != 0)) {
706 nxt_unit_alert(NULL, "thread attr init failed: %s (%d)",
707 strerror(res), res);
708
709 return NXT_UNIT_ERROR;
710 }
711
712 res = pthread_attr_setstacksize(&attr, c->thread_stack_size);
713 if (nxt_slow_path(res != 0)) {
714 nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)",
715 strerror(res), res);
716
717 return NXT_UNIT_ERROR;
718 }
719
720 nxt_java_thread_attr = &attr;
721 }
722
723 nxt_java_threads = nxt_unit_malloc(NULL,
724 sizeof(pthread_t) * (c->threads - 1));
725 if (nxt_slow_path(nxt_java_threads == NULL)) {
726 nxt_unit_alert(NULL, "Failed to allocate thread id array");
727
728 return NXT_UNIT_ERROR;
729 }
730
731 memset(nxt_java_threads, 0, sizeof(pthread_t) * (c->threads - 1));
732
733 return NXT_UNIT_OK;
734}
735
736
737static void
738nxt_java_join_threads(nxt_unit_ctx_t *ctx, nxt_java_app_conf_t *c)
739{
740 int res;
741 uint32_t i;
742
743 if (nxt_java_threads == NULL) {
744 return;
745 }
746
747 for (i = 0; i < c->threads - 1; i++) {
748 if ((uintptr_t) nxt_java_threads[i] == 0) {
749 continue;
750 }
751
752 res = pthread_join(nxt_java_threads[i], NULL);
753
754 if (nxt_fast_path(res == 0)) {
755 nxt_unit_debug(ctx, "thread #%d joined", (int) i);
756
757 } else {
758 nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)",
759 (int) i, strerror(res), res);
760 }
761 }
762
763 nxt_unit_free(ctx, nxt_java_threads);
764}
765
766