* Process data received through the syslogger pipe. * * This routine interprets the log pipe protocol which sends log messages as * (hopefully atomic) chunks - such chunks are detected and reassembled here. * * The protocol has a header that starts with two nul bytes, then has a 16 bit * length, the pid of the sending process, and a flag to indicate if it is * the last chunk in a message. I
| 1468 | * logbuffer, and *bytes_in_logbuffer is updated. |
| 1469 | */ |
| 1470 | static void |
| 1471 | process_pipe_input(char *logbuffer, int *bytes_in_logbuffer) |
| 1472 | { |
| 1473 | char *cursor = logbuffer; |
| 1474 | int count = *bytes_in_logbuffer; |
| 1475 | int dest = LOG_DESTINATION_STDERR; |
| 1476 | |
| 1477 | /* While we have enough for a header, process data... */ |
| 1478 | while (count >= sizeof(PipeProtoHeader)) |
| 1479 | { |
| 1480 | PipeProtoHeader p; |
| 1481 | int chunklen; |
| 1482 | |
| 1483 | /* Do we have a valid header? */ |
| 1484 | memcpy(&p, cursor, PIPE_HEADER_SIZE); |
| 1485 | if (chunk_is_postgres_chunk(&p)) |
| 1486 | { |
| 1487 | List *buffer_list; |
| 1488 | ListCell *cell; |
| 1489 | save_buffer *existing_slot = NULL, |
| 1490 | *free_slot = NULL; |
| 1491 | StringInfo str; |
| 1492 | |
| 1493 | chunklen = PIPE_HEADER_SIZE + p.len; |
| 1494 | |
| 1495 | /* Fall out of loop if we don't have the whole chunk yet */ |
| 1496 | if (count < chunklen) |
| 1497 | break; |
| 1498 | |
| 1499 | dest = (p.log_format == 'c' || p.log_format == 'f') ? |
| 1500 | LOG_DESTINATION_CSVLOG : LOG_DESTINATION_STDERR; |
| 1501 | |
| 1502 | /* Locate any existing buffer for this source pid */ |
| 1503 | buffer_list = buffer_lists[p.pid % NBUFFER_LISTS]; |
| 1504 | foreach(cell, buffer_list) |
| 1505 | { |
| 1506 | save_buffer *buf = (save_buffer *) lfirst(cell); |
| 1507 | |
| 1508 | /* |
| 1509 | * Different threads in the same process may write |
| 1510 | * log messages concurrently. The chunk messages |
| 1511 | * should be treat differently. |
| 1512 | */ |
| 1513 | if (buf->pid == p.pid && buf->tid == p.thid) |
| 1514 | { |
| 1515 | existing_slot = buf; |
| 1516 | break; |
| 1517 | } |
| 1518 | if (buf->pid == 0 && free_slot == NULL) |
| 1519 | free_slot = buf; |
| 1520 | } |
| 1521 | |
| 1522 | if (p.is_last == 'f' || p.is_last == 'F') |
| 1523 | { |
| 1524 | /* |
| 1525 | * Save a complete non-final chunk in a per-pid buffer |
| 1526 | */ |
| 1527 | if (existing_slot != NULL) |