trace_file_drv.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 638 行 · 第 1/2 页

C
638
字号
    data->buff_pos = 0;    data->wrap = wrap;    if (first_data) {	data->prev = first_data->prev;	first_data->prev = data;    } else	data->prev = NULL;    data->next = first_data;    first_data = data;    if (wrap && wrap->time > 0)	driver_set_timer(port, wrap->time);    return (ErlDrvData) data;}/*** Close a port*/static void trace_file_stop(ErlDrvData handle){    close_unlink_port((TraceFileData *) handle);}/*** Data sent from erlang to port.*/static void trace_file_output(ErlDrvData handle, char *buff, int bufflen){    int heavy = 0;    TraceFileData *data = (TraceFileData *) handle;    unsigned char b[5] = "";    put_be((unsigned) bufflen, b + 1);    switch (my_write(data, b, sizeof(b))) {    case 1:	heavy = !0;    case 0:	switch (my_write(data, buff, bufflen)) {	case 1:	    heavy = !0;	case 0:	    break;	case -1:	    driver_failure_posix(data->port, errno); /* XXX */	    return;	}	break;    case -1:	driver_failure_posix(data->port, errno); /* XXX */	return;    }    if (data->wrap) {	TraceFileWrapData *wrap = data->wrap;	/* Size limited wrapping log files */	wrap->len += sizeof(b) + bufflen;	if (wrap->time == 0 && wrap->len >= wrap->size) {	    if (wrap_file(data) < 0) {		driver_failure_posix(data->port, errno); /* XXX */		return;	    }	    heavy = !0;	}    }    if (heavy) {	set_port_control_flags(data->port, PORT_CONTROL_FLAG_HEAVY);    }}/*** Control message from erlang, we handle $f, which is flush.*/static int trace_file_control(ErlDrvData handle, unsigned int command, 			      char* buff, int count, 			      char** res, int res_size){    if (command == 'f') {	TraceFileData *data = (TraceFileData *) handle;	if (my_flush(data) < 0) {	    driver_failure_posix(data->port, errno); /* XXX */	}	if (res_size < 1) {	    *res = my_alloc(1);	}	**res = '\0';	return 1;    }     return -1;}/*** Timeout from driver_set_timer.*/static void trace_file_timeout(ErlDrvData handle) {    TraceFileData *data = (TraceFileData *) handle;    if (data->wrap) {	if (wrap_file(data) < 0) {	    driver_failure_posix(data->port, errno); /* XXX */	    return;	} else {	    driver_set_timer(data->port, data->wrap->time);	}    }}/*** Driver unloaded*/static void trace_file_finish(void){    while (first_data != NULL) {	close_unlink_port(first_data);    }}/*** Internal helpers*//* Calculate needed number of digits in filename counter.**/static unsigned digits(unsigned n) {    unsigned m, i;    for (m = 10, i = 1;  n >= m;  i++, m *= 10) ;    return i;}/*** Increment filename.**** The filename counter counts "0"-"9","10"-"19"..."[n->n]","0"...,** but also "","0" which is used for initialization.*/static void next_name(TraceFileName *n) {    if (n->cnt >= n->n) {	n->cnt = 0;	/* Circular count from "[n->n]" to "0", or from "" to "0" */	memmove(&n->name[n->suffix+1], 		&n->name[n->tail], 		n->len+1 - n->tail); /* Including '\0' */	n->name[n->suffix] = '0';	n->len -= n->tail - n->suffix - 1;	n->tail = n->suffix + 1;    } else {	int i = n->tail;	n->cnt++;	do {	    i--;	    /* Increment from the end, 	     * '0'..'1', carry propagate forward */	    if (n->name[i] < '9') {		n->name[i]++;		return;	    } else		n->name[i] = '0';	} while (i > n->suffix);	/* Wrapped around from "99..99" to "00..00", 	 * need one more character */	memmove(&n->name[n->tail+1],		&n->name[n->tail],		n->len+1 - n->tail); /* Incl '\0' */	n->name[n->tail++] = '0';	n->name[n->suffix] = '1';	n->len++;    }}/*** Yet another malloc wrapper*/static void *my_alloc(size_t size) {    void *ret;    if ((ret = (void *) driver_alloc(size)) == NULL) {	/* May or may not work... */	fprintf(stderr, "Could not allocate %d bytes of memory in %s.",		(int) size, __FILE__);	exit(1);    }    return ret;}/*** A write wrapper that regards it as an error if not all data was written.*/static int do_write(FILETYPE fd, unsigned char *buff, int siz) {    int w = write(fd, buff, siz);    if (w != siz) {	if (w >= 0) {	    errno = ENOSPC;	}	return -1;    }    return siz;}/*** Returns 0 if write to cache, 1 i write to file, and -1 if write failed.*/static int my_write(TraceFileData *data, unsigned char *buff, int siz) {    int wrote, w;    if (data->buff_siz - data->buff_pos >= siz) {	memcpy(data->buff + data->buff_pos, buff, siz);	data->buff_pos += siz; 	return 0;    }        wrote = data->buff_siz - data->buff_pos;    memcpy(data->buff + data->buff_pos, buff, wrote);    if (do_write(data->fd, data->buff, data->buff_siz) < 0) {	return -1;    }    data->buff_pos = 0;    if (siz - wrote >= data->buff_siz) {	/* Write directly, no need to buffer... */	if (do_write(data->fd, buff + wrote, siz - wrote) < 0) {	    return -1;	}	return 1;    }     memcpy(data->buff, buff + wrote, siz - wrote);    data->buff_pos = siz - wrote;    set_port_control_flags(data->port, PORT_CONTROL_FLAG_HEAVY);    return 1;}/* ** Returns negative if it failed to write. */static int my_flush(TraceFileData *data){    if (do_write(data->fd, data->buff, data->buff_pos) < 0) {	return -1;    }    data->buff_pos = 0;    return 0;}/*** Write unsigned to buffer in big endian*/static void put_be(unsigned n, unsigned char *s){    s[0] = n >> 24;    s[1] = (n >> 16) & 0xFFFFU;    s[2] = (n >> 8) & 0xFFFFU;    s[3] = n & 0xFFFFU;}/*** Wrapper that only closes non-negative filehandles*/static void do_close(FILETYPE fd) {    if (fd != -1) {	close(fd);    }}/*** Close the whole port and clean up*/static void close_unlink_port(TraceFileData *data) {    my_flush(data);    do_close(data->fd);    if (data->next)	data->next->prev = data->prev;    if (data->prev)	data->prev->next = data->next;    else	first_data = data->next;    if (data->wrap)	driver_free(data->wrap);    driver_free(data);}/*** Wrap to new file - close the current, open a new and** perhaps delete a too old one**** Returns negative if something failed.*/static int wrap_file(TraceFileData *data) {    if (my_flush(data) < 0) {	close(data->fd);	data->fd = -1;	return -1;    }    close(data->fd);    data->fd = -1;    data->buff_pos = 0;    data->wrap->len = 0;    /* Count down before starting to remove old files */    if (data->wrap->cnt > 0)	data->wrap->cnt--;    if (data->wrap->cnt == 0) {	/* Remove an old file */	unlink(data->wrap->del.name);	next_name(&data->wrap->del);    }    next_name(&data->wrap->cur);    data->fd = open(data->wrap->cur.name, O_WRONLY | O_TRUNC | O_CREAT#ifdef O_BINARY	      | O_BINARY#endif	      , 0777);    if (data->fd < 0) {	data->fd = -1;	return -1;    }    return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?