/*
 * submit a request to create a cache object for writing.
 * The StoreEntry structure is sent as a hint to the filesystem
 * to what will be stored in this object, to allow the filesystem
 * to select different polices depending on object size or type.
 */
storeIOState *
storeCreate(StoreEntry * e, STIOCB * file_callback, STIOCB * close_callback, void *callback_data)
{
    size_t objsize;
    sdirno dirn;
    SwapDir *SD;
    storeIOState *sio;

    store_io_stats.create.calls++;
    /* This is just done for logging purposes */
    objsize = objectLen(e);
    if (objsize != -1)
	objsize += e->mem_obj->swap_hdr_sz;

    /*
     * Pick the swapdir
     * We assume that the header has been packed by now ..
     */
    dirn = storeDirSelectSwapDir(e);
    if (dirn == -1) {
	debug(20, 2) ("storeCreate: no valid swapdirs for this object\n");
	store_io_stats.create.select_fail++;
	return NULL;
    }
    debug(20, 2) ("storeCreate: Selected dir '%d' for obj size '%ld'\n", dirn, (long int) objsize);
    SD = &Config.cacheSwap.swapDirs[dirn];

    /* Now that we have a fs to use, call its storeCreate function */
    sio = SD->obj.create(SD, e, file_callback, close_callback, callback_data);
    if (NULL == sio)
	store_io_stats.create.create_fail++;
    else
	store_io_stats.create.success++;
    return sio;
}
/*
 * Build a TLV list for a StoreEntry
 */
tlv *
storeSwapMetaBuild(StoreEntry * e)
{
    tlv *TLV = NULL;		/* we'll return this */
    tlv **T = &TLV;
    const char *url;
    const char *vary;
    const squid_off_t objsize = objectLen(e);
    assert(e->mem_obj != NULL);
    assert(e->swap_status == SWAPOUT_WRITING);
    url = storeUrl(e);
    debug(20, 3) ("storeSwapMetaBuild: %s\n", url);
    T = storeSwapTLVAdd(STORE_META_KEY, e->hash.key, SQUID_MD5_DIGEST_LENGTH, T);
#if SIZEOF_SQUID_FILE_SZ == SIZEOF_SIZE_T
    T = storeSwapTLVAdd(STORE_META_STD, &e->timestamp, STORE_HDR_METASIZE, T);
#else
    T = storeSwapTLVAdd(STORE_META_STD_LFS, &e->timestamp, STORE_HDR_METASIZE, T);
#endif
    T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T);
    if (objsize > -1) {
	T = storeSwapTLVAdd(STORE_META_OBJSIZE, &objsize, sizeof(objsize), T);
    }
    vary = e->mem_obj->vary_headers;
    if (vary)
	T = storeSwapTLVAdd(STORE_META_VARY_HEADERS, vary, strlen(vary) + 1, T);
    if (e->mem_obj->store_url)
	T = storeSwapTLVAdd(STORE_META_STOREURL, e->mem_obj->store_url, strlen(e->mem_obj->store_url) + 1, T);
    if (e->dirkey)
        T = storeSwapTLVAdd(STORE_META_KEY_URL, e->dirkey, SQUID_MD5_DIGEST_LENGTH, T);
    return TLV;
}
/*
 * This function is used below to decide if we have any more data to
 * send to the client.  If the store_status is STORE_PENDING, then we
 * do have more data to send.  If its STORE_OK, then
 * we continue checking.  If the object length is negative, then we
 * don't know the real length and must open the swap file to find out.
 * If the length is >= 0, then we compare it to the requested copy
 * offset.
 */
static int
storeClientNoMoreToSend(StoreEntry * e, store_client * sc)
{
    squid_off_t len;
    if (e->store_status == STORE_PENDING)
	return 0;
    if ((len = objectLen(e)) < 0)
	return 0;
    if (sc->copy_offset < len)
	return 0;
    return 1;
}
Exemple #4
0
static int 
swdaeSwapDirRoundRobin(cache_select_t *cache, const StoreEntry * e)
{
    static int dirn = 0;
    int i;  
    int load;
    SwapDir *sd;
    squid_off_t objsize = objectLen(e);
    for (i = 0; i < cache->dir.count; i++)
    {
        cache->dirn = cache->dirn % cache->dir.count;
        dirn = (int)cache->dir.items[cache->dirn];
        cache->dirn++;
        if (0 > dirn || dirn >= Config.cacheSwap.n_configured)
            continue;
        sd = &Config.cacheSwap.swapDirs[dirn];
        if (sd->flags.read_only)
        {
            debug(172, 5)("%s %s: %s read_only\n", PMOD_NAME, __func__, sd->path);
            continue;
        }
        if (sd->cur_size > sd->max_size)
        {
            debug(172, 5)("%s %s: %scur_size > sd->max_size\n", PMOD_NAME, __func__, sd->path);
            continue;
        }

        if (!swdaeSwapDirSwapDirSize(dirn, objsize))
        {
            debug(172,5)("%s %s objsize isn't Suitable %s %s\n",PMOD_NAME, __func__, sd->path, storeUrl(e));
            continue;
        }

        if (sd->checkobj(sd, e) == 0)
        {
            debug(172,5)("%s %s checkobj(sd,e) == 0\n", PMOD_NAME, sd->path);
            continue;
        }
        load = sd->checkload(sd, ST_OP_CREATE);
        if (load < 0 || load > 2000)
        {
            debug(172, 5)("%s %s Load too high %s\n", PMOD_NAME, sd->path, storeUrl(e));
            continue;
        }
        debug(172,3)("%s %s select [%s] store %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e));
        return dirn;
    }
    debug(172, 7)("%s %s nomatch %s\n", PMOD_NAME, __func__, storeUrl(e));
    return -1;
}
Exemple #5
0
static int 
swdaeSwapDirLeastLoad(cache_select_t *cache, const StoreEntry *e) 
{
    squid_off_t objsize;
    int most_free = 0, cur_free;
    squid_off_t least_objsize = -1; 
    int least_load = INT_MAX;
    int load;
    int dirn = 0;
    int dirn_no = -1; 
    int i;
    SwapDir *sd;

    /* Calculate the object size */
    objsize = objectLen(e);
    if (objsize != -1) 
        objsize += e->mem_obj->swap_hdr_sz;

    
    for (i = 0; i < cache->dir.count; i++)
    {   
        cache->dirn = cache->dirn % cache->dir.count;
        dirn = (int)cache->dir.items[cache->dirn];
        cache->dirn++;
        if (0 > dirn || dirn >= Config.cacheSwap.n_configured)
            continue;
        sd = &Config.cacheSwap.swapDirs[dirn];
        sd->flags.selected = 0;
        if (sd->flags.read_only)
        {
            debug(172, 5)("%s %s %s read_only\n", PMOD_NAME, __func__,sd->path);
            continue;
        }
        if (sd->cur_size > sd->max_size)
        {
            debug(172, 5)("%s %s %s cur_size > sd->max_size\n", PMOD_NAME, __func__, sd->path);
            continue;
        }
        if (!swdaeSwapDirSwapDirSize(dirn, objsize))
        {
            debug(172,5)("%s %s objsize isn't Suitable %s %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e));
            continue;
        }
        if (sd->checkobj(sd, e) == 0)
        {
            debug(172,5)("%s %s %s checkobj(sd,e) == 0\n",PMOD_NAME, __func__, sd->path);
            continue;
        }
        load = sd->checkload(sd, ST_OP_CREATE);
        if (load < 0 || load > 2000)
        {
            debug(172, 5)("%s %s %s Load too high %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e));
            continue;
        }
        if (load > least_load)
            continue;
        cur_free = sd->max_size - sd->cur_size;
        /* If the load is equal, then look in more details */
        if (load == least_load)
        {
            /* closest max_objsize fit */
            if (least_objsize != -1)
                if (sd->max_objsize > least_objsize || sd->max_objsize == -1)
                    continue;
            /* most free */
            if (cur_free < most_free)
                continue;
        }
        least_load = load;
        least_objsize = sd->max_objsize;
        most_free = cur_free;
        dirn_no = dirn;
    }
    if (dirn_no >= 0)
    {
        sd = &Config.cacheSwap.swapDirs[dirn_no];
        debug(172,5)("%s %s Select [%s] store %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e));
        Config.cacheSwap.swapDirs[dirn_no].flags.selected = 1;
    }else
    {
        debug(172,5)("%s %s Select Null store %s\n",PMOD_NAME, __func__, storeUrl(e));
    }
    return dirn_no;
}