📄 nbio.c
字号:
THROW_EXCEPTION(env, "java/io/IOException", strerror(errno)); return; }#ifdef USE_BTREE state->tree = btree_newnode();#else for (i = 0; i < MAX_FDS; i++) { state->selitems[i] = (jobject)NULL; }#endif DEBUG(fprintf(stderr,"SelectSetDevPollImpl.init opened /dev/poll, fd %d\n", state->devpoll_fd)); state->retevents = (struct pollfd *)malloc(max_retevents * sizeof(struct pollfd)); if (state->retevents == NULL) { THROW_EXCEPTION(env, "java/lang/OutOfMemoryError", "Cannot allocate state->retevents"); return; } return;}JNIEXPORT void JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_register (JNIEnv * env, jobject this, jobject selitemobj) { devpoll_impl_state *state; jclass cls, cls2; jfieldID fid, fid2, fid_events; jobject fdobj; short events, realevents; struct pollfd pfd; void *data; jobject selitem; DEBUG(fprintf(stderr,"SelectSetDevPollImpl.register called\n")); // Get state cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "native_state", "J"); state = (devpoll_impl_state *)((*env)->GetLongField(env, this, fid)); DEBUG(fprintf(stderr,"SelectSetDevPollImpl.register got state, fd %d\n", state->devpoll_fd)); // Get class and field IDs cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem"); fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); fid_events = (*env)->GetFieldID(env, cls, "events", "S"); cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor"); fid2 = (*env)->GetFieldID(env, cls2, "fd", "I"); // Get fd fdobj = (*env)->GetObjectField(env, selitemobj, fid); pfd.fd = (*env)->GetIntField(env, fdobj, fid2); // Get events events = (*env)->GetShortField(env, selitemobj, fid_events); realevents = 0; if (events != 0) { if (events & SELECTABLE_READ_READY) { realevents |= (POLLIN | POLLPRI); } if (events & SELECTABLE_WRITE_READY) { realevents |= POLLOUT; } pfd.events = realevents; } DEBUG(fprintf(stderr,"SelectSetDevPollImpl.register adding (fd=%d,events=0x%x)\n", pfd.fd, pfd.events)); // Register if (write(state->devpoll_fd, &pfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) { THROW_EXCEPTION(env, "java/io/IOException", strerror(errno)); return; }#ifdef USE_BTREE data = btree_search(state->tree, pfd.fd); if (data == NULL) { // Insert into B-tree state->tree = btree_insert(state->tree, pfd.fd, (*env)->NewGlobalRef(env, selitemobj)); }#else if ((pfd.fd < 0) || (pfd.fd >= MAX_FDS)) { fprintf(stderr,"Warning: pfd.fd is %d, out of range 0...%d.\n",MAX_FDS); fprintf(stderr," You need to recompile nbio.c with a larger MAX_FDS value.\n"); return; } selitem = state->selitems[pfd.fd]; if (selitem == (jobject)NULL) { state->selitems[pfd.fd] = (*env)->NewGlobalRef(env, selitemobj); }#endif return;}JNIEXPORT void JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_deregister (JNIEnv * env, jobject this, jobject selitemobj) { devpoll_impl_state *state; jclass cls, cls2; jfieldID fid, fid2; jobject fdobj, selitem; struct pollfd pfd; DEBUG(fprintf(stderr,"SelectSetDevPollImpl.deregister called\n")); // Get state cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "native_state", "J"); state = (devpoll_impl_state *)((*env)->GetLongField(env, this, fid)); DEBUG(fprintf(stderr,"SelectSetDevPollImpl.deregister got state, fd %d\n", state->devpoll_fd)); // Get class and field IDs cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem"); fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor"); fid2 = (*env)->GetFieldID(env, cls2, "fd", "I"); // Get fd fdobj = (*env)->GetObjectField(env, selitemobj, fid); pfd.fd = (*env)->GetIntField(env, fdobj, fid2); pfd.events = POLLREMOVE; DEBUG(fprintf(stderr,"SelectSetDevPollImpl.deregister removing (fd=%d,events=0x%x)\n", pfd.fd, pfd.events)); // Deeegister if (write(state->devpoll_fd, &pfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) { THROW_EXCEPTION(env, "java/io/IOException", strerror(errno)); return; }#ifdef USE_BTREE // XXX NEED TO DELETE NODE FROM BTREE#else if ((pfd.fd < 0) || (pfd.fd >= MAX_FDS)) { fprintf(stderr,"Warning: pfd.fd is %d, out of range 0...%d.\n",MAX_FDS); fprintf(stderr," You need to recompile nbio.c with a larger MAX_FDS value.\n"); return; } selitem = state->selitems[pfd.fd]; if (selitem != (jobject)NULL) { // selitem can be NULL if deregister is not synchronized // (although it should be) (*env)->DeleteGlobalRef(env, selitem); state->selitems[pfd.fd] = (jobject)NULL; }#endif return;}JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_doSelect (JNIEnv * env, jobject this, jint timeout) { devpoll_impl_state *state; jclass cls, cls2; jfieldID fid, fid2, fid_fd, fid_revents; jobject selitemobj, fdobj; jobjectArray itemarr, retitemarr; struct dvpoll dopoll; int itemarrlen, ret, i, j, fd, retfd, count; void *data; struct pollfd *pfd; short realevents; DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect called\n")); // Get state cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "native_state", "J"); state = (devpoll_impl_state *)((*env)->GetLongField(env, this, fid)); DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect got state, fd=%d\n",state->devpoll_fd)); // Get itemarray cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "itemarr", "[Lninja2/core/io_core/nbio/SelectItem;"); itemarr = (jobjectArray)((*env)->GetObjectField(env, this, fid)); if (itemarr == NULL) { // This can happen if we have an empty SelectSet return 0; } itemarrlen = (*env)->GetArrayLength(env, itemarr); if (itemarrlen <= 0) { THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "SelectItem[] array has size <= 0"); return 0; } DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect got itemarr, len %d\n",itemarrlen)); // Get retitemarr fid = (*env)->GetFieldID(env, cls, "retevents", "[Lninja2/core/io_core/nbio/SelectItem;"); retitemarr = (jobjectArray)((*env)->GetObjectField(env, this, fid)); DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect got retitemarr, length %d\n", ((*env)->GetArrayLength(env, retitemarr)))); // Get fid_revents cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem"); fid_revents = (*env)->GetFieldID(env, cls, "revents", "S"); fid_fd = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); // Get fid2 cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor"); fid2 = (*env)->GetFieldID(env, cls2, "fd", "I"); // Fill in dopoll dopoll.dp_timeout = timeout; dopoll.dp_nfds = state->max_retevents; dopoll.dp_fds = state->retevents; DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect doing DP_POLL\n")); ret = ioctl(state->devpoll_fd, DP_POLL, &dopoll); DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect DP_POLL returned %d\n", ret)); if (ret == 0) { return 0; } if (ret < 0) { int myerrno = errno; // Don't throw an exception if we were interrupted if (myerrno != EINTR) { THROW_EXCEPTION(env, "java/io/IOException", strerror(myerrno)); } return 0; } count = 0; for (i = 0; i < ret; i++) { pfd = &(state->retevents[i]); DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect ret[%d] fd %d revents 0x%x\n", i, pfd->fd, pfd->revents)); retfd = pfd->fd;#ifdef USE_BTREE data = btree_search(state->tree, retfd); if (data == NULL) { THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "retfd not found in registered set"); return 0; } selitemobj = (jobject)data;#else if ((retfd < 0) || (retfd >= MAX_FDS)) { fprintf(stderr,"Warning: retfd is %d, out of range 0...%d.\n",MAX_FDS); fprintf(stderr," You need to recompile nbio.c with a larger MAX_FDS value.\n"); THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "retfd out of range"); return 0; } selitemobj = state->selitems[retfd]; if (selitemobj == (jobject)NULL) { THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "retfd not found in registered set"); return 0; }#endif DEBUG(fprintf(stderr,"Got selitemobj 0x%lx\n", (unsigned long)selitemobj)); realevents = 0; if (pfd->revents & (POLLIN | POLLPRI)) { realevents |= SELECTABLE_READ_READY; } if (pfd->revents & POLLOUT) { realevents |= SELECTABLE_WRITE_READY; } if (pfd->revents & (POLLERR | POLLHUP | POLLNVAL)) { realevents |= SELECTABLE_SELECT_ERROR; } (*env)->SetShortField(env, selitemobj, fid_revents, realevents); DEBUG(fprintf(stderr,"Set revents\n")); (*env)->SetObjectArrayElement(env, retitemarr, count, selitemobj); DEBUG(fprintf(stderr,"Set retitemarr[%d]\n", count)); count++; } return ret;}#endif /* HAS_DEVPOLL *//* SelectSetPollImpl *******************************************************/JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_SelectSetPollImpl_doSelect(JNIEnv *env, jobject this, jint timeout) { jclass cls, cls2; jfieldID fid, fid2, fid_events, fid_revents; jobjectArray itemarr; jobject selitemobj, fdobj; struct pollfd *ufds; int *ufds_map; int itemarrlen; int i, n; int ret; int num_ufds = 0; short events, realevents; DEBUG(fprintf(stderr,"NBIO: doSelect called\n")); cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "itemarr", "[Lninja2/core/io_core/nbio/SelectItem;"); itemarr = (jobjectArray)(*env)->GetObjectField(env, this, fid); if (itemarr == NULL) { // This can happen if we have an empty SelectSet return 0; } DEBUG(fprintf(stderr,"NBIO: doSelect: got itemarr\n")); itemarrlen = (*env)->GetArrayLength(env, itemarr); if (itemarrlen <= 0) { THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "SelectItem[] array has size <= 0"); return 0; } DEBUG(fprintf(stderr,"NBIO: doSelect: itemarrlen is %d\n", itemarrlen)); cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem"); DEBUG(fprintf(stderr,"NBIO: doSelect: got SelectItem class\n")); fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); fid_events = (*env)->GetFieldID(env, cls, "events", "S"); fid_revents = (*env)->GetFieldID(env, cls, "revents", "S"); cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor"); fid2 = (*env)->GetFieldID(env, cls2, "fd", "I"); // Only allocate a ufd if events != 0 for (i = 0; i < itemarrlen; i++) { selitemobj = (*env)->GetObjectArrayElement(env, itemarr, i); if (selitemobj == NULL) { fprintf(stderr,"NBIO: WARNING: itemarr[%d] is NULL! (itemarrlen=%d)\n", i, itemarrlen); THROW_EXCEPTION(env, "java/lang/NullPointerException", "SelectItem element is null"); return 0; } events = (*env)->GetShortField(env, selitemobj, fid_events); if (events != 0) num_ufds++; } if (num_ufds == 0) return 0; ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_ufds); if (ufds == NULL) { THROW_EXCEPTION(env, "java/lang/OutOfMemoryError", "cannot allocate pollfd array"); return 0; } DEBUG(fprintf(stderr,"NBIO: doSelect: allocated %d ufds\n", num_ufds)); ufds_map = (int *)malloc(sizeof(int) * num_ufds); if (ufds_map == NULL) { THROW_EXCEPTION(env, "java/lang/OutOfMemoryError", "cannot allocate ufds_map"); free(ufds); return 0; } n = 0; for (i = 0; i < itemarrlen; i++) { selitemobj = (*env)->GetObjectArrayElement(env, itemarr, i); if (selitemobj == NULL) { THROW_EXCEPTION(env, "java/lang/NullPointerException", "SelectItem element is null"); free(ufds); free(ufds_map); return 0; } realevents = 0; events = (*env)->GetShortField(env, selitemobj, fid_events); if (events != 0) { if (events & SELECTABLE_READ_READY) { realevents |= (POLLIN | POLLPRI); } if (events & SELECTABLE_WRITE_READY) { realevents |= POLLOUT; } ufds[n].events = realevents; DEBUG(fprintf(stderr,"NBIO: doSelect: ufds[%d].events is 0x%x\n", n, ufds[n].events)); ufds[n].revents = 0; fdobj = (*env)->GetObjectField(env, selitemobj, fid); ufds[n].fd = (*env)->GetIntField(env, fdobj, fid2); DEBUG(fprintf(stderr,"NBIO: doSelect: ufds[%d].fd is %d\n", n, ufds[n].fd)); ufds_map[n] = i; n++; } } /* XXX MDW: poll() is interruptible. Under Linux, a signal (say, from * the GC) might interrupt poll. For now I don't deal with this * properly - I just go ahead and return early from doSelect() if the * call was interrupted. */ DEBUG(fprintf(stderr,"NBIO: Doing poll, %d fds, timeout %d\n", n, timeout)); ret = nbio_real_poll(ufds, num_ufds, timeout); DEBUG(fprintf(stderr,"NBIO: doSelect: did poll, timeout %d, ret is %d, errno is %d\n", timeout, ret, errno)); if (ret == 0) { free(ufds); free(ufds_map); return 0; } if (ret < 0) { int myerrno = errno; // Don't throw an exception if we were interrupted if (myerrno != EINTR) { THROW_EXCEPTION(env, "java/io/IOException", strerror(myerrno)); } free(ufds); free(ufds_map); return 0; } for (n = 0; n < num_ufds; n++) { DEBUG(fprintf(stderr,"NBIO: doSelect: ufds[%d].revents is 0x%x\n", n, ufds[n].revents)); if (ufds[n].revents != 0) { i = ufds_map[n]; selitemobj = (*env)->GetObjectArrayElement(env, itemarr, i); if (selitemobj == NULL) { THROW_EXCEPTION(env, "java/lang/NullPointerException", "SelectItem element is null"); free(ufds); free(ufds_map); return 0; } realevents = 0; if (ufds[n].revents & (POLLIN | POLLPRI)) { realevents |= SELECTABLE_READ_READY; } if (ufds[n].revents & POLLOUT) { realevents |= SELECTABLE_WRITE_READY; } if (ufds[n].revents & (POLLERR | POLLHUP | POLLNVAL)) { realevents |= SELECTABLE_SELECT_ERROR; } DEBUG(fprintf(stderr,"NBIO: doSelect: setting itemarr[%d].revents to 0x%x\n", i, realevents)); (*env)->SetShortField(env, selitemobj, fid_revents, realevents); } } free(ufds); free(ufds_map); DEBUG(fprintf(stderr,"NBIO: doSelect: returning %d\n", ret)); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -