int dfs_d(const igraph_t *graph, igraph_integer_t root, igraph_neimode_t mode, igraph_bool_t unreachable, igraph_vector_t *order, igraph_vector_t *order_out, igraph_vector_t *father, igraph_vector_t *dist, igraph_dfshandler_t *in_callback, igraph_dfshandler_t *out_callback, void *extra) { long int no_of_nodes=igraph_vcount(graph); igraph_lazy_adjlist_t adjlist; igraph_stack_t stack; igraph_vector_char_t added; igraph_vector_long_t nptr; long int actroot; long int act_rank=0; long int rank_out=0; long int act_dist=0; if (root < 0 || root >= no_of_nodes) { IGRAPH_ERROR("Invalid root vertex for DFS", IGRAPH_EINVAL); } if (mode != IGRAPH_OUT && mode != IGRAPH_IN && mode != IGRAPH_ALL) { IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE); } if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; } IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_char_destroy, &added); IGRAPH_CHECK(igraph_stack_init(&stack, 100)); IGRAPH_FINALLY(igraph_stack_destroy, &stack); IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, mode, /*simplify=*/ 0)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist); IGRAPH_CHECK(igraph_vector_long_init(&nptr, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_long_destroy, &nptr); # define FREE_ALL() do { \ igraph_vector_long_destroy(&nptr); \ igraph_lazy_adjlist_destroy(&adjlist); \ igraph_stack_destroy(&stack); \ igraph_vector_char_destroy(&added); \ IGRAPH_FINALLY_CLEAN(4); } while (0) /* Resize result vectors and fill them with IGRAPH_NAN */ # define VINIT(v) if (v) { \ igraph_vector_resize(v, no_of_nodes); \ igraph_vector_fill(v, IGRAPH_NAN); } VINIT(order); VINIT(order_out); VINIT(father); VINIT(dist); # undef VINIT IGRAPH_CHECK(igraph_stack_push(&stack, root)); VECTOR(added)[(long int)root] = 1; if (father) { VECTOR(*father)[(long int)root] = -1; } if (order) { VECTOR(*order)[act_rank++] = root; } if (dist) { VECTOR(*dist)[(long int)root] = 0; } if (in_callback) { igraph_bool_t terminate=in_callback(graph, root, 0, extra); if (terminate) { FREE_ALL(); return 0; } } for (actroot=0; actroot<no_of_nodes; actroot++) { /* 'root' first, then all other vertices */ if (igraph_stack_empty(&stack)) { if (!unreachable) { break; } if (VECTOR(added)[actroot]) { continue; } IGRAPH_CHECK(igraph_stack_push(&stack, actroot)); VECTOR(added)[actroot] = 1; if (father) { VECTOR(*father)[actroot] = -1; } if (order) { VECTOR(*order)[act_rank++] = actroot; } if (dist) { VECTOR(*dist)[actroot] = 0; } if (in_callback) { igraph_bool_t terminate=in_callback(graph, (igraph_integer_t) actroot, 0, extra); if (terminate) { FREE_ALL(); return 0; } } } while (!igraph_stack_empty(&stack)) { long int actvect=(long int) igraph_stack_top(&stack); igraph_vector_t *neis=igraph_lazy_adjlist_get(&adjlist, (igraph_integer_t) actvect); long int n=igraph_vector_size(neis); long int *ptr=igraph_vector_long_e_ptr(&nptr, actvect); igraph_vector_shuffle(neis); igraph_vector_print(neis); /* Search for a neighbor that was not yet visited */ igraph_bool_t any=0; long int nei; while (!any && (*ptr) <n) { nei=(long int) VECTOR(*neis)[(*ptr)]; any=!VECTOR(added)[nei]; (*ptr) ++; } if (any) { /* There is such a neighbor, add it */ IGRAPH_CHECK(igraph_stack_push(&stack, nei)); VECTOR(added)[nei] = 1; if (father) { VECTOR(*father)[ nei ] = actvect; } if (order) { VECTOR(*order)[act_rank++] = nei; } act_dist++; if (dist) { VECTOR(*dist)[nei] = act_dist; } if (in_callback) { igraph_bool_t terminate=in_callback(graph, (igraph_integer_t) nei, (igraph_integer_t) act_dist, extra); if (terminate) { FREE_ALL(); return 0; } } } else { /* There is no such neighbor, finished with the subtree */ igraph_stack_pop(&stack); if (order_out) { VECTOR(*order_out)[rank_out++] = actvect; } act_dist--; if (out_callback) { igraph_bool_t terminate=out_callback(graph, (igraph_integer_t) actvect, (igraph_integer_t) act_dist, extra); if (terminate) { FREE_ALL(); return 0; } } } } } FREE_ALL(); # undef FREE_ALL return 0; }
int main(int argc, char ** argv) { setlocale(LC_ALL, ""); setlocale(LC_CTYPE, "C-UTF-8"); initscr(); cbreak(); //keypad(stdscr, TRUE); refresh(); gui_t gui; core_t core; gui.mainwindow = create_window(LINES, COLS, 0, 0); gui.content = create_window(LINES-3, COLS-16-2, 1, 1); gui.user_list = create_window(LINES-3, 16, 1, COLS-16-1); strncpy(core.room, "(status)", 9); core.room[8] = '\0'; core.cur_line = 0; core.cur_user_pos = 0; init_colors(); draw_gui(gui.mainwindow, &core); core.cursor_x = 0; core.cursor_y = LINES-1; //core.serverkey = 0; char /*cur_time[9], userlist_buffer[1024],*/ buffer[1024]; time_t now; //strftime(cur_time, 9, "%H:%M:%S", localtime(&now)); //cur_time[8] = '\0'; //char buf[512]; add_info(&core, gui.content, "OS-Chat wystartowal", &now); add_info(&core, gui.content, "wpisz /help aby uzyskac pomoc", &now); //add_msg(&core, gui.content, "hun7er", "czesc", &now, 1); //add_msg(&core, gui.content, "hun7er", "]:>", &now, 1); //add_msg(&core, gui.content, "bot", "yo", &now, 0); //add_user_to_list(&core, "hun7er"); //add_user_to_list(&core, "testowy"); //add_content_line(&core, gui.content, 0, "-!- uzytkownik mescam dolaczyl do #global"); scrollok(gui.content, 1); refresh(); int int_queue_in, int_queue_out, ext_queue; // internal queue, external queue struct mq_attr attr; attr.mq_msgsize = MAX_MSG_SIZE; attr.mq_maxmsg = 10; //char buf[128]; int e1 = 1, e2 = 1; do { sprintf(res.q_in, "/internal_in%d", e1); res.int_in_fd = mq_open(res.q_in, O_RDWR|O_CREAT|O_EXCL, 0777, &attr); e1++; } while(res.int_in_fd == -1); do { sprintf(res.q_out, "/internal_out%d", e2); res.int_out_fd = mq_open(res.q_out, O_RDWR|O_CREAT|O_EXCL, 0777, &attr); e2++; } while(res.int_out_fd == -1); int_queue_in = res.int_in_fd; int_queue_out = res.int_out_fd; if(int_queue_in == -1 || int_queue_out == -1) { endwin(); printf("max msg size: %lu\n", MAX_MSG_SIZE); perror("Nie mozna utworzyc wewnetrznych kolejek komunikatow"); printf("Numer bledu: %d\n", errno); return -1; } //sprintf(buf, "Kolejki: %s (in), %s (out)", res.q_in, res.q_out); //add_info(&core, gui.content, buf, &now); now = time(NULL); //add_private(&core, gui.content, "hun7er", "psssst. Kolego, masz na ziarno?", &now); int ret = pipe(server_key); if(ret == -1) { add_content_line(&core, gui.content, 0, "-!- Blad: nie mozna utworzyc potoku"); } ret = pipe(room); if(ret == -1) { add_info(&core, gui.content, "BLAD: nie mozna utworzyc potoku", &now); } fcntl(server_key[0], F_SETFL, O_NDELAY); fcntl(server_key[1], F_SETFL, O_NDELAY); fcntl(room[0], F_SETFL, O_NDELAY); fcntl(room[1], F_SETFL, O_NDELAY); // internal: obrobione dane do wyswietlenia // external: "surowe" dane do obrobienia przez forki ext_queue = DEFAULT_QUEUE_KEY; get_key(&ext_queue); core.mykey = res.queue_key = ext_queue; core.serverkey = 0; //sprintf(buf, "DEBUG moj klucz kolejki: %d", ext_queue); //add_content_line(&core, gui.content, 0, buf); signal(SIGINT, SIG_DFL); //int child1 = 0, child2 = 0; if(!(res.child_id1 = fork())) { signal(SIGINT, SIG_DFL); int queue_in = mq_open(res.q_in, O_RDWR), skey = 0, queue_out = mq_open(res.q_out, O_RDWR); if(queue_in == -1) { perror("Nie mozna otworzyc wewnetrznej kolejki komunikatow (in)"); return -1; } compact_message cmg; // m.in. do odpowiadania na HEARTBEAT standard_message smg; // m.in. wiadomosci prywatne/kanalowe user_list usr; message msg; // odbieranie struct timespec tim; tim.tv_sec = 0; tim.tv_nsec = 1000; //close(server_key[1]); char roomname[512]; close(room[1]); while(1) { int mid = msgget(ext_queue, 0777); char buf[16]; if(mid == -1) { // wyslij komunikat do GUI że się posypała kolejka // spróbuj zaalokować nową } else { if(receive(ext_queue, &cmg, /*member_size(compact_message, content)*/sizeof(compact_message), MSG_HEARTBEAT) != -1) { msg.type = M_HEARTBEAT; msg.source = cmg.content.value; int rcpt = msgget(cmg.content.value, 0777); cmg.content.value = core.mykey; msgsnd(rcpt, &cmg, sizeof(compact_message), IPC_NOWAIT); //mq_send(queue_out, (char*)&msg, MAX_MSG_SIZE, M_HEARTBEAT); mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_HEARTBEAT); } if(receive(ext_queue, &cmg, /*member_size(compact_message, content)*/sizeof(compact_message), MSG_JOIN) != -1) { int ret = 0; do { ret = read(room[0], &roomname, 512); } while(ret == 0); msg.type = M_JOIN; strcpy(msg.content.room, roomname); mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_JOIN); } if(receive(ext_queue, &cmg, /*member_size(compact_message, content)*/sizeof(compact_message), MSG_REGISTER) != -1) { int /*mid = -1, */len = -1, val; switch(cmg.content.value) { case 0: msg.type = M_REGISTER; strcpy(msg.content.name, cmg.content.sender); mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_REGISTER); //printf("ret = %d\n", ret); msg.type = M_JOIN; strcpy(msg.content.room, GLOBAL_ROOM_NAME); mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_JOIN); msg.type = M_USERLIST; msg.source = core.mykey; len = 0; do { len = read(server_key[0], &buf, 16); } while (len == 0); write(server_key[1], &buf, 16); val = atoi(buf); if(skey != val) skey = val; if(skey != 0) { msg.dest = skey; mq_send(queue_out, (char*)&msg, MAX_MSG_SIZE, M_USERLIST); } //msgsnd(mid, &cmg, /*member_size(compact_message, content)*/sizeof(compact_message), IPC_NOWAIT); break; case -1: // nick istnieje msg.type = M_ERROR; strcpy(msg.content.message, "Blad rejestracji: nick uzywany"); mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_ERROR); break; case -2: // serwer pelen msg.type = M_ERROR; strcpy(msg.content.message, "Blad rejestracji: serwer pelen"); mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_ERROR); break; } } if(receive(ext_queue, &smg, /*member_size(standard_message, content)*/sizeof(standard_message), MSG_ROOM) != -1) { msg.type = M_MESSAGE; strcpy(msg.content.message, smg.content.message); strcpy(msg.content.name, smg.content.sender); msg.content.date = smg.content.send_date; mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_MESSAGE); } if(receive(ext_queue, &smg, /*member_size(standard_message, content)*/sizeof(standard_message), MSG_PRIVATE) != -1) { msg.type = M_PRIVATE; strcpy(msg.content.message, smg.content.message); strcpy(msg.content.name, smg.content.sender); mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_PRIVATE); } if(receive(ext_queue, &usr, /*member_size(user_list, content)*/sizeof(user_list), MSG_LIST) != -1) { msg.type = M_USERLIST; int i = 0; for(; i < MAX_USER_LIST_LENGTH; i++) { strcpy(msg.content.list[i], usr.content.list[i]); } mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_USERLIST); } if(receive(ext_queue, &cmg, sizeof(compact_message), MSG_LEAVE) != -1) { msg.type = M_LEAVE; mq_send(queue_in, (char*)&msg, MAX_MSG_SIZE, M_LEAVE); } } nanosleep(&tim, NULL); } // tu będzie odbieranie msgrcv() komunikatów zwykłych (najlepiej w jakiejś zewnętrznej funkcji) + wysyłanie danych do kolejki wewnętrznej w razie potrzeby //} } else { // interfejs uzytkownika if(!(res.child_id2 = fork())) { signal(SIGINT, SIG_DFL); struct pollfd ufds; int queue_out = mq_open(res.q_out, O_RDWR); if(queue_out == -1) { perror("Nie mozna otworzyc wewnetrznej kolejki komunikatow (out)"); return -1; } ufds.fd = queue_out; ufds.events = POLLIN; while(1) { switch(poll(&ufds, 1, 10)) { default: if(ufds.revents && POLLIN) // tu jakis callback do wysyłania np. get_and_send() w out_callback out_callback(queue_out); //key_callback(&gui, &core, buffer); } } // wysylanie } else { if(!(res.child_id3 = fork())) { int queue_out = mq_open(res.q_out, O_RDWR); if(queue_out == -1) { endwin(); perror("Nie mozna otworzyc wewnetrznej kolejki"); kill(getppid(), SIGKILL); exit(-1); } struct timespec tim; tim.tv_sec = 2; tim.tv_nsec = 0; //char buf[512]; int skey = 0; //close(server_key[1]); while(1) { //sprintf(buf, "[DEBUG] core.serverkey: %d", core.serverkey); //add_content_line(&core, gui.content, 1, buf); char buf[16]; read(server_key[0], &buf, 16); int val = atoi(buf); if(val != skey && skey > 0) skey = val; if(skey > 0) { endwin(); printf("skey: %d\n", skey); exit(-1); message msg; msg.type = M_USERLIST; msg.source = core.mykey; msg.dest = skey; mq_send(queue_out, (char*)&msg, MAX_MSG_SIZE, M_USERLIST); sprintf(buf, "%d", skey); write(server_key[1], &buf, 16); //add_content_line(&core, gui.content, 1, "[DEBUG] Trying to reach server..."); } nanosleep(&tim, NULL); } } else { signal(SIGINT, sighandler); int /*i = 0, */ufds_size = 2; struct pollfd ufds[2]; ufds[0].fd = STDIN_FILENO; ufds[0].events = POLLIN; ufds[1].fd = int_queue_in; ufds[1].events = POLLIN; while(1) { //mvwprintw(gui.user_list, 0, 0, "%s", userlist_buffer); /*for(i = 0; i < LINES; i++) { // naprawic zeby tylko wyswietlalo gdy jest jakas zmiana mvwprintw(gui.user_list, i, 0, "%s", core.userlist[i]); } wrefresh(gui.user_list);*/ wmove(gui.mainwindow, core.cursor_y, (strcmp(core.room, "(status)") == 0 ? strlen(core.room)+3+core.cursor_x : strlen(core.room)+4+core.cursor_x)); wrefresh(gui.mainwindow); //refresh(); switch(poll(ufds, ufds_size, 10)) { case -1: // np. resize terminala redraw(&gui, &core); //refresh(); break; default: if(ufds[0].revents && POLLIN) key_callback(&gui, &core, buffer, int_queue_out); if(ufds[1].revents && POLLIN) in_callback(&gui, &core, int_queue_in); } } // while(1) } } // else } // else forka return 0; }