void input_start_stdin(int fd) { if (read_stream) { return; } read_buffer = rbuffer_new(READ_BUFFER_SIZE); read_stream = rstream_new(read_cb, read_buffer, NULL); rstream_set_file(read_stream, fd); rstream_start(read_stream); }
// new a net pool struct net_pool* net_new() { struct net_pool* np = (struct net_pool*)malloc(sizeof(struct net_pool)); // get the eventfd np->eventfd = poll_create(); if(poll_invalid(np->eventfd)) { log_error("epoll create failure\n"); return NULL; } np->eventn = 0; np->eventindex = 0; np->allocid = 0; np->count = 0; np->cap = DEFAULT_SOCKET; // beforehand alloc an array as a container np->ns = (struct net_socket**)malloc(np->cap * sizeof(struct net_socket*)); // initialize the elements of array: alloc memory int i = 0; for(; i < np->cap; ++i) { np->ns[i] = (struct net_socket*)malloc(sizeof(struct net_socket)); memset(np->ns[i], 0, sizeof(struct net_socket)); np->ns[i]->rdsz = MIN_READ_BUFFER; np->ns[i]->wbuff = wbuffer_new(); np->ns[i]->rbuff = rbuffer_new(); } np->ud = NULL; // set signal to np net_set_sighandler(np); // np->prothandler = (map<int, PROTHANDLER>*)malloc(sizeof(map<int, PROTHANDLER>)) ; // map is a type of class, use new, call structure function np->prothandler = new map<int, PROTHANDLER>; np->onlineconnidtocharid = new map<int, int>; np->onlinecharidtoconnid = new map<int, int>; np->serverid = -1; return np; }
// expand the capacity static void net_expand(struct net_pool* np) { log_debug("net_expand ...\n"); int newcap = np->cap * 2; // new array for saving net socket's information struct net_socket** ns = (struct net_socket**)malloc(newcap * sizeof(struct net_socket*)); memset(ns, 0, newcap * sizeof(struct net_socket*)); int i = 0; // transplant the old data to new container for(; i < np->cap; ++i) { // in fact, np->ns[i]->id == i // use %, incase of spilling int nid = np->ns[i]->id % newcap; if(ns[nid] != NULL) { log_error("new net_socket error : %d", i); continue; } ns[nid] = np->ns[i]; } // malloc new container's data for(i = 0; i < newcap; ++i) { if(!ns[i]) { ns[i] = (struct net_socket*)malloc(sizeof(struct net_socket)); memset(ns[i], 0, sizeof(struct net_socket)); ns[i]->rdsz = MIN_READ_BUFFER; ns[i]->rbuff = rbuffer_new(); ns[i]->wbuff = wbuffer_new(); } } // free the old array free(np->ns); // set the new array np->ns = ns; // increse the cap np->cap = newcap; }
/// Tries to start a new job. /// /// @param[out] status The job id if the job started successfully, 0 if the job /// table is full, -1 if the program could not be executed. /// @return The job pointer if the job started successfully, NULL otherwise Job *job_start(JobOptions opts, int *status) { int i; Job *job; // Search for a free slot in the table for (i = 0; i < MAX_RUNNING_JOBS; i++) { if (table[i] == NULL) { break; } } if (i == MAX_RUNNING_JOBS) { // No free slots shell_free_argv(opts.argv); *status = 0; return NULL; } job = xmalloc(sizeof(Job)); // Initialize job->id = i + 1; *status = job->id; job->status = -1; job->refcount = 1; job->stopped_time = 0; job->term_sent = false; job->in = NULL; job->out = NULL; job->err = NULL; job->opts = opts; job->closed = false; process_init(job); if (opts.writable) { handle_set_job((uv_handle_t *)job->proc_stdin, job); job->refcount++; } if (opts.stdout_cb) { handle_set_job((uv_handle_t *)job->proc_stdout, job); job->refcount++; } if (opts.stderr_cb) { handle_set_job((uv_handle_t *)job->proc_stderr, job); job->refcount++; } // Spawn the job if (!process_spawn(job)) { if (opts.writable) { uv_close((uv_handle_t *)job->proc_stdin, close_cb); } if (opts.stdout_cb) { uv_close((uv_handle_t *)job->proc_stdout, close_cb); } if (opts.stderr_cb) { uv_close((uv_handle_t *)job->proc_stderr, close_cb); } process_close(job); event_poll(0); // Manually invoke the close_cb to free the job resources *status = -1; return NULL; } if (opts.writable) { job->in = wstream_new(opts.maxmem); wstream_set_stream(job->in, job->proc_stdin); } // Start the readable streams if (opts.stdout_cb) { job->out = rstream_new(read_cb, rbuffer_new(JOB_BUFFER_SIZE), job); rstream_set_stream(job->out, job->proc_stdout); rstream_start(job->out); } if (opts.stderr_cb) { job->err = rstream_new(read_cb, rbuffer_new(JOB_BUFFER_SIZE), job); rstream_set_stream(job->err, job->proc_stderr); rstream_start(job->err); } // Save the job to the table table[i] = job; return job; }
void input_init(void) { input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN); }
/// Tries to start a new job. /// /// @param argv Argument vector for the process. The first item is the /// executable to run. /// @param data Caller data that will be associated with the job /// @param stdout_cb Callback that will be invoked when data is available /// on stdout /// @param stderr_cb Callback that will be invoked when data is available /// on stderr /// @param job_exit_cb Callback that will be invoked when the job exits /// @param maxmem Maximum amount of memory used by the job WStream /// @param[out] status The job id if the job started successfully, 0 if the job /// table is full, -1 if the program could not be executed. /// @return The job pointer if the job started successfully, NULL otherwise Job *job_start(char **argv, void *data, rstream_cb stdout_cb, rstream_cb stderr_cb, job_exit_cb job_exit_cb, size_t maxmem, int *status) { int i; Job *job; // Search for a free slot in the table for (i = 0; i < MAX_RUNNING_JOBS; i++) { if (table[i] == NULL) { break; } } if (i == MAX_RUNNING_JOBS) { // No free slots *status = 0; return NULL; } job = xmalloc(sizeof(Job)); // Initialize job->id = i + 1; *status = job->id; job->status = -1; job->pending_refs = 3; job->pending_closes = 4; job->data = data; job->stdout_cb = stdout_cb; job->stderr_cb = stderr_cb; job->exit_cb = job_exit_cb; job->stopped = false; job->exit_timeout = EXIT_TIMEOUT; job->proc_opts.file = argv[0]; job->proc_opts.args = argv; job->proc_opts.stdio = job->stdio; job->proc_opts.stdio_count = 3; job->proc_opts.flags = UV_PROCESS_WINDOWS_HIDE; job->proc_opts.exit_cb = exit_cb; job->proc_opts.cwd = NULL; job->proc_opts.env = NULL; job->proc.data = NULL; job->proc_stdin.data = NULL; job->proc_stdout.data = NULL; job->proc_stderr.data = NULL; // Initialize the job std{in,out,err} uv_pipe_init(uv_default_loop(), &job->proc_stdin, 0); job->stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; job->stdio[0].data.stream = (uv_stream_t *)&job->proc_stdin; uv_pipe_init(uv_default_loop(), &job->proc_stdout, 0); job->stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; job->stdio[1].data.stream = (uv_stream_t *)&job->proc_stdout; uv_pipe_init(uv_default_loop(), &job->proc_stderr, 0); job->stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; job->stdio[2].data.stream = (uv_stream_t *)&job->proc_stderr; // Give all handles a reference to the job handle_set_job((uv_handle_t *)&job->proc, job); handle_set_job((uv_handle_t *)&job->proc_stdin, job); handle_set_job((uv_handle_t *)&job->proc_stdout, job); handle_set_job((uv_handle_t *)&job->proc_stderr, job); // Spawn the job if (uv_spawn(uv_default_loop(), &job->proc, &job->proc_opts) != 0) { free_job(job); *status = -1; return NULL; } job->in = wstream_new(maxmem); wstream_set_stream(job->in, (uv_stream_t *)&job->proc_stdin); // Start the readable streams job->out = rstream_new(read_cb, rbuffer_new(JOB_BUFFER_SIZE), job); job->err = rstream_new(read_cb, rbuffer_new(JOB_BUFFER_SIZE), job); rstream_set_stream(job->out, (uv_stream_t *)&job->proc_stdout); rstream_set_stream(job->err, (uv_stream_t *)&job->proc_stderr); rstream_start(job->out); rstream_start(job->err); // Save the job to the table table[i] = job; // Start polling job status if this is the first if (job_count == 0) { uv_prepare_start(&job_prepare, job_prepare_cb); } job_count++; return job; }