Exemplo n.º 1
0
static void
pconnHistDump(StoreEntry * e)
{
    int i;
    storeAppendPrintf(e,
	"Client-side persistent connection counts:\n"
	"\n"
	"\treq/\n"
	"\tconn      count\n"
	"\t----  ---------\n");
    for (i = 0; i < PCONN_HIST_SZ; i++) {
	if (client_pconn_hist[i] == 0)
	    continue;
	storeAppendPrintf(e, "\t%4d  %9d\n", i, client_pconn_hist[i]);
    }
    storeAppendPrintf(e,
	"\n"
	"Server-side persistent connection counts:\n"
	"\n"
	"\treq/\n"
	"\tconn      count\n"
	"\t----  ---------\n");
    for (i = 0; i < PCONN_HIST_SZ; i++) {
	if (server_pconn_hist[i] == 0)
	    continue;
	storeAppendPrintf(e, "\t%4d  %9d\n", i, server_pconn_hist[i]);
    }
}
Exemplo n.º 2
0
void
cacheDigestReport(CacheDigest * cd, const char *label, StoreEntry * e)
{
	CacheDigestStats stats;
	assert(cd && e);
	cacheDigestStats(cd, &stats);
	storeAppendPrintf(e, "%s digest: size: %d bytes\n",
					  label ? label : "", stats.bit_count / 8
					 );
	storeAppendPrintf(e, "\t entries: count: %d capacity: %d util: %d%%\n",
					  cd->count,
					  cd->capacity,
					  xpercentInt(cd->count, cd->capacity)
					 );
	storeAppendPrintf(e, "\t deletion attempts: %d\n",
					  cd->del_count
					 );
	storeAppendPrintf(e, "\t bits: per entry: %d on: %d capacity: %d util: %d%%\n",
					  cd->bits_per_entry,
					  stats.bit_on_count, stats.bit_count,
					  xpercentInt(stats.bit_on_count, stats.bit_count)
					 );
	storeAppendPrintf(e, "\t bit-seq: count: %d avg.len: %.2f\n",
					  stats.bseq_count,
					  xdiv(stats.bseq_len_sum, stats.bseq_count)
					 );
}
Exemplo n.º 3
0
static void
memStringStats(StoreEntry * sentry)
{
    const char *pfmt = "%-20s\t %d\t %d\n";
    int i;
    int pooled_count = 0;
    size_t pooled_volume = 0;
    /* heading */
    storeAppendPrintf(sentry,
                      "String Pool\t Impact\t\t\n"
                      " \t (%%strings)\t (%%volume)\n");
    /* table body */
    for (i = 0; i < mem_str_pool_count; i++) {
        const MemPool *pool = StrPools[i].pool;
        const int plevel = pool->meter.inuse.level;
        storeAppendPrintf(sentry, pfmt,
                          pool->label,
                          xpercentInt(plevel, StrCountMeter.level),
                          xpercentInt(plevel * pool->obj_size, StrVolumeMeter.level));
        pooled_count += plevel;
        pooled_volume += plevel * pool->obj_size;
    }
    /* malloc strings */
    storeAppendPrintf(sentry, pfmt,
                      "Other Strings",
                      xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level),
                      xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level));
    storeAppendPrintf(sentry, "\n");
}
Exemplo n.º 4
0
/*
 * Make this non-static so we can register
 * it from storeInit();
 */
void
storeIOStats(StoreEntry * sentry)
{
    storeAppendPrintf(sentry, "Store IO Interface Stats\n");
    storeAppendPrintf(sentry, "create.calls %d\n", store_io_stats.create.calls);
    storeAppendPrintf(sentry, "create.select_fail %d\n", store_io_stats.create.select_fail);
    storeAppendPrintf(sentry, "create.create_fail %d\n", store_io_stats.create.create_fail);
    storeAppendPrintf(sentry, "create.success %d\n", store_io_stats.create.success);
}
Exemplo n.º 5
0
static void
locationRewriteStats(StoreEntry * sentry)
{
    storeAppendPrintf(sentry, "Redirector Statistics:\n");
    helperStats(sentry, locrewriters);
    if (Config.onoff.redirector_bypass)
	storeAppendPrintf(sentry, "\nNumber of requests bypassed "
	    "because all rewriters were busy: %d\n", n_bypassed);
}
Exemplo n.º 6
0
static void
storeurlStats(StoreEntry * sentry)
{
    storeAppendPrintf(sentry, "Redirector Statistics:\n");
    helperStats(sentry, storeurlors);
    if (Config.onoff.storeurl_bypass)
	storeAppendPrintf(sentry, "\nNumber of requests bypassed "
	    "because all store url bypassers were busy: %d\n", n_bypassed);
}
static void
gopherHTMLFooter(StoreEntry * e)
{
    storeAppendPrintf(e, "<HR noshade size=\"1px\">\n");
    storeAppendPrintf(e, "<ADDRESS>\n");
    storeAppendPrintf(e, "Generated %s by %s (%s)\n",
	mkrfc1123(squid_curtime),
	getMyHostname(),
	visible_appname_string);
    storeAppendPrintf(e, "</ADDRESS></BODY></HTML>\n");
}
Exemplo n.º 8
0
static void
refreshCheckStats(StoreEntry * sentry)
{
    refresh_check_helper *p = Config.Program.refresh_check;

    if (p) {
	storeAppendPrintf(sentry, "Refresh Check helper statistics:\n");
	helperStats(sentry, p->helper);
	storeAppendPrintf(sentry, "\n");
    }
}
Exemplo n.º 9
0
static void
gopherEndHTML(GopherStateData * gopherState)
{
    StoreEntry *e = gopherState->entry;
    if (!gopherState->HTML_header_added) {
	gopherHTMLHeader(e, "Server Return Nothing", NULL);
	storeAppendPrintf(e, "<P>The Gopher query resulted in a blank response</P>");
    } else if (gopherState->HTML_pre) {
	storeAppendPrintf(e, "</PRE>\n");
    }
    gopherHTMLFooter(e);
}
Exemplo n.º 10
0
static void
externalAclStats(StoreEntry * sentry)
{
    external_acl *p;

    for (p = Config.externalAclHelperList; p; p = p->next) {
	storeAppendPrintf(sentry, "External ACL Statistics: %s\n", p->name);
	storeAppendPrintf(sentry, "Cache size: %d\n", p->cache->count);
	helperStats(sentry, p->helper);
	storeAppendPrintf(sentry, "\n");
    }
}
static void
refreshCountsStats(StoreEntry * sentry, struct RefreshCounts *rc)
{
    int sum = 0;
    int tot = rc->total;

    storeAppendPrintf(sentry, "\n\n%s histogram:\n", rc->proto);
    storeAppendPrintf(sentry, "Count\t%%Total\tCategory\n");

#define refreshCountsStatsEntry(code,desc) { \
	storeAppendPrintf(sentry, "%6d\t%6.2f\t%s\n", \
	    rc->status[code], xpercent(rc->status[code], tot), desc); \
    sum += rc->status[code]; \
}

    refreshCountsStatsEntry(FRESH_REQUEST_MAX_STALE_ALL,
	"Fresh: request max-stale wildcard");
    refreshCountsStatsEntry(FRESH_REQUEST_MAX_STALE_VALUE,
	"Fresh: request max-stale value");
    refreshCountsStatsEntry(FRESH_EXPIRES,
	"Fresh: expires time not reached");
    refreshCountsStatsEntry(FRESH_LMFACTOR_RULE,
	"Fresh: refresh_pattern last-mod factor percentage");
    refreshCountsStatsEntry(FRESH_MIN_RULE,
	"Fresh: refresh_pattern min value");
    refreshCountsStatsEntry(FRESH_OVERRIDE_EXPIRES,
	"Fresh: refresh_pattern override expires");
    refreshCountsStatsEntry(FRESH_OVERRIDE_LASTMOD,
	"Fresh: refresh_pattern override lastmod");
    refreshCountsStatsEntry(STALE_MUST_REVALIDATE,
	"Stale: response has must-revalidate");
    refreshCountsStatsEntry(STALE_RELOAD_INTO_IMS,
	"Stale: changed reload into IMS");
    refreshCountsStatsEntry(STALE_FORCED_RELOAD,
	"Stale: request has no-cache directive");
    refreshCountsStatsEntry(STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE,
	"Stale: age exceeds request max-age value");
    refreshCountsStatsEntry(STALE_EXPIRES,
	"Stale: expires time reached");
    refreshCountsStatsEntry(STALE_MAX_RULE,
	"Stale: refresh_pattern max age rule");
    refreshCountsStatsEntry(STALE_LMFACTOR_RULE,
	"Stale: refresh_pattern last-mod factor percentage");
    refreshCountsStatsEntry(STALE_DEFAULT,
	"Stale: by default");

    tot = sum;			/* paranoid: "total" line shows 100% if we forgot nothing */
    storeAppendPrintf(sentry, "%6d\t%6.2f\tTOTAL\n",
	rc->total, xpercent(rc->total, tot));
    \
	storeAppendPrintf(sentry, "\n");
}
Exemplo n.º 12
0
static void
ptrDump(StoreEntry * sentry)
{
    hash_link *hptr;
    ptr *c;
    storeAppendPrintf(sentry, "Tracking %d pointers\n", leakCount);
    hash_first(htable);
    while ((hptr = hash_next(htable))) {
	c = (ptr *) hptr;
	storeAppendPrintf(sentry, "%20p last used %9d seconds ago by %s:%d\n",
	    c->key, squid_curtime - c->when, c->file, c->line);
    }
}
Exemplo n.º 13
0
void
aioStats(StoreEntry * sentry)
{
    storeAppendPrintf(sentry, "ASYNC IO Counters:\n");
    storeAppendPrintf(sentry, "open\t%d\n", aio_counts.open);
    storeAppendPrintf(sentry, "close\t%d\n", aio_counts.close);
    storeAppendPrintf(sentry, "cancel\t%d\n", aio_counts.cancel);
    storeAppendPrintf(sentry, "write\t%d\n", aio_counts.write);
    storeAppendPrintf(sentry, "read\t%d\n", aio_counts.read);
    storeAppendPrintf(sentry, "stat\t%d\n", aio_counts.stat);
    storeAppendPrintf(sentry, "unlink\t%d\n", aio_counts.unlink);
    storeAppendPrintf(sentry, "check_callback\t%d\n", aio_counts.check_callback);
    storeAppendPrintf(sentry, "queue\t%d\n", aio_get_queue_len());
}
Exemplo n.º 14
0
static void
authNegotiateCfgDump(StoreEntry * entry, const char *name, authScheme * scheme)
{
    auth_negotiate_config *config = scheme->scheme_data;
    wordlist *list = config->authenticate;
    storeAppendPrintf(entry, "%s %s program", name, "negotiate");
    while (list != NULL) {
	storeAppendPrintf(entry, " %s", list->key);
	list = list->next;
    }
    storeAppendPrintf(entry, "\n");
    storeAppendPrintf(entry, "%s %s children %d\n", name, "negotiate", config->authenticateChildren);
    storeAppendPrintf(entry, "%s %s keep_alive %s\n", name, "negotiate", config->keep_alive ? "on" : "off");
}
Exemplo n.º 15
0
void
cacheDigestGuessStatsReport(const cd_guess_stats * stats, StoreEntry * sentry, const char *label)
{
	const int true_count = stats->true_hits + stats->true_misses;
	const int false_count = stats->false_hits + stats->false_misses;
	const int hit_count = stats->true_hits + stats->false_hits;
	const int miss_count = stats->true_misses + stats->false_misses;
	const int tot_count = true_count + false_count;

	assert(label);
	assert(tot_count == hit_count + miss_count);	/* paranoid */

	if (!tot_count)
	{
		storeAppendPrintf(sentry, "no guess stats for %s available\n", label);
		return;
	}
	storeAppendPrintf(sentry, "Digest guesses stats for %s:\n", label);
	storeAppendPrintf(sentry, "guess\t hit\t\t miss\t\t total\t\t\n");
	storeAppendPrintf(sentry, " \t #\t %%\t #\t %%\t #\t %%\t\n");
	storeAppendPrintf(sentry, "true\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n",
					  stats->true_hits, xpercent(stats->true_hits, tot_count),
					  stats->true_misses, xpercent(stats->true_misses, tot_count),
					  true_count, xpercent(true_count, tot_count));
	storeAppendPrintf(sentry, "false\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n",
					  stats->false_hits, xpercent(stats->false_hits, tot_count),
					  stats->false_misses, xpercent(stats->false_misses, tot_count),
					  false_count, xpercent(false_count, tot_count));
	storeAppendPrintf(sentry, "all\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n",
					  hit_count, xpercent(hit_count, tot_count),
					  miss_count, xpercent(miss_count, tot_count),
					  tot_count, xpercent(tot_count, tot_count));
	storeAppendPrintf(sentry, "\tclose_hits: %d ( %d%%) /* cd said hit, doc was in the peer cache, but we got a miss */\n",
					  stats->close_hits, xpercentInt(stats->close_hits, stats->false_hits));
}
Exemplo n.º 16
0
static void
commIncomingStats(StoreEntry * sentry)
{
    StatCounters *f = &statCounter;
    storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n",
	incoming_icp_interval >> INCOMING_FACTOR);
    storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n",
	incoming_dns_interval >> INCOMING_FACTOR);
    storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n",
	incoming_http_interval >> INCOMING_FACTOR);
    storeAppendPrintf(sentry, "\n");
    storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n");
#ifdef HAVE_POLL
    storeAppendPrintf(sentry, "ICP Messages handled per comm_poll_icp_incoming() call:\n");
#else
    storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n");
#endif
    statHistDump(&f->comm_icp_incoming, sentry, statHistIntDumper);
#ifdef HAVE_POLL
    storeAppendPrintf(sentry, "DNS Messages handled per comm_poll_dns_incoming() call:\n");
#else
    storeAppendPrintf(sentry, "DNS Messages handled per comm_select_dns_incoming() call:\n");
#endif
    statHistDump(&f->comm_dns_incoming, sentry, statHistIntDumper);
#ifdef HAVE_POLL
    storeAppendPrintf(sentry, "HTTP Messages handled per comm_poll_http_incoming() call:\n");
#else
    storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_http_incoming() call:\n");
#endif
    statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper);
}
Exemplo n.º 17
0
void
storeDirStats(StoreEntry * sentry)
{
    storeAppendPrintf(sentry, "Store Directory Statistics:\n");
    storeAppendPrintf(sentry, "Store Entries          : %d\n",
	memInUse(MEM_STOREENTRY));
    storeAppendPrintf(sentry, "Maximum Swap Size      : %8d KB\n",
	Config.Swap.maxSize);
    storeAppendPrintf(sentry, "Current Store Swap Size: %8d KB\n",
	store_swap_size);
    storeAppendPrintf(sentry, "Current Capacity       : %d%% used, %d%% free\n",
	percent((int) store_swap_size, (int) Config.Swap.maxSize),
	percent((int) (Config.Swap.maxSize - store_swap_size), (int) Config.Swap.maxSize));
    storeUfsDirStats(sentry);	/* XXX */
}
Exemplo n.º 18
0
static void
cachemgrReconfigure(StoreEntry * sentry)
{
    debug(16, 0) ("Reconfigure by command.\n");
    storeAppendPrintf(sentry, "Reconfiguring Squid Process ....");
    reconfigure(SIGHUP);
}
Exemplo n.º 19
0
static void
memBufStats(StoreEntry * sentry)
{
    storeAppendPrintf(sentry, "Large buffers: %d (%d KB)\n",
                      (int) HugeBufCountMeter.level,
                      (int) HugeBufVolumeMeter.level / 1024);
}
Exemplo n.º 20
0
void
netdbBinaryExchange(StoreEntry * s)
{
    http_reply *reply = s->mem_obj->reply;
#if USE_ICMP
    netdbEntry *n;
    int i;
    int j;
    int rec_sz;
    char *buf;
    struct in_addr addr;
    storeBuffer(s);
    httpReplyReset(reply);
    httpReplySetHeaders(reply, HTTP_OK, "OK", NULL, -1, squid_curtime, -1);
    httpReplySwapOut(reply, s);
    rec_sz = 0;
    rec_sz += 1 + sizeof(addr.s_addr);
    rec_sz += 1 + sizeof(int);
    rec_sz += 1 + sizeof(int);
    buf = memAllocate(MEM_4K_BUF);
    i = 0;
    hash_first(addr_table);
    while ((n = (netdbEntry *) hash_next(addr_table))) {
        if (0.0 == n->rtt)
            continue;
        if (n->rtt > 60000)	/* RTT > 1 MIN probably bogus */
            continue;
        if (!safe_inet_addr(n->network, &addr))
            continue;
        buf[i++] = (char) NETDB_EX_NETWORK;
        xmemcpy(&buf[i], &addr.s_addr, sizeof(addr.s_addr));
        i += sizeof(addr.s_addr);
        buf[i++] = (char) NETDB_EX_RTT;
        j = htonl((int) (n->rtt * 1000));
        xmemcpy(&buf[i], &j, sizeof(int));
        i += sizeof(int);
        buf[i++] = (char) NETDB_EX_HOPS;
        j = htonl((int) (n->hops * 1000));
        xmemcpy(&buf[i], &j, sizeof(int));
        i += sizeof(int);
        if (i + rec_sz > 4096) {
            storeAppend(s, buf, i);
            i = 0;
        }
    }
    if (i > 0) {
        storeAppend(s, buf, i);
        i = 0;
    }
    assert(0 == i);
    storeBufferFlush(s);
    memFree(buf, MEM_4K_BUF);
#else
    httpReplyReset(reply);
    httpReplySetHeaders(reply, HTTP_BAD_REQUEST, "Bad Request", NULL, -1, -1, -1);
    httpReplySwapOut(reply, s);
    storeAppendPrintf(s, "NETDB support not compiled into this Squid cache.\n");
#endif
    storeComplete(s);
}
Exemplo n.º 21
0
static void
gopherEndHTML(GopherStateData * gopherState)
{
    if (!gopherState->data_in)
	storeAppendPrintf(gopherState->entry,
	    "<HTML><HEAD><TITLE>Server Return Nothing.</TITLE>\n"
	    "</HEAD><BODY><HR><H1>Server Return Nothing.</H1></BODY></HTML>\n");
}
Exemplo n.º 22
0
static void
httpHeaderFldsPerHdrDumper(StoreEntry * sentry, int idx, double val, double size, int count)
{
    if (count)
	storeAppendPrintf(sentry, "%2d\t %5d\t %5d\t %6.2f\n",
	    idx, (int) val, count,
	    xpercent(count, dump_stat->destroyedCount));
}
void
squidaio_stats(StoreEntry * sentry)
{
    squidaio_thread_t *threadp;
    int i;

    if (!squidaio_initialised)
	return;

    storeAppendPrintf(sentry, "\n\nThreads Status:\n");
    storeAppendPrintf(sentry, "#\tID\t# Requests\n");

    threadp = threads;
    for (i = 0; i < squidaio_nthreads; i++) {
	storeAppendPrintf(sentry, "%i\t0x%lx\t%ld\n", i + 1, threadp->dwThreadId, threadp->requests);
	threadp = threadp->next;
    }
}
Exemplo n.º 24
0
static void
eventDump(StoreEntry * sentry)
{
    struct ev_entry *e = tasks;
    if (last_event_ran)
	storeAppendPrintf(sentry, "Last event to run: %s\n\n", last_event_ran);
    storeAppendPrintf(sentry, "%s\t%s\t%s\t%s\n",
	"Operation",
	"Next Execution",
	"Weight",
	"Callback Valid?");
    while (e != NULL) {
	storeAppendPrintf(sentry, "%s\t%f seconds\t%d\t%s\n",
	    e->name, e->when - current_dtime, e->weight,
	    e->arg ? cbdataValid(e->arg) ? "yes" : "no" : "N/A");
	e = e->next;
    }
}
Exemplo n.º 25
0
static void
cachemgrOfflineToggle(StoreEntry * sentry)
{
    Config.onoff.offline = !Config.onoff.offline;
    debug(16, 0) ("offline_mode now %s.\n",
	Config.onoff.offline ? "ON" : "OFF");
    storeAppendPrintf(sentry, "offline_mode is now %s\n",
	Config.onoff.offline ? "ON" : "OFF");
}
Exemplo n.º 26
0
static void
cachemgrMenu(StoreEntry * sentry)
{
    action_table *a;
    for (a = ActionTable; a != NULL; a = a->next) {
	storeAppendPrintf(sentry, " %-22s\t%s\t%s\n",
	    a->action, a->desc, cachemgrActionProtection(a));
    }
}
Exemplo n.º 27
0
static void
authDigestCfgDump(StoreEntry * entry, const char *name, authScheme * scheme)
{
    auth_digest_config *config = scheme->scheme_data;
    wordlist *list = config->authenticate;
    debug(29, 9) ("authDigestCfgDump: Dumping configuration\n");
    storeAppendPrintf(entry, "%s %s", name, "digest");
    while (list != NULL) {
	storeAppendPrintf(entry, " %s", list->key);
	list = list->next;
    }
    storeAppendPrintf(entry, "\n%s %s realm %s\n%s %s children %d\n%s %s nonce_max_count %d\n%s %s nonce_max_duration %d seconds\n%s %s nonce_garbage_interval %d seconds\n",
	name, "digest", config->digestAuthRealm,
	name, "digest", config->authenticateChildren,
	name, "digest", config->noncemaxuses,
	name, "digest", (int) config->noncemaxduration,
	name, "digest", (int) config->nonceGCInterval);
}
Exemplo n.º 28
0
static void
gopherHTMLHeader(StoreEntry * e, const char *title, const char *substring)
{
    storeAppendPrintf(e, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
    storeAppendPrintf(e, "<HTML><HEAD><TITLE>");
    storeAppendPrintf(e, title, substring);
    storeAppendPrintf(e, "</TITLE>");
    storeAppendPrintf(e, "<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n");
    storeAppendPrintf(e, "</HEAD>\n<BODY><H1>");
    storeAppendPrintf(e, title, substring);
    storeAppendPrintf(e, "</H1>\n");
}
Exemplo n.º 29
0
static void
peerUserHashCachemgr(StoreEntry * sentry)
{
    peer *p;
    int sumfetches = 0;
    storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n",
	"Hostname",
	"Hash",
	"Multiplier",
	"Factor",
	"Actual");
    for (p = Config.peers; p; p = p->next)
	sumfetches += p->stats.fetches;
    for (p = Config.peers; p; p = p->next) {
	storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n",
	    p->name, p->userhash.hash,
	    p->userhash.load_multiplier,
	    p->userhash.load_factor,
	    sumfetches ? (double) p->stats.fetches / sumfetches : -1.0);
    }
}
Exemplo n.º 30
0
void
storeDigestReport(StoreEntry * e)
{
#if USE_CACHE_DIGESTS
    if (!Config.onoff.digest_generation) {
	return;
    }
    if (store_digest) {
	cacheDigestReport(store_digest, "store", e);
	storeAppendPrintf(e, "\t added: %d rejected: %d ( %.2f %%) del-ed: %d\n",
	    sd_stats.add_count,
	    sd_stats.rej_count,
	    xpercent(sd_stats.rej_count, sd_stats.rej_count + sd_stats.add_count),
	    sd_stats.del_count);
	storeAppendPrintf(e, "\t collisions: on add: %.2f %% on rej: %.2f %%\n",
	    xpercent(sd_stats.add_coll_count, sd_stats.add_count),
	    xpercent(sd_stats.rej_coll_count, sd_stats.rej_count));
    } else {
	storeAppendPrintf(e, "store digest: disabled.\n");
    }
#endif
}