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 + -
显示快捷键?