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;
}
Beispiel #2
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;
}