void newclient(int c) { char request[1024]; int n; unsigned int start; char *reply; extern char *pwcheck(); start = 0; while (start < sizeof(request) - 1) { n = read(c, request+start, sizeof(request) - 1 - start); if (n < 1) { reply = "Error reading request"; goto sendreply; } start += n; if (request[start-1] == '\0' && strlen(request) < start) { break; } } if (start >= sizeof(request) - 1) { reply = "Request too big"; } else { reply = pwcheck(request, request + strlen(request) + 1); } sendreply: retry_write(c, reply, strlen(reply)); close(c); }
void testrunner_t::_check(int pass, const char *file, int line, const char *fmt, ...) { va_list args; char buf[STATUS_LEN]; /* build a status line. 1st char is a code which * is interpreted in run_test() above. */ snprintf(buf, sizeof(buf)-2, "%c%s:%d: %s: ", (pass ? '+' : '-'), file, line, (pass ? "passed" : "FAILED")); va_start(args, fmt); vsnprintf(buf+strlen(buf), sizeof(buf)-2-strlen(buf), fmt, args); va_end(args); strcat(buf, "\n"); if (current_->verbose_) fputs(buf+1, stderr); if (!pass) { fflush(stderr); if (status_pipe >= 0) retry_write(status_pipe, buf, strlen(buf)); abort(); /*NOTREACHED*/ } }
static void sync_log_base(const char *channel, const char *string) { int fd; struct stat sbuffile, sbuffd; int retries = 0; const char *fname; /* are we being supressed? */ if (!sync_log_enabled(channel)) return; fname = sync_log_fname(channel); while (retries++ < SYNC_LOG_RETRIES) { fd = open(fname, O_WRONLY|O_APPEND|O_CREAT, 0640); if (fd < 0 && errno == ENOENT) { if (!cyrus_mkdir(fname, 0755)) { fd = open(fname, O_WRONLY|O_APPEND|O_CREAT, 0640); } } if (fd < 0) { syslog(LOG_ERR, "sync_log(): Unable to write to log file %s: %s", fname, strerror(errno)); return; } if (lock_blocking(fd, fname) == -1) { syslog(LOG_ERR, "sync_log(): Failed to lock %s for %s: %m", fname, string); xclose(fd); return; } /* Check that the file wasn't renamed after it was opened above */ if ((fstat(fd, &sbuffd) == 0) && (stat(fname, &sbuffile) == 0) && (sbuffd.st_ino == sbuffile.st_ino)) break; lock_unlock(fd, fname); xclose(fd); } if (retries >= SYNC_LOG_RETRIES) { xclose(fd); syslog(LOG_ERR, "sync_log(): Failed to lock %s for %s after %d attempts", fname, string, retries); return; } if (retry_write(fd, string, strlen(string)) < 0) syslog(LOG_ERR, "write() to %s failed: %s", fname, strerror(errno)); (void)fsync(fd); /* paranoia */ lock_unlock(fd, fname); xclose(fd); }
/* * shareinput_writer_notifyready * * Called by the writer (producer) once it is done producing all tuples and * writing them to disk. It notifies all the readers (consumers) that tuples * are ready to be read from disk. * * For planner-generated plans we wait for acks from all the readers before * proceedings. It is a blocking operation. * * For optimizer-generated plans we don't wait for acks, we proceed immediately. * It is a non-blocking operation. */ void * shareinput_writer_notifyready(int share_id, int xslice, PlanGenerator planGen) { int n; ShareInput_Lk_Context *pctxt = gp_malloc(sizeof(ShareInput_Lk_Context)); if(!pctxt) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Shareinput Writer failed: out of memory"))); pctxt->readyfd = -1; pctxt->donefd = -1; pctxt->zcnt = 0; pctxt->del_ready = false; pctxt->del_done = false; pctxt->lkname_ready[0] = '\0'; pctxt->lkname_done[0] = '\0'; RegisterXactCallbackOnce(XCallBack_ShareInput_FIFO, pctxt); sisc_lockname(pctxt->lkname_ready, MAXPGPATH, share_id, "ready"); create_tmp_fifo(pctxt->lkname_ready); pctxt->del_ready = true; pctxt->readyfd = open(pctxt->lkname_ready, O_RDWR, 0600); if(pctxt->readyfd < 0) elog(ERROR, "could not open fifo \"%s\": %m", pctxt->lkname_ready); sisc_lockname(pctxt->lkname_done, MAXPGPATH, share_id, "done"); create_tmp_fifo(pctxt->lkname_done); pctxt->del_done = true; pctxt->donefd = open(pctxt->lkname_done, O_RDWR, 0600); if(pctxt->donefd < 0) elog(ERROR, "could not open fifo \"%s\": %m", pctxt->lkname_done); for(n=0; n<xslice; ++n) { #if USE_ASSERT_CHECKING int rwsize = #endif retry_write(pctxt->readyfd, "a", 1); Assert(rwsize == 1); } elog(DEBUG1, "SISC WRITER (shareid=%d, slice=%d): wrote notify_ready to %d xslice readers", share_id, currentSliceId, xslice); if (planGen == PLANGEN_PLANNER) { /* For planner-generated plans, we wait for acks from all the readers */ writer_wait_for_acks(pctxt, share_id, xslice); } return (void *) pctxt; }
/* * shareinput_reader_notifydone * * Called by the reader (consumer) to notify the writer (producer) that * it is done reading tuples from disk. * * This is a non-blocking operation. */ void shareinput_reader_notifydone(void *ctxt, int share_id) { ShareInput_Lk_Context *pctxt = (ShareInput_Lk_Context *) ctxt; #if USE_ASSERT_CHECKING int rwsize = #endif retry_write(pctxt->donefd, "z", 1); Assert(rwsize == 1); UnregisterXactCallbackOnce(XCallBack_ShareInput_FIFO, (void *) ctxt); shareinput_clean_lk_ctxt(pctxt); }
EXPORTED ssize_t mappedfile_pwrite(struct mappedfile *mf, const void *base, size_t len, off_t offset) { ssize_t written; off_t pos; assert(mf->is_rw); assert(mf->fd != -1); assert(base); if (!len) return 0; /* nothing to write! */ /* XXX - memcmp and don't both writing if it matches? */ mf->dirty++; /* locate the file handle */ pos = lseek(mf->fd, offset, SEEK_SET); if (pos < 0) { syslog(LOG_ERR, "IOERROR: %s seek to %llX: %m", mf->fname, (long long unsigned int)offset); return -1; } /* write the buffer */ written = retry_write(mf->fd, base, len); if (written < 0) { syslog(LOG_ERR, "IOERROR: %s write %llu bytes at %llX: %m", mf->fname, (long long unsigned int)len, (long long unsigned int)offset); return -1; } _ensure_mapped(mf, pos+written, /*update*/1); return written; }
void testrunner_t::run_test(testfn_t *fn) { running_ = fn; nrun_++; int pipefd[2]; if (pipe(pipefd) < 0) { perror("pipe"); return; } dmsg("Forking"); pid_t pid = fork(); if (pid < 0) { perror("fork"); close(pipefd[PIPE_READ]); close(pipefd[PIPE_WRITE]); running_ = 0; return; } if (pid == 0) { /* child process - return and run the test code, dtor will exit. */ dmsg("In child process"); close(pipefd[PIPE_READ]); /* record the write end of the status pipe for _check() */ status_pipe = pipefd[PIPE_WRITE]; /* run the fixtures and test function */ fn->run(); /* send a success message */ char buf[STATUS_LEN]; snprintf(buf, sizeof(buf), "+PASS %s.%s", fn->suite(), fn->name()); retry_write(status_pipe, buf, strlen(buf)); dmsg("Child process exiting normally"); exit(0); } else { /* parent process - read status and wait for the child to finish */ dmsg("In parent process"); close(pipefd[PIPE_WRITE]); /* we expect at most one status line, from either a * _check() failure or a successful test. */ char buf[STATUS_LEN]; if (read_status(buf, sizeof(buf), pipefd[PIPE_READ]) < 0) { running_ = 0; return; } close(pipefd[PIPE_READ]); /* wait the for child process to exit */ int r = wait_for_child(pid); /* diagnose test failure */ if (r < 0 && r != -ESRCH) { running_ = 0; return; } if (r == 0 && buf[0] == '+') { fprintf(stderr, "PASS %s.%s\n", fn->suite(), fn->name()); npass_++; } else if (buf[0] != '\0') { fprintf(stderr, "Test %s.%s failed:\n", fn->suite(), fn->name()); fputs(buf+1, stderr); } } running_ = 0; }
/* create a downgraded index file in cyrus.index. We don't copy back * expunged messages, sorry */ static int dump_index(struct mailbox *mailbox, int oldversion, struct seqset *expunged_seq, int first, int sync, struct protstream *pin, struct protstream *pout) { char oldname[MAX_MAILBOX_PATH]; const char *fname; int oldindex_fd = -1; indexbuffer_t headerbuf; indexbuffer_t recordbuf; char *hbuf = (char *)headerbuf.buf; char *rbuf = (char *)recordbuf.buf; int header_size; int record_size; int n, r; if (oldversion == 6) { header_size = 76; record_size = 60; } else if (oldversion == 7) { header_size = 76; record_size = 72; } else if (oldversion == 8) { header_size = 92; record_size = 80; } else if (oldversion == 9) { header_size = 96; record_size = 80; } else if (oldversion == 10) { header_size = 96; record_size = 88; } else { return IMAP_MAILBOX_BADFORMAT; } fname = mailbox_meta_fname(mailbox, META_INDEX); snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname); oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666); if (oldindex_fd == -1) goto fail; downgrade_header(&mailbox->i, hbuf, oldversion, header_size, record_size); /* Write header - everything we'll say */ n = retry_write(oldindex_fd, hbuf, header_size); if (n == -1) goto fail; struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_UNLINKED); const message_t *msg; while ((msg = mailbox_iter_step(iter))) { const struct index_record *record = msg_record(msg); /* we have to make sure expunged records don't get the * file copied, or a reconstruct could bring them back * to life! It we're not creating an expunged file... */ if (record->system_flags & FLAG_EXPUNGED) { if (oldversion < 9) seqset_add(expunged_seq, record->uid, 1); continue; } /* not making sure exists matches, we do trust a bit */ downgrade_record(record, rbuf, oldversion); n = retry_write(oldindex_fd, rbuf, record_size); if (n == -1) goto fail; } mailbox_iter_done(&iter); close(oldindex_fd); r = dump_file(first, sync, pin, pout, oldname, "cyrus.index", NULL, 0); unlink(oldname); if (r) return r; /* create cyrus.expunge */ if (oldversion > 8 && mailbox->i.num_records > mailbox->i.exists) { int nexpunge = mailbox->i.num_records - mailbox->i.exists; fname = mailbox_meta_fname(mailbox, META_EXPUNGE); snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname); oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666); if (oldindex_fd == -1) goto fail; header_set_num_records(hbuf, nexpunge); /* Write header - everything we'll say */ n = retry_write(oldindex_fd, hbuf, header_size); if (n == -1) goto fail; iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_UNLINKED); while ((msg = mailbox_iter_step(iter))) { const struct index_record *record = msg_record(msg); /* ignore non-expunged records */ if (!(record->system_flags & FLAG_EXPUNGED)) continue; downgrade_record(record, rbuf, oldversion); n = retry_write(oldindex_fd, rbuf, record_size); if (n == -1) goto fail; } close(oldindex_fd); r = dump_file(first, sync, pin, pout, oldname, "cyrus.expunge", NULL, 0); unlink(oldname); if (r) return r; } return 0; fail: if (oldindex_fd != -1) close(oldindex_fd); unlink(oldname); return IMAP_IOERROR; }
/* * shareinput_reader_waitready * * Called by the reader (consumer) to wait for the writer (producer) to produce * all the tuples and write them to disk. * * This is a blocking operation. */ void * shareinput_reader_waitready(int share_id, PlanGenerator planGen) { mpp_fd_set rset; struct timeval tval; int n; char a; ShareInput_Lk_Context *pctxt = gp_malloc(sizeof(ShareInput_Lk_Context)); if(!pctxt) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Share input reader failed: out of memory"))); pctxt->readyfd = -1; pctxt->donefd = -1; pctxt->zcnt = 0; pctxt->del_ready = false; pctxt->del_done = false; pctxt->lkname_ready[0] = '\0'; pctxt->lkname_done[0] = '\0'; RegisterXactCallbackOnce(XCallBack_ShareInput_FIFO, pctxt); sisc_lockname(pctxt->lkname_ready, MAXPGPATH, share_id, "ready"); create_tmp_fifo(pctxt->lkname_ready); pctxt->readyfd = open(pctxt->lkname_ready, O_RDWR, 0600); if(pctxt->readyfd < 0) elog(ERROR, "could not open fifo \"%s\": %m", pctxt->lkname_ready); sisc_lockname(pctxt->lkname_done, MAXPGPATH, share_id, "done"); create_tmp_fifo(pctxt->lkname_done); pctxt->donefd = open(pctxt->lkname_done, O_RDWR, 0600); if(pctxt->donefd < 0) elog(ERROR, "could not open fifo \"%s\": %m", pctxt->lkname_done); while(1) { CHECK_FOR_INTERRUPTS(); MPP_FD_ZERO(&rset); MPP_FD_SET(pctxt->readyfd, &rset); tval.tv_sec = 1; tval.tv_usec = 0; n = select(pctxt->readyfd+1, (fd_set *) &rset, NULL, NULL, &tval); if(n==1) { #if USE_ASSERT_CHECKING int rwsize = #endif retry_read(pctxt->readyfd, &a, 1); Assert(rwsize == 1 && a == 'a'); elog(DEBUG1, "SISC READER (shareid=%d, slice=%d): Wait ready got writer's handshake", share_id, currentSliceId); if (planGen == PLANGEN_PLANNER) { /* For planner-generated plans, we send ack back after receiving the handshake */ elog(DEBUG1, "SISC READER (shareid=%d, slice=%d): Wait ready writing ack back to writer", share_id, currentSliceId); #if USE_ASSERT_CHECKING rwsize = #endif retry_write(pctxt->donefd, "b", 1); Assert(rwsize == 1); } break; } else if(n==0) { elog(DEBUG1, "SISC READER (shareid=%d, slice=%d): Wait ready time out once", share_id, currentSliceId); } else { int save_errno = errno; elog(LOG, "SISC READER (shareid=%d, slice=%d): Wait ready try again, errno %d ... ", share_id, currentSliceId, save_errno); } } return (void *) pctxt; }
/* create a downgraded index file in cyrus.index. We don't copy back * expunged messages, sorry */ static int dump_index(struct mailbox *mailbox, int oldversion, struct seqset *expunged_seq, int first, int sync, struct protstream *pin, struct protstream *pout) { char oldname[MAX_MAILBOX_PATH]; const char *fname; int oldindex_fd = -1; indexbuffer_t headerbuf; indexbuffer_t recordbuf; char *hbuf = (char *)headerbuf.buf; char *rbuf = (char *)recordbuf.buf; int header_size; int record_size; int n, r; struct index_record record; unsigned recno; if (oldversion == 6) { header_size = 76; record_size = 60; } else if (oldversion == 7) { header_size = 76; record_size = 72; } else if (oldversion == 8) { header_size = 92; record_size = 80; } else if (oldversion == 9) { header_size = 96; record_size = 80; } else if (oldversion == 10) { header_size = 96; record_size = 88; } else { return IMAP_MAILBOX_BADFORMAT; } fname = mailbox_meta_fname(mailbox, META_INDEX); snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname); oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666); if (oldindex_fd == -1) goto fail; downgrade_header(&mailbox->i, hbuf, oldversion, header_size, record_size); /* Write header - everything we'll say */ n = retry_write(oldindex_fd, hbuf, header_size); if (n == -1) goto fail; for (recno = 1; recno <= mailbox->i.num_records; recno++) { if (mailbox_read_index_record(mailbox, recno, &record)) goto fail; /* we don't care about unlinked records at all */ if (record.system_flags & FLAG_UNLINKED) continue; /* we have to make sure expunged records don't get the * file copied, or a reconstruct could bring them back * to life! It we're not creating an expunged file... */ if (record.system_flags & FLAG_EXPUNGED) { if (oldversion < 9) seqset_add(expunged_seq, record.uid, 1); continue; } /* not making sure exists matches, we do trust a bit */ downgrade_record(&record, rbuf, oldversion); n = retry_write(oldindex_fd, rbuf, record_size); if (n == -1) goto fail; } close(oldindex_fd); r = dump_file(first, sync, pin, pout, oldname, "cyrus.index"); unlink(oldname); if (r) return r; /* create cyrus.expunge */ if (oldversion > 8 && mailbox->i.num_records > mailbox->i.exists) { int nexpunge = mailbox->i.num_records - mailbox->i.exists; fname = mailbox_meta_fname(mailbox, META_EXPUNGE); snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname); oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666); if (oldindex_fd == -1) goto fail; *((bit32 *)(hbuf+OFFSET_NUM_RECORDS)) = htonl(nexpunge); /* Write header - everything we'll say */ n = retry_write(oldindex_fd, hbuf, header_size); if (n == -1) goto fail; for (recno = 1; recno <= mailbox->i.num_records; recno++) { if (mailbox_read_index_record(mailbox, recno, &record)) goto fail; /* ignore non-expunged records */ if (!(record.system_flags & FLAG_EXPUNGED)) continue; downgrade_record(&record, rbuf, oldversion); n = retry_write(oldindex_fd, rbuf, record_size); if (n == -1) goto fail; } close(oldindex_fd); r = dump_file(first, sync, pin, pout, oldname, "cyrus.expunge"); unlink(oldname); if (r) return r; } return 0; fail: if (oldindex_fd != -1) close(oldindex_fd); unlink(oldname); return IMAP_IOERROR; }
static void memory_out () { retry_write (2, "virtual memory exhausted\n", 25); exit (1); }