Beispiel #1
0
void
put_in_output_queue(char *stuff)
{
  
  output_queue = append_and_free_old(output_queue, stuff); 
  DPRINTF3(DEBUG_TERMIO,"put %d bytes in output queue (which now has %d bytes): %s",
	   (int) strlen(stuff), (int) strlen(output_queue), mangle_string_for_debug_log(stuff, 20));

}
Beispiel #2
0
char *pass_through_filter(int tag, const char *buffer) {
    char *filtered;
    DPRINTF3(DEBUG_FILTERING, "to filter (%s, %d bytes) %s", tag2description(tag), (int) strlen(buffer), mangle_string_for_debug_log(buffer, MANGLE_LENGTH));
    if (filter_pid ==0)
        return mysavestring(buffer);
    write_to_filter((expected_tag = tag), buffer);
    filtered = read_from_filter(tag);
    DPRINTF2(DEBUG_FILTERING, "from filter (%d bytes) %s", (int) strlen(filtered), mangle_string_for_debug_log(filtered, MANGLE_LENGTH));
    return filtered;
}
Beispiel #3
0
Datei: semact.c Projekt: hh/emacs
void deleteSymDef(void *p) {
	S_symbol 		*pp;
	S_javaStat		*scp;
	pp = (S_symbol *) p;
	DPRINTF3("deleting %s %s\n", pp->name, pp->linkName);
	if (symTabDelete(s_javaStat->locals,pp)) return;
	if (symTabDelete(s_symTab,pp)==0) {
		assert(s_opt.taskRegime);
		if (s_opt.taskRegime != RegimeEditServer) {
			error(ERR_INTERNAL,"symbol on deletion not found");
		}
	}
}
Beispiel #4
0
void
mysignal(int sig, sighandler_type handler) {

#ifdef HAVE_SIGACTION
    struct sigaction action;
    DPRINTF3(DEBUG_SIGNALS,"Setting handler for signal %d (%s) to <0x%lx>", sig, signal_name(sig), (long) handler);
    action.sa_handler = handler;
    sigfillset(&action.sa_mask); /* don't bother making our signal handlers re-entrant (they aren't) */
    action.sa_flags = (sig == SIGCHLD ? SA_NOCLDSTOP : 0); /* no SA_RESTART */
    if (sigaction(sig, &action, NULL) != 0)
# else /* rlwrap running in Ye Olde Computer Museum?? */
    if (signal(sig, handler) == SIG_ERR)
# endif
        if(handler != SIG_DFL) /* allow e.g. KILL to be set to its default */
            myerror(FATAL|USE_ERRNO, "Failed setting handler for signal %d (%s)", sig, signal_name(sig));
}
Beispiel #5
0
void
flush_output_queue()
{
  int nwritten, queuelen, how_much;
  char *old_queue = output_queue;
  char *nl;

  if (!output_queue)
    return;
  queuelen = strlen(output_queue);
  nl       = strchr(output_queue, '\n');
  how_much = min(BUFFSIZE, nl ? 1+ nl - output_queue : queuelen); /* never write more than one line, and never more than BUFFSIZE in one go */
  nwritten = write(master_pty_fd, output_queue, how_much);

  assert(nwritten <= strlen(output_queue));
  if (debug) {
    char scratch = output_queue[nwritten];
    output_queue[nwritten] = '\0'; /* temporarily replace the last written byte + 1 by a '\0' */
    DPRINTF3(DEBUG_TERMIO,"flushed %d of %d bytes from output queue to pty: %s",
	     nwritten, queuelen, mangle_string_for_debug_log(output_queue, MANGLE_LENGTH));
    output_queue[nwritten] =  scratch;
  }	
  
  if (nwritten < 0) {
    switch (nwritten) {
    case EINTR:
    case EAGAIN:
      return;
    default:
      myerror("write to master pty failed");
    }
  }

  if (!output_queue[nwritten]) /* nothing left in queue */
    output_queue = NULL;
  else
    output_queue = mysavestring(output_queue + nwritten);	/* this much is left to be written */

  free(old_queue);
}
Beispiel #6
0
static void
pass_on_signal(int signo)
{
    int ret, saved_errno = errno, pass_it_on = TRUE;
    DEBUG_RANDOM_SLEEP;
    zero_select_timeout();
#ifdef DEBUG
    log_named_signal(signo);
#endif

    if(pass_on_sigINT_as_sigTERM && signo == SIGINT)
        signo=SIGTERM;

    switch (signo) {
    case SIGWINCH: /* non-POSIX, but present on most systems */
        /* Make slave pty's winsize equal to that of STDIN. Pass the signal on *only if*
           winsize has changed. This is particularly important because we have the slave pty
           still open - when we pass on the signal the child will probably do a TIOCSWINSZ ioctl()
           on the slave pty  - causing us (the parent) to get a SIGWINCH again, thus getting stuck in a loop */
        pass_it_on = adapt_tty_winsize(STDIN_FILENO, master_pty_fd);
        break;
    case SIGTERM:
        sigterm_received = TRUE;
        break;
    default:
        break;
    }
    if (!command_pid)
        pass_it_on = FALSE;         /* no child (yet) to pass it on to */

    if (pass_it_on) {             /* we resend the signal to the process *group* of the child */
        ret = kill( -command_pid, signo);
        DPRINTF3(DEBUG_SIGNALS, "kill(%d,%s) = %d", -command_pid, signal_name(signo), ret);
        we_just_got_a_signal_or_EOF = TRUE; /* signal to main loop that next command output should leave the prompt alone */
    }
    errno = saved_errno;

}
Beispiel #7
0
static int
handle_hotkey2(int UNUSED(count), int hotkey, int ignore_history)
{
  char *prefix, *postfix, *history,  *histpos_as_string, *executing_keyseq;
  char *new_prefix, *new_postfix, *new_history, *new_histpos_as_string, *message; 
  char *filter_food, *filtered, **fragments,  *new_rl_line_buffer;
  int length, new_histpos;
  unsigned long int hash;

  static const unsigned int MAX_HISTPOS_DIGITS = 6; /* one million history items should suffice */

  
#ifdef HAVE_RL_EXECUTING_KEYSEQ /* i.e. if readline version is >= 6.3 */
  executing_keyseq = mysavestring(rl_executing_keyseq);
#else
  executing_keyseq = mysavestring("?");
  *executing_keyseq = hotkey; /* The filter will only get the *last* byte of the key sequence that triggered rl_handle_hotkey */ 
#endif

    
  DPRINTF3(DEBUG_READLINE, "hotkey press (ignore_history == %d): %x (%s)", ignore_history, hotkey, mangle_string_for_debug_log(executing_keyseq, MANGLE_LENGTH));

  if (hotkey == '\t') /* this would go horribly wrong with all the splitting on '\t' going on.... @@@ or pass key as a string e.g. "009" */
    myerror(FATAL | NOERRNO, "Sorry, you cannot use TAB as an hotkey in rlwrap");


  prefix = mysavestring(rl_line_buffer);
  prefix[rl_point] = '\0';                                     /* chop off just before cursor */
  postfix = mysavestring(rl_line_buffer + rl_point);

  if (ignore_history) {
    histpos_as_string = mysavestring("0");
    history = mysavestring("");
  } else {
    histpos_as_string = as_string(where_history());
    assert(strlen(histpos_as_string) <= MAX_HISTPOS_DIGITS);
    history = entire_history_as_one_string();
    hash = hash_multiple(2, history, histpos_as_string);
  }     

  /* filter_food = key + tab + prefix + tab + postfix + tab + history + tab + histpos  + '\0' */
  length = strlen(rl_line_buffer) + strlen(history) + MAX_HISTPOS_DIGITS + 5; 
  filter_food = mymalloc(length);   
  sprintf(filter_food, "%s\t%s\t%s\t%s\t%s", executing_keyseq, prefix, postfix, history, histpos_as_string); /* this is the format that the filter expects */

  /* let the filter filter ...! */
  filtered= pass_through_filter(TAG_HOTKEY, filter_food);
  
  /* OK, we now have to read back everything. There should be exactly 5 TAB-separated components*/
  fragments = split_on_single_char(filtered, '\t', 5);
  message               = fragments[0];
  new_prefix            = fragments[1];
  new_postfix           = fragments[2];
  new_history           = fragments[3];
  new_histpos_as_string = fragments[4];

  if (!ignore_history && hash_multiple(2, new_history, new_histpos_as_string) != hash) { /* history has been rewritten */
    char **linep, **history_lines = split_on_single_char(new_history, '\n', 0);
    DPRINTF3(DEBUG_READLINE, "hash=%lx, new_history is %d bytes long, histpos <%s>", hash, (int) strlen(new_history), new_histpos_as_string);
    clear_history();
    for (linep = history_lines; *linep; linep++) 
      add_history(*linep);
    new_histpos = my_atoi(new_histpos_as_string);
    history_set_pos(new_histpos);
    free_splitlist(history_lines);
  }
  new_rl_line_buffer = add2strings(new_prefix, new_postfix);

  if ( (length = strlen(new_rl_line_buffer)) > 0  &&  new_rl_line_buffer[length - 1] == '\n') {
    new_rl_line_buffer[length - 1] = '\0';
    rl_done = TRUE;
    return_key = (char) '\n';
    assert(strchr(new_rl_line_buffer, '\n') == NULL);
  }

  rl_delete_text(0, strlen(rl_line_buffer));
  rl_point = 0;
  rl_insert_text(new_rl_line_buffer);
  rl_point = strlen(new_rl_line_buffer);

  
  
  if (*message && *message != hotkey) {                          /* if message has been set (i.e. != hotkey) , and isn't empty: */ 
    message = append_and_free_old(mysavestring(message), " ");   /* put space (for readability) between the message and the input line .. */
    message_in_echo_area(message);                          /* .. then write it to echo area */
  }     

  clear_line();
  rl_on_new_line();
  rl_redisplay();
 

  free_splitlist(fragments);                                   /* this will free all the fragments (and the list itself) in one go  */
  free_multiple(prefix, postfix, filter_food, executing_keyseq, filtered, new_rl_line_buffer, history, histpos_as_string, FMEND);
  return 0;
}
Beispiel #8
0
static void
my_homegrown_redisplay(int hide_passwords)
{
  static int line_start = 0;    /* at which position of prompt_plus_line does the printed line start? */
  static int line_extends_right = 0;
  static int line_extends_left = 0;
  static char *previous_line = NULL;
  
  
  int width = winsize.ws_col;
  int skip = max(1, min(width / 5, 10));        /* jumpscroll this many positions when cursor reaches edge of terminal */
  
  char *prompt_without_ignore_markers;
  int colourless_promptlen = colourless_strlen(rl_prompt, &prompt_without_ignore_markers,0);
  int promptlen = strlen(prompt_without_ignore_markers);
  int invisible_chars_in_prompt = promptlen - colourless_promptlen;
  char *prompt_plus_line = add2strings(prompt_without_ignore_markers, rl_line_buffer);
  char *new_line;
  int total_length = strlen(prompt_plus_line);
  int curpos = promptlen + rl_point; /* cursor position within prompt_plus_line */
  int i, printed_length,
    new_curpos,                    /* cursor position on screen */
    keep_old_line, vlinestart, printwidth, last_column;
  DPRINTF3(DEBUG_AD_HOC,"rl_prompt: <%s>, prompt_without_ignore_markers: <%s>,  prompt_plus_line: <%s>", rl_prompt, prompt_without_ignore_markers, prompt_plus_line);   

  /* In order to handle prompt with colour we either print the whole prompt, or start past it:
     starting in the middle is too difficult (i.e. I am too lazy) to get it right.
     We use a "virtual line start" vlinestart, which is the number of invisible chars in prompt in the former case, or
     linestart in the latter (which then must be >= strlen(prompt))

     At all times (before redisplay and after) the following is true:
     - the cursor is at column (curpos - vlinestart) (may be < 0 or > width)
     - the character under the cursor is prompt_plus_line[curpos]
     - the character at column 0 is prompt_plus_line[linestart]
     - the last column is at <number of printed visible or invisible chars> - vlinestart
     
     the goal of this function is to display (part of) prompt_plus_line such
     that the cursor is visible again */
     
  
  if (hide_passwords)
    for (i = promptlen; i < total_length; i++)
      prompt_plus_line[i] = '*';        /* hide a pasword by making user input unreadable  */


  if (rl_point == 0)            /* (re)set  at program start and after accept_line (where rl_point is zeroed) */
    line_start = 0;
  assert(line_start == 0 || line_start >= promptlen); /* the line *never* starts in the middle of the prompt (too complicated to handle)*/
  vlinestart = (line_start > promptlen ? line_start : invisible_chars_in_prompt); 
  

  if (curpos - vlinestart > width - line_extends_right) /* cursor falls off right edge ?   */
    vlinestart = (curpos - width + line_extends_right) + skip;  /* jumpscroll left                 */

  else if (curpos < vlinestart + line_extends_left) {   /* cursor falls off left edge ?    */
    if (curpos == total_length) /* .. but still at end of line?    */
      vlinestart = max(0, total_length - width);        /* .. try to display entire line   */
    else                        /* in not at end of line ..        */
      vlinestart = curpos - line_extends_left - skip; /* ... jumpscroll right ..         */
  }     
  if (vlinestart <= invisible_chars_in_prompt) {
    line_start = 0;             /* ... but not past start of line! */
    vlinestart = invisible_chars_in_prompt;
  } else if (vlinestart > invisible_chars_in_prompt && vlinestart <= promptlen) {
    line_start = vlinestart = promptlen;
  } else {
    line_start = vlinestart;
  }

  printwidth = (line_start > 0 ? width : width + invisible_chars_in_prompt);
  printed_length = min(printwidth, total_length - line_start);  /* never print more than width     */
  last_column = printed_length - vlinestart;


  /* some invariants :     0 <= line_start <= curpos <= line_start + printed_length <= total_length */
  /* these are interesting:   ^                                                      ^              */

  assert(0 <= line_start);
  assert(line_start <= curpos);
  assert(curpos <= line_start + printed_length);        /* <=, rather than <, as cursor may be past eol   */
  assert(line_start + printed_length <= total_length);


  new_line = prompt_plus_line + line_start;
  new_line[printed_length] = '\0';
  new_curpos = curpos - vlinestart;

  /* indicate whether line extends past right or left edge  (i.e. whether the "interesting
     inequalities marked ^ above are really unequal) */

  line_extends_left = (line_start > 0 ? 1 : 0);
  line_extends_right = (total_length - vlinestart > width ? 1 : 0);
  if (line_extends_left)
    new_line[0] = '<';
  if (line_extends_right)
    new_line[printwidth - 1] = '>';

  

  keep_old_line = FALSE;
  if (term_cursor_hpos) {
    if (previous_line && strcmp(new_line, previous_line) == 0) {
      keep_old_line = TRUE;
    } else {
      if (previous_line)
        free(previous_line);
      previous_line = mysavestring(new_line);
    }
  }
  /* DPRINTF2(DEBUG_AD_HOC, "keep_old_line=%d, new_line=<%s>", keep_old_line, new_line); */
  /* keep_old_line = TRUE; */
  if (!keep_old_line) {
    clear_line();
    cr();
    write_patiently(STDOUT_FILENO, new_line, printed_length, "to stdout");
  }
  
  assert(term_cursor_hpos || !keep_old_line);   /* if we cannot position cursor, we must have reprinted ... */

  if (term_cursor_hpos)
    cursor_hpos(new_curpos);
  else                          /* ... so we know we're 1 past last position on line */
    backspace(last_column - new_curpos);
  free(prompt_plus_line);
  free(prompt_without_ignore_markers);
}
Beispiel #9
0
static int
is_server_running(rmedia_handle_t *handle)
{
	door_arg_t	door_args;
	smedia_reqping_t	reqping;
	smedia_retping_t	*retping;
	int		ret_val;
	int		door_fd;
	CLIENT		*clnt;
	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
	smserver_info	*server_info;

	/*
	 * We will assume that we are running at level 2 or greater
	 * and attempt to contact the server using RPC mecahnisms.
	 * If that fails then we will attempt to contact the server
	 * using non-rpc mechanism. This will enable the libsmedia
	 * to be used in SINGLE user mode when inetd is not running.
	 * We expect the server to have been started manually by user.
	 *
	 * Note that "localhost" is used (vs hostname (eg, "uname -n")),
	 * as this minimizes interference with common IPSec rules.
	 */

	clnt = clnt_create("localhost", SMSERVERPROG, SMSERVERVERS,
	    "circuit_v");
	if (clnt == (CLIENT *)NULL) {
		/*
		 * The failure could be that we are running at level 1
		 */
		door_fd = open(smedia_service, O_RDONLY, 0644);
		if (door_fd < 0) {
			DPRINTF1("Error in opening %s\n",
			    smedia_service);
			return (0);
		}

		DPRINTF1("rbuf address=%p\n", rbuf);
		reqping.cnum = SMEDIA_CNUM_PING;
		door_args.data_ptr = (char *)&reqping;
		door_args.data_size = sizeof (smedia_services_t);
		door_args.desc_ptr = NULL;
		door_args.desc_num = 0;
		door_args.rbuf = rbuf;
		door_args.rsize = sizeof (rbuf);

		ret_val = door_call(door_fd, &door_args);
		(void) close(door_fd);
		if (ret_val < 0) {
			return (0);
		}
		DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
		    door_args.rsize, door_args.data_size,
		    door_args.data_ptr);
		retping = (smedia_retping_t *)(
		    (void *)door_args.data_ptr);
		if (retping->cnum != SMEDIA_CNUM_PING) {
			DPRINTF1("*** door call failed *** cnum "
			    "returned = 0x%x\n", retping->cnum);
			return (0);
		}
		return (1);
	}
	server_info = smserverproc_get_serverinfo_1(NULL, clnt);
	if (server_info == NULL) {
		if (clnt)
			clnt_destroy(clnt);
		return (0);
	}
	if (server_info->status != 0) {
		if (clnt)
			clnt_destroy(clnt);
		DPRINTF1("get server_info call failed. "
		    "status = %d\n", server_info->status);
		return (0);
	}
	if (server_info->vernum != SMSERVERVERS) {
		if (clnt)
			clnt_destroy(clnt);
		DPRINTF2("version expected = %d version "
		    "returned = %d\n", SMSERVERVERS,
		    server_info->vernum);
		return (0);
	}

	door_fd = open(smedia_service, O_RDONLY, 0644);
	if (door_fd < 0) {
		DPRINTF1("Error in opening %s\n", smedia_service);
		return (0);
	}

	DPRINTF1("rbuf address=%p\n", rbuf);
	reqping.cnum = SMEDIA_CNUM_PING;
	door_args.data_ptr = (char *)&reqping;
	door_args.data_size = sizeof (smedia_services_t);
	door_args.desc_ptr = NULL;
	door_args.desc_num = 0;
	door_args.rbuf = rbuf;
	door_args.rsize = sizeof (rbuf);

	ret_val = door_call(door_fd, &door_args);
	(void) close(door_fd);
	if (ret_val < 0) {
		return (0);
	}
	DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
	    door_args.rsize, door_args.data_size,
	    door_args.data_ptr);
	retping = (smedia_retping_t *)((void *)door_args.data_ptr);
	if (retping->cnum != SMEDIA_CNUM_PING) {
		DPRINTF1("*** door call failed *** cnum returned "
		    "= 0x%x\n", retping->cnum);
		return (0);
	}
	handle->sm_clnt = clnt;
	return (1);
}
Beispiel #10
0
smedia_handle_t
get_handle_from_fd(int32_t fd)
{
	rmedia_handle_t	*handle;
	void	*lib_handle;
	int	door_fd, door_server;
	int	ret_val;
	door_arg_t	door_args;
	smedia_reqopen_t	reqopen;
	smedia_reterror_t	*reterror;
	door_desc_t	ddesc[2];
	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
	struct stat	stat;

	DPRINTF("smedia_get_handle called\n");
	handle = (rmedia_handle_t *)malloc(sizeof (rmedia_handle_t));
	if (handle == NULL) {
		DPRINTF("Could not allocate memory for handle\n");
		return (NULL);
	}
	(void) memset((void *) handle, 0, sizeof (rmedia_handle_t));
	handle->sm_fd = -1;
	handle->sm_door = -1;
	handle->sm_death_door = -1;
	handle->sm_buffd = -1;
	handle->sm_buf = NULL;
	handle->sm_bufsize = 0;

	if (ioctl(fd, DKIOCINFO, &handle->sm_dkinfo) == -1) {
		free(handle);
		PERROR("DKIOCINFO failed");
		return (NULL);
	}
	lib_handle = get_dev_library_handle(fd);
	if (lib_handle == NULL) {
		free(handle);
		DPRINTF("lib_Handle is NULL\n");
		errno = ENOTSUP;
		return (NULL);
	}
	DPRINTF("Handle initialised successfully.\n");
	/* Initialise the handle elements */
	handle->sm_lib_handle = lib_handle;
	handle->sm_signature = LIBSMEDIA_SIGNATURE;
	DPRINTF2("fd=%d signature=0x%x\n", handle->sm_fd, handle->sm_signature);

	if ((handle->sm_dkinfo.dki_ctype == DKC_SCSI_CCS) ||
	    (handle->sm_dkinfo.dki_ctype == DKC_MD21) ||
	    (handle->sm_dkinfo.dki_ctype == DKC_CDROM)) {

		ret_val = is_server_running(handle);
		if (ret_val == 0) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			return (NULL);
		}
		door_fd = open(smedia_service, O_RDONLY, 0644);
		if (door_fd < 0) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			DPRINTF1("Error in opening %s\n", smedia_service);
			PERROR(smedia_service);
			return (NULL);
		}

		DPRINTF1("rbuf address=%p\n", rbuf);
		ddesc[0].d_data.d_desc.d_descriptor = fd;
		ddesc[0].d_attributes = DOOR_DESCRIPTOR;
		reqopen.cnum = SMEDIA_CNUM_OPEN_FD;
		door_args.data_ptr = (char *)&reqopen;
		door_args.data_size = sizeof (smedia_services_t);
		door_args.desc_ptr = &ddesc[0];
		door_args.desc_num = 1;
		door_args.rbuf = rbuf;
		door_args.rsize = sizeof (rbuf);

		ret_val = door_call(door_fd, &door_args);
		(void) close(door_fd);
		if (ret_val < 0) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			PERROR("door_call");
			return (NULL);
		}
		DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
		    door_args.rsize, door_args.data_size,
		    door_args.data_ptr);
		reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
		if (reterror->cnum != SMEDIA_CNUM_OPEN_FD) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			DPRINTF1(
	"*** door call failed *** cnum returned = 0x%x\n", reterror->cnum);
			errno = reterror->errnum;
			return (NULL);
		}
		/*
		 * 2 door descriptors are returned after the above door call.
		 * The first door descriptor is the one that will be used
		 * in subsequent smedia calls. A dedicated thread is
		 * associated with this door to handle client calls.
		 * The second door descriptor is needed to signal unexpected
		 * death of the client to the server. This will help the server
		 * to do the necessary cleanup.
		 */
		if (door_args.desc_num != 2) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			DPRINTF("Num of door descriptors returned by "
			    "server is not 2");
			if (door_args.desc_num)
				(void) close(door_args.desc_ptr->\
				    d_data.d_desc.d_descriptor);
			return (NULL);
		}
		door_server = door_args.desc_ptr->d_data.d_desc.d_descriptor;
		/* Check if the descriptor returned is S_IFDOOR */
		if (fstat(door_server, &stat) < 0) {
			PERROR("fstat");
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			return (NULL);
		}
		if (!S_ISDOOR(stat.st_mode)) {
			DPRINTF(
		"Descriptor returned by door_call is not of type DOOR\n");
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			return (NULL);
		}
		handle->sm_door = door_server;
		handle->sm_fd = fd;
		door_args.desc_ptr++;
		handle->sm_death_door =
		    door_args.desc_ptr->d_data.d_desc.d_descriptor;
		DPRINTF("door call succeeded.\n");
		return ((smedia_handle_t)handle);

	} else {
		handle->sm_fd = fd;
		return ((smedia_handle_t)handle);
	}

}
Beispiel #11
0
/*
  Given the actual data set <dataSet>, estimates the values for
  algorithm parameters that would give the optimal running time of a
  query. 

  The set <sampleQueries> is a set with query sample points
  (R-NN DS's parameters are optimized for query points from the set
  <sampleQueries>). <sampleQueries> could be a sample of points from the
  actual query set or from the data set. When computing the estimated
  number of collisions of a sample query point <q> with the data set
  points, if there is a point in the data set with the same pointer
  with <q> (that is when <q> is a data set point), then the
  corresponding point (<q>) is not considered in the data set (for the
  purpose of computing the respective #collisions estimation).
//如果查询样本点来自数据集,则为了考虑碰撞估计,不讲对应的样本查询点考虑进数据集合
  The return value is the estimate of the optimal parameters.
*/
RNNParametersT computeOptimalParameters(RealT R,   //半径
					RealT successProbability,     //成功率
					IntT nPoints,      //数据点的个数
					IntT dimension,     //维度
					PPointT *dataSet,    //数据集合
					IntT nSampleQueries,     //样本查询点的个数
					PPointT *sampleQueries,     //样本查询点的数据集
					MemVarT memoryUpperBound){   //每个半径需要使用内存的上界,多个半径的时候Qboundry才会使用到,用一个半径的时候,是使用不到的。
  ASSERT(nSampleQueries > 0);

  initializeLSHGlobal();   //设置了一个时间参数,把时间函数所花的时间求出来,得出精确操作所花费的时间
                           //用来评估算法效率
  RNNParametersT optParameters;
  optParameters.successProbability = successProbability;
  optParameters.dimension = dimension;
  optParameters.parameterR = R;
#ifdef USE_L1_DISTANCE
  optParameters.parameterR2 = R;   //L1 norm下R2 与R相等,   //R与R2的作用?
#else  
  optParameters.parameterR2 = SQR(R);   //?R2的作用是什么
#endif
  optParameters.useUfunctions = TRUE; // TODO: could optimize here:
				      // maybe sometimes, the old way
				      // was better.
  optParameters.parameterW = PARAMETER_W_DEFAULT;  //W用于计算L2 norm下的LSH函数的参数,4
  optParameters.parameterT = nPoints;    //数据点的个数
  optParameters.typeHT = HT_HYBRID_CHAINS;  //hashing表构建的类型
  
  // Compute the run-time parameters (timings of different parts of the algorithm).
  IntT nReps = 10; // # number of repetitiions //重复的数量为10个 
  RealT lshPrecomp = 0, uhashOver = 0, distComp = 0;  //LSH预处理的时间,从Hash表中取得桶的时间 ,计算两点距离的时间
  for(IntT i = 0; i < nReps; i++){          //重复nReps次,计算LSH 3个阶段的时间,然后在计算出来的平均时间。
    RealT lP, uO, dC;                    //并且进行了哈希表的构建,哈希函数的计算,等等
    determineRTCoefficients(optParameters.parameterR, 
			    optParameters.successProbability, 
			    optParameters.useUfunctions, 
			    optParameters.typeHT, 
			    optParameters.dimension, 
			    nPoints, 
			    dataSet, 
			    lP, 
			    uO, 
			    dC);
    lshPrecomp += lP;   //累计重复nReps次的时间。       因为随机数产生是不同的,所以每次处理的时间也不同
    uhashOver += uO;            
    distComp += dC;            
    DPRINTF4("Coefs: lP = %0.9lf\tuO = %0.9lf\tdC = %0.9lf\n", lP, uO, dC);    
  }
  lshPrecomp /= nReps;     //平均处理的时间
  uhashOver /= nReps;     
  distComp /= nReps;      
  DPRINTF("Coefs (final): lshPrecomp = %0.9lf\n", lshPrecomp);    
  DPRINTF("Coefs (final): uhashOver = %0.9lf\n", uhashOver);        
  DPRINTF("Coefs (final): distComp = %0.9lf\n", distComp);          
  DPRINTF("Remaining memory: %lld\n", memoryUpperBound);         

  // Try all possible <k>s and choose the one for which the time
  // estimate of a query is minimal.
  IntT k;     
  RealT timeLSH, timeUH, timeCycling;    
  //IntT queryIndex = genRandomInt(0, nPoints);
  //PPointT query = dataSet[queryIndex]; // query points = a random points from the data set. //查询点取为从数据集中取的随机点
  IntT bestK = 0;
  RealT bestTime = 0;
  for(k = 2; ; k += 2){   //之前进行计算的时候,将k预设为16

    DPRINTF("ST. k = %d\n", k);
    IntT m = computeMForULSH(k, successProbability);    //通过k和p计算出m
    IntT L = m * (m-1) / 2;
    //DPRINTF("Available memory: %lld\n", getAvailableMemory());
    if (L * nPoints > memoryUpperBound / 12){   //??为什么除以12呢?? 12是一个常数,用于对内存的估算  //4×tableSize+8×#buckets+8n<20n
      break;
    }
    timeLSH = m * k * lshPrecomp;    //m次,k维预处理时间,之前有计算好平均每次处理的时间
    timeUH = L * uhashOver;           //L个hash表
    //RealT nCollisions = estimateNCollisionsFromDSPoint(nPoints, dimension, dataSet, queryIndex, k, L, R);

    // Compute the mean number of collisions for the points from the sample query set.
    RealT nCollisions = 0;      //计算平均冲突的点的数量
    for(IntT i = 0; i < nSampleQueries; i++){
      nCollisions += estimateNDistinctCollisions(nPoints, dimension, dataSet, sampleQueries[i], TRUE, k, m, R);
    }
    nCollisions /= nSampleQueries;    //每个查询点能查询到近邻点的平均数量

    timeCycling = nCollisions * distComp;       //查询点查到所有近邻的时间??
    DPRINTF3("ST.m=%d L=%d \n", m, L);
    DPRINTF("ST.Estimated # distinct collisions = %0.6lf\n", (double)nCollisions);
    DPRINTF("ST.TimeLSH = %0.6lf\n", timeLSH);
    DPRINTF("ST.TimeUH = %0.6lf\n", timeUH);
    DPRINTF("ST.TimeCycling = %0.6lf\n", timeCycling);
    DPRINTF("ST.Sum = %0.6lf\n", timeLSH + timeUH + timeCycling);
    if (bestK == 0 || (timeLSH + timeUH + timeCycling) < bestTime) {  //第一轮循环k=0,此时bestTime是比较大的,所以随着k的增大,得到最优时间
      bestK = k;
      bestTime = timeLSH + timeUH + timeCycling;
    }
    ASSERT(k < 100); //  otherwise, k reached 100 -- which, from
    //  experience, should never happen for reasonable
    //  data set & available memory amount.
  }


  DPRINTF("STO.Optimal k = %d\n", bestK);    
  IntT m = computeMForULSH(bestK, successProbability);   //计算L2 norm下的m
  IntT L = m * (m-1) / 2;
  timeLSH = m * bestK * lshPrecomp;
  timeUH = L * uhashOver;
  
  // Compute the mean number of collisions for the points from the sample query set.
  RealT nCollisions = 0;
  for(IntT i = 0; i < nSampleQueries; i++){
    nCollisions += estimateNDistinctCollisions(nPoints, dimension, dataSet, sampleQueries[i], TRUE, k, m, R);
  }
  nCollisions /= nSampleQueries;

  // timeCycling = estimateNCollisionsFromDSPoint(nPoints, dimension, dataSet, queryIndex, bestK, L, R) * distComp;
  timeCycling = nCollisions * distComp;
  DPRINTF("STO.TimeLSH = %0.6lf\n", timeLSH);
  DPRINTF("STO.TimeUH = %0.6lf\n", timeUH);
  DPRINTF("STO.TimeCycling = %0.6lf\n", timeCycling);
  DPRINTF("STO.Sum = %0.6lf\n", timeLSH + timeUH + timeCycling);
  
  optParameters.parameterK = bestK;
  optParameters.parameterM = m;
  optParameters.parameterL = L;

  return optParameters;
}
Beispiel #12
0
/* Read history and completion word lists */
void
init_rlwrap()
{

  char *homedir, *histdir, *homedir_prefix, *hostname;
  time_t now;
  
  /* open debug file if necessary */

  if (debug) {    
    debug_fp = fopen(DEBUG_FILENAME, "w");
    if (!debug_fp)
      myerror("Couldn't open debug file %s", DEBUG_FILENAME);
    setbuf(debug_fp, NULL); /* always write debug messages to disk at once */
  }
  hostname = getenv("HOSTNAME") ? getenv("HOSTNAME") : "?";
  now = time(NULL);
  DPRINTF0(DEBUG_ALL, "-*- mode: grep -*-");
  DPRINTF3(DEBUG_ALL, "rlwrap version %s, host: %s, time: %s", VERSION, hostname, ctime(&now));
  init_terminal();

  
  
  /* Determine rlwrap home dir and prefix for default history and completion filenames */
  homedir = (getenv("RLWRAP_HOME") ? getenv("RLWRAP_HOME") : getenv("HOME"));
  homedir_prefix = (getenv("RLWRAP_HOME") ?                    /* is RLWRAP_HOME set?                */
		    add2strings(getenv("RLWRAP_HOME"), "/") :  /* use $RLWRAP_HOME/<command>_history */
		    add2strings(getenv("HOME"), "/."));	       /* if not, use ~/.<command>_history   */

  /* Determine history file name and check its existence and permissions */

  if (history_filename) {
    histdir = mydirname(history_filename);
  } else {
    histdir = homedir;
    history_filename = add3strings(homedir_prefix, command_name, "_history");
  }
  
  if (write_histfile) {
    if (access(history_filename, F_OK) == 0) {	/* already exists, can we read/write it? */
      if (access(history_filename, R_OK | W_OK) != 0) {
	myerror("cannot read and write %s", history_filename);
      }
    } else {			        /* doesn't exist, can we create it? */
      if(access(histdir, W_OK) != 0) {
        if (errno == ENOENT) {
          mode_t oldmask = umask(0);
          if (mkdir(histdir, 0700))       /* rwx------ */
            myerror("cannot create directory %s", histdir);
          umask(oldmask);
        } else {
          myerror("cannot create history file in %s", histdir);
        }
      }
    }
  } else {			/* ! write_histfile */
    if (access(history_filename, R_OK) != 0) {
      myerror("cannot read %s", history_filename);
    }
  }

  /* Initialize history */
  using_history();
  stifle_history(histsize);
  read_history(history_filename);	/* ignore errors here: history file may not yet exist, but will be created on exit */

  if (feed_history_into_completion_list)
    feed_file_into_completion_list(history_filename);
  /* Determine completion file name (completion files are never written to,
     and ignored when unreadable or non-existent) */

  completion_filename =
    add3strings(homedir_prefix, command_name, "_completions");
  default_completion_filename =
    add3strings(DATADIR, "/rlwrap/completions/", command_name);

  rl_readline_name = command_name;

  /* Initialise completion list (if <completion_filename> is readable) */
  if (access(completion_filename, R_OK) == 0) {
    feed_file_into_completion_list(completion_filename);
  } else if (access(default_completion_filename, R_OK) == 0) {
    feed_file_into_completion_list(default_completion_filename);
  }

  
}
Beispiel #13
0
/*
 * main loop: listen on stdin (for user input) and master pty (for command output),
 * and try to write output_queue to master_pty (if it is not empty)
 * This function never returns.
 */
void
main_loop()
{				
  int nfds;			
  fd_set readfds;	
  fd_set writefds;
  int nread;		
  char buf[BUFFSIZE], *timeoutstr, *old_raw_prompt, *new_output_minus_prompt;
  int promptlen = 0;
  int leave_prompt_alone;
  sigset_t no_signals_blocked;
   
  struct timespec         select_timeout, *select_timeoutptr;
  struct timespec immediately = { 0, 0 }; /* zero timeout when child is dead */
  struct timespec  wait_a_little = {0, 0xBadf00d }; /* tv_usec field will be filled in when initialising */
  struct timespec  *forever = NULL;
  wait_a_little.tv_nsec = 1000 * 1000 * wait_before_prompt;

  
  
  sigemptyset(&no_signals_blocked);
  

  init_readline("");
  last_minute_checks();
  pass_through_filter(TAG_OUTPUT,""); /* If something is wrong with filter, get the error NOW */
  set_echo(FALSE);		/* This will also put the terminal in CBREAK mode */
	test_main(); 
  
  /* ------------------------------  main loop  -------------------------------*/
  while (TRUE) {
    /* listen on both stdin and pty_fd */
    FD_ZERO(&readfds);
    FD_SET(STDIN_FILENO, &readfds);
    FD_SET(master_pty_fd, &readfds);

    /* try to write output_queue to master_pty (but only if it is nonempty) */
    FD_ZERO(&writefds);
    if (output_queue_is_nonempty())
      FD_SET(master_pty_fd, &writefds);



    DPRINTF1(DEBUG_AD_HOC, "prompt_is_still_uncooked =  %d", prompt_is_still_uncooked);
    if (command_is_dead || ignore_queued_input) {
      select_timeout = immediately;
      select_timeoutptr = &select_timeout;
      timeoutstr = "immediately";
    } else if (prompt_is_still_uncooked) {
      select_timeout = wait_a_little;
      select_timeoutptr = &select_timeout;
      timeoutstr = "wait_a_little";
    } else {
      select_timeoutptr = forever; /* NULL */
      timeoutstr = "forever";
    }
     
    DPRINTF1(DEBUG_TERMIO, "calling select() with timeout %s",  timeoutstr);
    

    nfds = my_pselect(1 + master_pty_fd, &readfds, &writefds, NULL, select_timeoutptr, &no_signals_blocked);

    DPRINTF3(DEBUG_TERMIO, "select() returned  %d (stdin|pty in|pty out = %03d), within_line_edit=%d", nfds,
	     100*(FD_ISSET(STDIN_FILENO, &readfds)?1:0) + 10*(FD_ISSET(master_pty_fd, &readfds)?1:0) + (FD_ISSET(master_pty_fd, &writefds)?1:0), 
	     within_line_edit);

    assert(!filter_pid || filter_is_dead || kill(filter_pid,0) == 0); 
    assert(command_is_dead || kill(command_pid,0) == 0);
    
    /* check flags that may have been set by signal handlers */
    if (filter_is_dead) 
      filters_last_words(); /* will call myerror with last words */
      	
    if (received_WINCH) {  /* received_WINCH flag means we've had a WINCH while within_line_edit was FALSE */
      DPRINTF0(DEBUG_READLINE, "Starting line edit as a result of WINCH ");
      within_line_edit = TRUE;
      restore_rl_state();
      received_WINCH = FALSE;
      continue;
    }	
    
    if (nfds < 0) {		/* exception  */	
      if (errno == EINTR) {	/* interrupted by signal */
	continue;
      }	else
	myerror("select received exception");
    } else if (nfds == 0) {
      
      /* timeout, which can only happen when .. */
      if (ignore_queued_input) {       /* ... we have read all the input keystrokes that should
					  be ignored (i.e. those that accumulated on stdin while we
				          were calling an external editor) */
	ignore_queued_input = FALSE;
	continue;
      } else if (command_is_dead) {                         /* ... or else, if child is dead, ... */
	DPRINTF2(DEBUG_SIGNALS,
		 "select returned 0, command_is_dead=%d, commands_exit_status=%d",
		 command_is_dead, commands_exit_status);
	cleanup_rlwrap_and_exit(EXIT_SUCCESS);
      }	else if (prompt_is_still_uncooked) { /* cooking time? */
	if (we_just_got_a_signal_or_EOF) {
	  we_just_got_a_signal_or_EOF = FALSE;              /* 1. If we got a signal/EOF before cooking time, we don't need special action
                                                                  to preserve the cooked prompt.
							       2. Reset we_just_got_a_signal_or_EOF  after a signal or EOF that didn't kill command */
          continue;
	}	
	if (!skip_rlwrap()) {                        /* ... or else, it is time to cook the prompt */
	  if (pre_given && accepted_lines == 0) {
	    saved_rl_state.input_buffer = mysavestring(pre_given); /* stuff pre-given text into edit buffer */
	    saved_rl_state.point =  strlen(pre_given);
	    DPRINTF0(DEBUG_READLINE, "Starting line edit (because of -P option)");
	    within_line_edit = TRUE;
	    restore_rl_state();

	    continue;
	  }
	  
	  if (accepted_lines == 1 && one_shot_rlwrap) 
	    cleanup_rlwrap_and_exit(EXIT_SUCCESS);

			  
	  move_cursor_to_start_of_prompt(ERASE); /* cooked prompt may be shorter than raw prompt, hence the ERASE */
	  /* move and erase before cooking, as we need to move/erase according
	     to the raw prompt */
          cook_prompt_if_necessary();
	  DPRINTF2(DEBUG_READLINE,"After cooking, raw_prompt=%s, cooked=%s",
                   mangle_string_for_debug_log(saved_rl_state.raw_prompt, MANGLE_LENGTH),
                   mangle_string_for_debug_log(saved_rl_state.cooked_prompt, MANGLE_LENGTH));
	  my_putstr(saved_rl_state.cooked_prompt);
	  rlwrap_already_prompted = TRUE;
	}
	prompt_is_still_uncooked = FALSE;
      } else {
	myerror("unexpected select() timeout");
      }
    } else if (nfds > 0) {	/* Hah! something to read or write */ 

      /* -------------------------- read pty --------------------------------- */
      if (FD_ISSET(master_pty_fd, &readfds)) { /* there is something to read on master pty: */
	if ((nread = read(master_pty_fd, buf, BUFFSIZE - 1)) <= 0) { /* read it */
	 
	  if (command_is_dead || nread == 0) { /*  child is dead or has closed its stdout */
	    if (promptlen > 0)	/* commands dying words were not terminated by \n ... */
	      my_putchar('\n');	/* provide the missing \n */
	    cleanup_rlwrap_and_exit(EXIT_SUCCESS);
	  } else  if (errno == EINTR)	/* interrupted by signal ...*/	                     
	    continue;                   /* ... don't worry */
	  else
	    myerror("read error on master pty");
	}
	  
	completely_mirror_slaves_output_settings(); /* some programs (e.g. joe) need this. Gasp!! */	
        
	
        if (skip_rlwrap()) { /* Race condition here! The client may just have finished an emacs session and
			        returned to cooked mode, while its ncurses-riddled output is stil waiting for us to be processed. */
	  write_patiently(STDOUT_FILENO, buf, nread, "to stdout");

	  DPRINTF2(DEBUG_TERMIO, "read from pty and wrote to stdout  %d  bytes in direct mode  <%s>",
                   nread, mangle_string_for_debug_log((buf[nread]='\0', buf), MANGLE_LENGTH));
	  yield();
	  continue;
	}

	DPRINTF2(DEBUG_TERMIO, "read %d bytes from pty into buffer: %s", nread,  mangle_string_for_debug_log((buf[nread]='\0', buf), MANGLE_LENGTH));
        
        remove_padding_and_terminate(buf, nread);
        
	write_logfile(buf);
	if (within_line_edit)	/* client output arrives while we're editing keyboard input:  */
	  save_rl_state();      /* temporarily disable readline and restore the screen state before readline was called */
  

	assert(saved_rl_state.raw_prompt != NULL);


        /* We *always* compute the printable part and the new raw prompt, and *always* print the printable part
           There are four possibilities:
           1. impatient before cooking.         The raw prompt has been printed,  write the new output after it
           2. patient before cooking            No raw prompt has been printed yet, don't print anything
           3. impatient after cooking
             3a  no current prompt              print the new output
             3b  some current prompt            erase it, replace by current raw prompt and print new output
           4. patient after cooking             don't print anything
        */
        
        /* sometimes we want to leave the prompt standing, e.g. after accepting a line, or when a signal arrived */
	leave_prompt_alone =
	     *saved_rl_state.raw_prompt == '\0' /* saved_rl_state.raw_prompt = "" in two distinct cases: when there is actually no prompt,
						   or just after accepting a line, when the cursor is at the end of the prompt. In both
						   cases, we dont't want to move the cursor */
          || prompt_is_still_uncooked /* in this case no prompt has been displayed yet */
          || command_is_dead                    
          || (we_just_got_a_signal_or_EOF && strrchr(buf, '\n')); /* a signal followed by output with a newline in it: treat it as
                                                                     response to user input, so leave the prompt alone */

        DPRINTF3(DEBUG_READLINE, "leave_prompt_alone: %s (raw prompt: %s, prompt_is_still_uncooked: %d)",
                 (leave_prompt_alone? "yes" : "no"), mangle_string_for_debug_log(saved_rl_state.raw_prompt, MANGLE_LENGTH), prompt_is_still_uncooked);
	
        if (!leave_prompt_alone) /* && (!impatient_prompt || !saved_rl_state.cooked_prompt)) */
	  move_cursor_to_start_of_prompt(ERASE);  
	else if (we_just_got_a_signal_or_EOF) {
	  free (saved_rl_state.raw_prompt);
	  saved_rl_state.raw_prompt =  mysavestring(""); /* prevent reprinting the prompt */
	}	

        if (impatient_prompt && !leave_prompt_alone)
          old_raw_prompt =  mysavestring(saved_rl_state.raw_prompt);

        new_output_minus_prompt = process_new_output(buf, &saved_rl_state);	/* chop off the part after the last newline and put this in
										   saved_rl_state.raw_prompt (or append buf if  no newline found)*/

	if (impatient_prompt) {   /* in impatient mode, ALL command output is passed through the OUTPUT filter, including the prompt The
				     prompt, however, is filtered separately at cooking time and then displayed */
	  char *filtered = pass_through_filter(TAG_OUTPUT, buf);
          if(!leave_prompt_alone) {
            my_putstr(old_raw_prompt);
            free(old_raw_prompt);
          }
	  my_putstr(filtered);
	  free (filtered);
	  rlwrap_already_prompted = TRUE;
	} else {
	  my_putstr(new_output_minus_prompt);
	  rlwrap_already_prompted = FALSE;
	}	
	   
	free(new_output_minus_prompt);	

		    
	prompt_is_still_uncooked = TRUE; 
       

	if (within_line_edit)
	  restore_rl_state();

	yield();  /* wait for what client has to say .... */ 
	continue; /* ... and don't attempt to process keyboard input as long as it is talking ,
		     in order to avoid re-printing the current prompt (i.e. unfinished output line) */
      }

      
      /* ----------------------------- key pressed: read stdin -------------------------*/
      if (FD_ISSET(STDIN_FILENO, &readfds)) {	/* key pressed */
	unsigned char byte_read;                /* the readline function names and documentation talk about "characters" and "keys",
						   but we're reading bytes (i.e. unsigned chars) here, and those may very well be
						   part of a multi-byte character. Example: hebrew "aleph" in utf-8 is 0xd790; pressing this key
						   will make us read 2 bytes 0x90 and then 0xd7, (or maybe the other way round depending on endianness??)
						   The readline library hides all this complexity and allows one to just "pass the bytes around" */
	nread = read(STDIN_FILENO, &byte_read, 1);  /* read next byte of input   */
	assert(sizeof(unsigned char) == 1);      /* gets optimised away */

	if (nread <= 0) 
	  DPRINTF1(DEBUG_TERMIO, "read from stdin returned %d", nread); 
	if (nread < 0)
	  if (errno == EINTR)
	    continue;
	  else
	    myerror("Unexpected error");
	else if (nread == 0)	/* EOF on stdin */
	  cleanup_rlwrap_and_exit(EXIT_SUCCESS);
        else if (ignore_queued_input)
	  continue;             /* do nothing with it*/
	assert(nread == 1);
	DPRINTF2(DEBUG_TERMIO, "read from stdin: byte 0x%02x (%s)", byte_read, mangle_char_for_debug_log(byte_read, TRUE)); 
	if (skip_rlwrap()) {	/* direct mode, just pass it on */
	                        /* remote possibility of a race condition here: when the first half of a multi-byte char is read in
				   direct mode and the second half in readline mode. Oh well... */
	  DPRINTF0(DEBUG_TERMIO, "passing it on (in transparent mode)");	
	  completely_mirror_slaves_terminal_settings(); /* this is of course 1 keypress too late: we should
							   mirror the terminal settings *before* the user presses a key.
							   (maybe using rl_event_hook??)   @@@FIXME  @@@ HOW?*/
          write_patiently(master_pty_fd, &byte_read, 1, "to master pty");
	} else {		/* hand it over to readline */
	  if (!within_line_edit) {	/* start a new line edit    */
	    DPRINTF0(DEBUG_READLINE, "Starting line edit");
	    within_line_edit = TRUE;
	    restore_rl_state();
	  } 
	                                        
	  
	  

	  if (term_eof && byte_read == term_eof && strlen(rl_line_buffer) == 0) {	/* hand a term_eof (usually CTRL-D) directly to command */ 
	    char *sent_EOF = mysavestring("?");
	    *sent_EOF = term_eof;
	    put_in_output_queue(sent_EOF);
	    we_just_got_a_signal_or_EOF = TRUE;
	    free(sent_EOF);
	  }	
	  else {
	    rl_stuff_char(byte_read);  /* stuff it back in readline's input queue */
	    DPRINTF0(DEBUG_TERMIO, "passing it to readline");	
	    DPRINTF2(DEBUG_READLINE, "rl_callback_read_char() (_rl_eof_char=%d, term_eof=%d)", _rl_eof_char, term_eof);
	    rl_callback_read_char();
	  }
	}
      }
    
      /* -------------------------- write pty --------------------------------- */
      if (FD_ISSET(master_pty_fd, &writefds)) {
	flush_output_queue();
	yield(); /*  give  slave command time to respond. If we don't do this,
		     nothing bad will happen, but the "dialogue" on screen will be
		     out of order   */
      }
    }				/* if (ndfs > 0)         */
  }				/* while (1)             */
}				/* void main_loop()      */
Beispiel #14
0
/*
  Given the actual data set <dataSet>, estimates the values for
  algorithm parameters that would give the optimal running time of a
  query. 

  The set <sampleQueries> is a set with query sample points
  (R-NN DS's parameters are optimized for query points from the set
  <sampleQueries>). <sampleQueries> could be a sample of points from the
  actual query set or from the data set. When computing the estimated
  number of collisions of a sample query point <q> with the data set
  points, if there is a point in the data set with the same pointer
  with <q> (that is when <q> is a data set point), then the
  corresponding point (<q>) is not considered in the data set (for the
  purpose of computing the respective #collisions estimation).

  The return value is the estimate of the optimal parameters.
*/
RNNParametersT computeOptimalParameters(RealT R, 
					RealT successProbability, 
					IntT nPoints, 
					IntT dimension, 
					PPointT *dataSet, 
					IntT nSampleQueries, 
					PPointT *sampleQueries, 
					MemVarT memoryUpperBound){
  ASSERT(nSampleQueries > 0);

  initializeLSHGlobal();

  RNNParametersT optParameters;
  optParameters.successProbability = successProbability;
  optParameters.dimension = dimension;
  optParameters.parameterR = R;
#ifdef USE_L1_DISTANCE
  optParameters.parameterR2 = R;
#else  
  optParameters.parameterR2 = SQR(R);
#endif
  optParameters.useUfunctions = TRUE; // TODO: could optimize here:
				      // maybe sometimes, the old way
				      // was better.
  optParameters.parameterW = PARAMETER_W_DEFAULT;
  optParameters.parameterT = nPoints;
  optParameters.typeHT = HT_HYBRID_CHAINS;
  
  // Compute the run-time parameters (timings of different parts of the algorithm).
  IntT nReps = 10; // # number of repetions
  RealT lshPrecomp = 0, uhashOver = 0, distComp = 0;
  for(IntT i = 0; i < nReps; i++){
    RealT lP, uO, dC;
    determineRTCoefficients(optParameters.parameterR, 
			    optParameters.successProbability, 
			    optParameters.useUfunctions, 
			    optParameters.typeHT, 
			    optParameters.dimension, 
			    nPoints, 
			    dataSet, 
			    lP, 
			    uO, 
			    dC);
    lshPrecomp += lP;
    uhashOver += uO;
    distComp += dC;
    DPRINTF4("Coefs: lP = %0.9lf\tuO = %0.9lf\tdC = %0.9lf\n", lP, uO, dC);
  }
  lshPrecomp /= nReps;
  uhashOver /= nReps;
  distComp /= nReps;
  DPRINTF("Coefs (final): lshPrecomp = %0.9lf\n", lshPrecomp);
  DPRINTF("Coefs (final): uhashOver = %0.9lf\n", uhashOver);
  DPRINTF("Coefs (final): distComp = %0.9lf\n", distComp);
  DPRINTF("Remaining memory: %lld\n", memoryUpperBound);

  // Try all possible <k>s and choose the one for which the time
  // estimate of a query is minimal.
  IntT k;
  RealT timeLSH, timeUH, timeCycling;
  //IntT queryIndex = genRandomInt(0, nPoints);
  //PPointT query = dataSet[queryIndex]; // query points = a random points from the data set.
  IntT bestK = 0;
  RealT bestTime = 0;
  for(k = 2; ; k += 2){

    DPRINTF("ST. k = %d\n", k);
    IntT m = computeMForULSH(k, successProbability);
    IntT L = m * (m-1) / 2;
    //DPRINTF("Available memory: %lld\n", getAvailableMemory());
    if (L * nPoints > memoryUpperBound / 12){
      break;
    }
    timeLSH = m * k * lshPrecomp;
    timeUH = L * uhashOver;
    //RealT nCollisions = estimateNCollisionsFromDSPoint(nPoints, dimension, dataSet, queryIndex, k, L, R);

    // Compute the mean number of collisions for the points from the sample query set.
    RealT nCollisions = 0;
    for(IntT i = 0; i < nSampleQueries; i++){
      nCollisions += estimateNDistinctCollisions(nPoints, dimension, dataSet, sampleQueries[i], TRUE, k, m, R);
    }
    nCollisions /= nSampleQueries;

    timeCycling = nCollisions * distComp;
    DPRINTF3("ST.m=%d L=%d \n", m, L);
    DPRINTF("ST.Estimated # distinct collisions = %0.6lf\n", (double)nCollisions);
    DPRINTF("ST.TimeLSH = %0.6lf\n", timeLSH);
    DPRINTF("ST.TimeUH = %0.6lf\n", timeUH);
    DPRINTF("ST.TimeCycling = %0.6lf\n", timeCycling);
    DPRINTF("ST.Sum = %0.6lf\n", timeLSH + timeUH + timeCycling);
    if (bestK == 0 || (timeLSH + timeUH + timeCycling) < bestTime) {
      bestK = k;
      bestTime = timeLSH + timeUH + timeCycling;
    }
    ASSERT(k < 100); //  otherwise, k reached 100 -- which, from
    //  experience, should never happen for reasonable
    //  data set & available memory amount.
  }


  DPRINTF("STO.Optimal k = %d\n", bestK);
  IntT m = computeMForULSH(bestK, successProbability);
  IntT L = m * (m-1) / 2;
  timeLSH = m * bestK * lshPrecomp;
  timeUH = L * uhashOver;
  
  // Compute the mean number of collisions for the points from the sample query set.
  RealT nCollisions = 0;
  for(IntT i = 0; i < nSampleQueries; i++){
    nCollisions += estimateNDistinctCollisions(nPoints, dimension, dataSet, sampleQueries[i], TRUE, k, m, R);
  }
  nCollisions /= nSampleQueries;

  // timeCycling = estimateNCollisionsFromDSPoint(nPoints, dimension, dataSet, queryIndex, bestK, L, R) * distComp;
  timeCycling = nCollisions * distComp;
  DPRINTF("STO.TimeLSH = %0.6lf\n", timeLSH);
  DPRINTF("STO.TimeUH = %0.6lf\n", timeUH);
  DPRINTF("STO.TimeCycling = %0.6lf\n", timeCycling);
  DPRINTF("STO.Sum = %0.6lf\n", timeLSH + timeUH + timeCycling);
  
  optParameters.parameterK = bestK;
  optParameters.parameterM = m;
  optParameters.parameterL = L;

  return optParameters;
}