static void free_refreshCheckState(void *data) { refreshCheckState *state = data; storeUnlockObject(state->entry); cbdataUnlock(state->callback_data); cbdataUnlock(state->def); }
static void free_externalAclState(void *data) { externalAclState *state = data; safe_free(state->key); cbdataUnlock(state->callback_data); cbdataUnlock(state->def); }
static void externalAclHandleReply(void *data, char *reply) { externalAclState *state = data; externalAclState *next; int result = 0; char *status; char *token; char *value; char *t; char *user = NULL; char *error = NULL; external_acl_entry *entry = NULL; debug(82, 2) ("externalAclHandleReply: reply=\"%s\"\n", reply); if (reply) { status = strwordtok(reply, &t); if (status && strcmp(status, "OK") == 0) result = 1; while ((token = strwordtok(NULL, &t))) { value = strchr(token, '='); if (value) { *value++ = '\0'; /* terminate the token, and move up to the value */ if (strcmp(token, "user") == 0) user = value; else if (strcmp(token, "error") == 0) error = value; } } } dlinkDelete(&state->list, &state->def->queue); if (cbdataValid(state->def)) { if (reply) entry = external_acl_cache_add(state->def, state->key, result, user, error); else { external_acl_entry *oldentry = hash_lookup(state->def->cache, state->key); if (oldentry) external_acl_cache_delete(state->def, oldentry); } } do { cbdataUnlock(state->def); state->def = NULL; if (cbdataValid(state->callback_data)) state->callback(state->callback_data, entry); cbdataUnlock(state->callback_data); state->callback_data = NULL; next = state->queue; cbdataFree(state); state = next; } while (state); }
static void storeAufsIOCallback(storeIOState * sio, int errflag) { STIOCB *callback = sio->callback; void *their_data = sio->callback_data; squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate; int fd = aiostate->fd; debug(79, 3) ("storeAufsIOCallback: errflag=%d\n", errflag); sio->callback = NULL; sio->callback_data = NULL; debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); if (callback) if (NULL == their_data || cbdataValid(their_data)) callback(their_data, errflag, sio); debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); cbdataUnlock(their_data); aiostate->fd = -1; if (aiostate->flags.opening) Opening_FD--; cbdataFree(sio); if (fd < 0) return; debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); #if ASYNC_CLOSE fd_close(fd); aioClose(fd); #else aioCancel(fd); file_close(fd); #endif store_open_disk_fd--; statCounter.syscalls.disk.closes++; debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); }
static void storeClientCopy2(StoreEntry * e, store_client * sc) { if (sc->flags.copy_event_pending) return; if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { debug(20, 5) ("storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set\n"); return; } if (sc->flags.store_copying) { sc->flags.copy_event_pending = 1; debug(20, 3) ("storeClientCopy2: Queueing storeClientCopyEvent()\n"); eventAdd("storeClientCopyEvent", storeClientCopyEvent, sc, 0.0, 0); return; } cbdataLock(sc); /* ick, prevent sc from getting freed */ sc->flags.store_copying = 1; debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->hash.key)); assert(sc->callback != NULL); /* * We used to check for ENTRY_ABORTED here. But there were some * problems. For example, we might have a slow client (or two) and * the server-side is reading far ahead and swapping to disk. Even * if the server-side aborts, we want to give the client(s) * everything we got before the abort condition occurred. */ storeClientCopy3(e, sc); sc->flags.store_copying = 0; cbdataUnlock(sc); /* ick, allow sc to be freed */ }
static void peerSelectCallback(ps_state * psstate) { StoreEntry *entry = psstate->entry; FwdServer *fs = psstate->servers; void *data = psstate->callback_data; if (entry) { debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry)); if (entry->ping_status == PING_WAITING) eventDelete(peerPingTimeout, psstate); entry->ping_status = PING_DONE; } if (fs == NULL) { debug(44, 1) ("Failed to select source for '%s'\n", storeUrl(entry)); debug(44, 1) (" always_direct = %d\n", psstate->always_direct); debug(44, 1) (" never_direct = %d\n", psstate->never_direct); debug(44, 1) (" timedout = %d\n", psstate->ping.timedout); } psstate->ping.stop = current_time; psstate->request->hier.ping = psstate->ping; if (cbdataValid(data)) { psstate->servers = NULL; psstate->callback(fs, data); } cbdataUnlock(data); peerSelectStateFree(psstate); }
/* free fetch state structures * must be called only when fetch cbdata is valid */ static void peerDigestFetchFinish(DigestFetchState * fetch, int err) { assert(fetch->entry && fetch->request); if (fetch->old_entry) { debug(72, 2) ("peerDigestFetchFinish: deleting old entry\n"); storeUnregister(fetch->old_entry, fetch); storeReleaseRequest(fetch->old_entry); storeUnlockObject(fetch->old_entry); fetch->old_entry = NULL; } /* update global stats */ kb_incr(&Counter.cd.kbytes_sent, (size_t) fetch->sent.bytes); kb_incr(&Counter.cd.kbytes_recv, (size_t) fetch->recv.bytes); Counter.cd.msgs_sent += fetch->sent.msg; Counter.cd.msgs_recv += fetch->recv.msg; /* unlock everything */ storeUnregister(fetch->entry, fetch); storeUnlockObject(fetch->entry); requestUnlink(fetch->request); fetch->entry = NULL; fetch->request = NULL; assert(fetch->pd == NULL); cbdataUnlock(fetch); cbdataFree(fetch); }
static void peerCountMcastPeersDone(void *data) { ps_state *psstate = data; peer *p = psstate->callback_data; StoreEntry *fake = psstate->entry; if (cbdataValid(p)) { p->mcast.flags.counting = 0; p->mcast.avg_n_members = doubleAverage(p->mcast.avg_n_members, (double) psstate->ping.n_recv, ++p->mcast.n_times_counted, 10); debug(15, 1) ("Group %s: %d replies, %4.1f average, RTT %d\n", p->host, psstate->ping.n_recv, p->mcast.avg_n_members, p->stats.rtt); p->mcast.n_replies_expected = (int) p->mcast.avg_n_members; } cbdataUnlock(p); EBIT_SET(fake->flags, ENTRY_ABORTED); requestUnlink(fake->mem_obj->request); fake->mem_obj->request = NULL; storeReleaseRequest(fake); storeUnlockObject(fake); requestUnlink(psstate->request); cbdataFree(psstate); }
static void storeUfsReadDone(int fd, const char *buf, int len, int errflag, void *my_data) { storeIOState *sio = my_data; ufsstate_t *ufsstate = (ufsstate_t *) sio->fsstate; STRCB *callback = sio->read.callback; void *their_data = sio->read.callback_data; ssize_t rlen; debug(79, 3) ("storeUfsReadDone: dirno %d, fileno %08X, FD %d, len %d\n", sio->swap_dirn, sio->swap_filen, fd, len); ufsstate->flags.reading = 0; if (errflag) { debug(79, 3) ("storeUfsReadDone: got failure (%d)\n", errflag); rlen = -1; } else { rlen = len; sio->offset += len; } assert(callback); assert(their_data); sio->read.callback = NULL; sio->read.callback_data = NULL; if (cbdataValid(their_data)) callback(their_data, buf, rlen); cbdataUnlock(their_data); }
void aioOpen(const char *path, int oflag, mode_t mode, AIOCB * callback, void *callback_data) { aio_ctrl_t *ctrlp; int ret; assert(initialised); aio_counts.open++; ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = -2; ctrlp->done_handler = callback; ctrlp->done_handler_data = callback_data; ctrlp->operation = _AIO_OPEN; cbdataLock(callback_data); if (aio_open(path, oflag, mode, &ctrlp->result) < 0) { ret = open(path, oflag, mode); if (callback) (callback) (ctrlp->fd, callback_data, ret, errno); cbdataUnlock(callback_data); memPoolFree(aio_ctrl_pool, ctrlp); return; } ctrlp->next = used_list; used_list = ctrlp; return; }
void aioUnlink(const char *pathname, AIOCB * callback, void *callback_data) { aio_ctrl_t *ctrlp; char *path; assert(initialised); aio_counts.unlink++; ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = -2; ctrlp->done_handler = callback; ctrlp->done_handler_data = callback_data; ctrlp->operation = _AIO_UNLINK; path = xstrdup(pathname); cbdataLock(callback_data); if (aio_unlink(path, &ctrlp->result) < 0) { int ret = unlink(path); (callback) (ctrlp->fd, callback_data, ret, errno); cbdataUnlock(callback_data); memPoolFree(aio_ctrl_pool, ctrlp); xfree(path); return; } ctrlp->next = used_list; used_list = ctrlp; xfree(path); } /* aioUnlink */
void aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data) { aio_ctrl_t *ctrlp; assert(initialised); aio_counts.stat++; ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = -2; ctrlp->done_handler = callback; ctrlp->done_handler_data = callback_data; ctrlp->operation = _AIO_STAT; cbdataLock(callback_data); if (aio_stat(path, sb, &ctrlp->result) < 0) { if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL) errno = EWOULDBLOCK; if (callback) (callback) (ctrlp->fd, callback_data, -1, errno); cbdataUnlock(callback_data); memPoolFree(aio_ctrl_pool, ctrlp); return; } ctrlp->next = used_list; used_list = ctrlp; return; } /* aioStat */
/* Read from client side and queue it for writing to the server */ static void sslReadClient(int fd, void *data) { SslStateData *sslState = data; int len; assert(fd == sslState->client.fd); debug(26, 3) ("sslReadClient: FD %d, reading %d bytes at offset %d\n", fd, SQUID_TCP_SO_RCVBUF - sslState->client.len, sslState->client.len); Counter.syscalls.sock.reads++; len = read(fd, sslState->client.buf + sslState->client.len, SQUID_TCP_SO_RCVBUF - sslState->client.len); debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", fd, len); if (len > 0) { fd_bytes(fd, len, FD_READ); kb_incr(&Counter.client_http.kbytes_in, len); sslState->client.len += len; } cbdataLock(sslState); if (len < 0) { debug(50, ECONNRESET == errno ? 3 : 1) ("sslReadClient: FD %d: read failure: %s\n", fd, xstrerror()); if (!ignoreErrno(errno)) comm_close(fd); } else if (len == 0) { comm_close(fd); } if (cbdataValid(sslState)) sslSetSelect(sslState); cbdataUnlock(sslState); }
static void helperStatefulRequestFree(helper_stateful_request * r) { cbdataUnlock(r->data); xfree(r->buf); memFree(r, MEM_HELPER_STATEFUL_REQUEST); }
static void helperRequestFree(helper_request * r) { cbdataUnlock(r->data); xfree(r->buf); memFree(r, MEM_HELPER_REQUEST); }
static void idnsCheckQueue(void *unused) { dlink_node *n; dlink_node *p = NULL; idns_query *q; event_queued = 0; for (n = lru_list.tail; n; n = p) { q = n->data; if (tvSubDsec(q->sent_t, current_time) < 5.0) break; debug(78, 3) ("idnsCheckQueue: ID %#04x timeout\n", q->id); p = n->prev; dlinkDelete(&q->lru, &lru_list); if (q->nsends < IDNS_MAX_TRIES) { idnsSendQuery(q); } else { int v = cbdataValid(q->callback_data); debug(78, 1) ("idnsCheckQueue: ID %x: giving up after %d tries and %5.1f seconds\n", (int) q->id, q->nsends, tvSubDsec(q->start_t, current_time)); cbdataUnlock(q->callback_data); if (v) q->callback(q->callback_data, NULL, 0); memFree(q, MEM_IDNS_QUERY); } } idnsTickleQueue(); }
void requestDestroy(request_t * req) { assert(req); if (req->body_reader) requestAbortBody(req); if (req->auth_user_request) authenticateAuthUserRequestUnlock(req->auth_user_request); safe_free(req->canonical); safe_free(req->vary_hdr); safe_free(req->vary_headers); stringClean(&req->vary_encoding); safe_free(req->urlgroup); safe_free(req->extacl_user); safe_free(req->extacl_passwd); stringClean(&req->urlpath); httpHeaderClean(&req->header); if (req->cache_control) httpHdrCcDestroy(req->cache_control); if (req->range) httpHdrRangeDestroy(req->range); stringClean(&req->extacl_log); if (req->vary) { if (req->etags == &req->vary->etags) req->etags = NULL; storeLocateVaryDone(req->vary); req->vary = NULL; } assert(req->etags == NULL); safe_free(req->etag); if (req->pinned_connection) cbdataUnlock(req->pinned_connection); req->pinned_connection = NULL; memFree(req, MEM_REQUEST_T); }
storeIOState * storeDiskdCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data) { sfileno f; int x; storeIOState *sio; char *buf; int shm_offset; diskdinfo_t *diskdinfo = SD->fsdata; diskdstate_t *diskdstate; /* * Fail on open() if there are too many requests queued. */ if (diskdinfo->away > diskdinfo->magic1) { diskd_stats.open_fail_queue_len++; return NULL; } /* Allocate a number */ f = storeDiskdDirMapBitAllocate(SD); debug(79, 3) ("storeDiskdCreate: fileno %08X\n", f); CBDATA_INIT_TYPE_FREECB(storeIOState, storeDiskdIOFreeEntry); sio = cbdataAlloc(storeIOState); sio->fsstate = diskdstate = memPoolAlloc(diskd_state_pool); sio->swap_filen = f; sio->swap_dirn = SD->index; sio->mode = O_WRONLY | O_CREAT | O_TRUNC; sio->callback = callback; sio->callback_data = callback_data; sio->e = e; cbdataLock(callback_data); diskdstate->flags.writing = 0; diskdstate->flags.reading = 0; diskdstate->flags.close_request = 0; diskdstate->id = diskd_stats.sio_id++; buf = storeDiskdShmGet(SD, &shm_offset); xstrncpy(buf, storeDiskdDirFullPath(SD, f, NULL), SHMBUF_BLKSZ); x = storeDiskdSend(_MQD_OPEN, SD, diskdstate->id, sio, strlen(buf) + 1, sio->mode, shm_offset); if (x < 0) { debug(79, 1) ("storeDiskdSend OPEN: %s\n", xstrerror()); storeDiskdShmPut(SD, shm_offset); cbdataUnlock(sio->callback_data); cbdataFree(sio); return NULL; } storeDiskdDirReplAdd(SD, e); diskd_stats.create.ops++; return sio; }
static void free_external_acl_data(void *data) { external_acl_data *p = data; wordlistDestroy(&p->arguments); cbdataUnlock(p->def); p->def = NULL; }
static void freePeerMonitor(void *data) { PeerMonitor *pm = data; if (cbdataValid(pm->peer)) pm->peer->monitor.data = NULL; cbdataUnlock(pm->peer); pm->peer = NULL; }
void storeDiskdHandle(diomsg * M) { int valid = M->callback_data ? cbdataValid(M->callback_data) : 1; if (M->callback_data) cbdataUnlock(M->callback_data); if (!valid) { debug(79, 3) ("storeDiskdHandle: Invalid callback_data %p\n", M->callback_data); /* * The read operation has its own callback. If we don't * call storeDiskdReadDone(), then we must make sure the * callback_data gets unlocked! */ if (_MQD_READ == M->mtype) { storeIOState *sio = M->callback_data; cbdataUnlock(sio->read.callback_data); } return; } /* set errno passed from diskd. makes debugging more meaningful */ if (M->status < 0) errno = -M->status; switch (M->mtype) { case _MQD_OPEN: storeDiskdOpenDone(M); break; case _MQD_CLOSE: storeDiskdCloseDone(M); break; case _MQD_READ: storeDiskdReadDone(M); break; case _MQD_WRITE: storeDiskdWriteDone(M); break; case _MQD_UNLINK: storeDiskdUnlinkDone(M); break; default: assert(0); break; } }
static void authenticateBasicHandleReply(void *data, char *reply) { authenticateStateData *r = data; auth_user_t *auth_user; basic_data *basic_auth; auth_basic_queue_node *tmpnode; int valid; char *t = NULL; debug(29, 9) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : "<NULL>"); if (reply) { if ((t = strchr(reply, ' '))) *t++ = '\0'; if (*reply == '\0') reply = NULL; } assert(r->auth_user_request != NULL); assert(r->auth_user_request->auth_user->auth_type == AUTH_BASIC); auth_user = r->auth_user_request->auth_user; basic_auth = auth_user->scheme_data; if (reply && (strncasecmp(reply, "OK", 2) == 0)) basic_auth->flags.credentials_ok = 1; else { basic_auth->flags.credentials_ok = 3; safe_free(r->auth_user_request->message); if (t && *t) r->auth_user_request->message = xstrdup(t); } basic_auth->credentials_checkedtime = squid_curtime; valid = cbdataValid(r->data); if (valid) r->handler(r->data, NULL); cbdataUnlock(r->data); while (basic_auth->auth_queue) { tmpnode = basic_auth->auth_queue->next; valid = cbdataValid(basic_auth->auth_queue->data); if (valid) basic_auth->auth_queue->handler(basic_auth->auth_queue->data, NULL); cbdataUnlock(basic_auth->auth_queue->data); xfree(basic_auth->auth_queue); basic_auth->auth_queue = tmpnode; } authenticateStateFree(r); }
static void storeDiskdIOCallback(storeIOState * sio, int errflag) { void *p = sio->callback_data; debug(79, 3) ("storeDiskdIOCallback: errflag=%d\n", errflag); if (cbdataValid(p)) sio->callback(p, errflag, sio); cbdataUnlock(p); cbdataFree(sio); }
static void storeAufsWriteDone(int fd, int errflag, size_t len, void *my_data) #endif { static int loop_detect = 0; storeIOState *sio = my_data; squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate; #if ASYNC_WRITE int errflag; int len = aio_return; /* Translate from errno to Squid disk error */ if (aio_errno) errflag = aio_errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; else errflag = DISK_OK; #endif debug(79, 3) ("storeAufsWriteDone: dirno %d, fileno %08X, FD %d, len %ld, err=%d\n", sio->swap_dirn, sio->swap_filen, fd, (long int) len, errflag); assert(++loop_detect < 10); aiostate->flags.writing = 0; if (errflag) { debug(79, 0) ("storeAufsWriteDone: got failure (%d)\n", errflag); storeAufsIOCallback(sio, errflag); loop_detect--; return; } sio->offset += len; #if ASYNC_WRITE if (storeAufsKickWriteQueue(sio)) (void) 0; else if (aiostate->flags.close_request) storeAufsIOCallback(sio, errflag); #else /* loop around storeAufsKickWriteQueue to break recursion stack * overflow when large amounts of data has been queued for write. * As writes are blocking here we immediately get called again * without going via the I/O event loop.. */ if (!aiostate->flags.write_kicking) { /* cbdataLock to protect us from the storeAufsIOCallback on error above */ cbdataLock(sio); aiostate->flags.write_kicking = 1; while (storeAufsKickWriteQueue(sio)) if (!cbdataValid(sio)) break; if (cbdataValid(sio)) { aiostate->flags.write_kicking = 0; if (aiostate->flags.close_request) storeAufsIOCallback(sio, errflag); } cbdataUnlock(sio); } #endif loop_detect--; }
/* * This routine hasn't been optimised to take advantage of the * passed sc. Yet. */ int storeUnregister(store_client * sc, StoreEntry * e, void *data) { MemObject *mem = e->mem_obj; #if STORE_CLIENT_LIST_DEBUG assert(sc == storeClientListSearch(e->mem_obj, data)); #endif if (mem == NULL) return 0; debug(20, 3) ("storeUnregister: called for '%s'\n", storeKeyText(e->hash.key)); if (sc == NULL) return 0; if (mem->clients.head == NULL) return 0; dlinkDelete(&sc->node, &mem->clients); mem->nclients--; if (e->store_status == STORE_OK && e->swap_status != SWAPOUT_DONE) storeSwapOut(e); if (sc->swapin_sio) { storeClose(sc->swapin_sio); cbdataUnlock(sc->swapin_sio); sc->swapin_sio = NULL; statCounter.swap.ins++; } if (NULL != sc->callback) { /* callback with ssize = -1 to indicate unexpected termination */ debug(20, 3) ("storeUnregister: store_client for %s has a callback\n", mem->url); storeClientCallback(sc, -1); } #if DELAY_POOLS delayUnregisterDelayIdPtr(&sc->delay_id); #endif cbdataUnlock(sc->callback_data); /* we're done with it now */ /*assert(!sc->flags.disk_io_pending); */ cbdataFree(sc); assert(e->lock_count > 0); storeSwapOutMaintainMemObject(e); if (mem->nclients == 0) CheckQuickAbort(e); return 1; }
static void netdbExchangeDone(void *data) { netdbExchangeState *ex = data; debug(38, 3) ("netdbExchangeDone: %s\n", storeUrl(ex->e)); requestUnlink(ex->r); storeClientUnregister(ex->sc, ex->e, ex); storeUnlockObject(ex->e); cbdataUnlock(ex->p); cbdataFree(ex); }
void peerNoteDigestGone(peer * p) { #if USE_CACHE_DIGESTS if (p->digest) { PeerDigest *pd = p->digest; p->digest = NULL; cbdataUnlock(pd); } #endif }
void eventFreeMemory(void) { struct ev_entry *event; while ((event = tasks)) { tasks = event->next; if (NULL != event->arg) cbdataUnlock(event->arg); memFree(event, MEM_EVENT); } tasks = NULL; }
static void idnsCallback(idns_query * q, rfc1035_rr * answers, int n, const char *error) { int valid; valid = cbdataValid(q->callback_data); cbdataUnlock(q->callback_data); if (valid) q->callback(q->callback_data, answers, n, error); while (q->queue) { idns_query *q2 = q->queue; q->queue = q2->queue; valid = cbdataValid(q2->callback_data); cbdataUnlock(q2->callback_data); if (valid) q2->callback(q2->callback_data, answers, n, error); cbdataFree(q2); } if (q->hash.key) { hash_remove_link(idns_lookup_hash, &q->hash); q->hash.key = NULL; } }
static void errorMapFetchComplete(ErrorMapState * state) { storeClientUnregister(state->sc, state->e, state); state->sc = NULL; storeUnlockObject(state->e); state->e = NULL; requestUnlink(state->req); state->req = NULL; cbdataUnlock(state->callback_data); state->callback_data = NULL; cbdataFree(state); }