Esempio n. 1
0
static PyObject *
range_item(rangeobject *r, Py_ssize_t i)
{
    Py_ssize_t len = range_length(r);
    PyObject *rem, *incr, *result;

    /* XXX(nnorwitz): should negative indices be supported? */
    /* XXX(nnorwitz): should support range[x] where x > PY_SSIZE_T_MAX? */
    if (i < 0 || i >= len) {
        if (!PyErr_Occurred())
            PyErr_SetString(PyExc_IndexError,
                            "range object index out of range");
        return NULL;
    }

    /* XXX(nnorwitz): optimize for short ints. */
    rem = PyLong_FromSsize_t(i);
    if (!rem)
        return NULL;
    incr = PyNumber_Multiply(rem, r->step);
    Py_DECREF(rem);
    if (!incr)
        return NULL;
    result = PyNumber_Add(r->start, incr);
    Py_DECREF(incr);
    return result;
}
static void clean_cpu_cache(struct cach_buf *buf, struct cach_range *range)
{
	struct cach_range intersection;

	intersect_range(&buf->range_dirty_in_cpu_cache, range, &intersection);
	if (is_non_empty_range(&intersection)) {
		bool cleaned_everything;

		expand_range_2_edge(&intersection,
					&buf->range_dirty_in_cpu_cache);

		clean_cpu_dcache(
				offset_2_vaddr(buf, intersection.start),
				offset_2_paddr(buf, intersection.start),
				range_length(&intersection),
				buf->cache_settings &
					HWMEM_ALLOC_HINT_INNER_CACHE_ONLY,
							&cleaned_everything);

		if (cleaned_everything)
			null_range(&buf->range_dirty_in_cpu_cache);
		else
			shrink_range(&buf->range_dirty_in_cpu_cache,
								&intersection);
	}
}
static void flush_cpu_cache(struct cach_buf *buf, struct cach_range *range)
{
	struct cach_range intersection;

	intersect_range(&buf->range_in_cpu_cache, range, &intersection);
	if (is_non_empty_range(&intersection)) {
		bool flushed_everything;

		expand_range_2_edge(&intersection, &buf->range_in_cpu_cache);

		flush_cpu_dcache(
				offset_2_vaddr(buf, intersection.start),
				offset_2_paddr(buf, intersection.start),
				range_length(&intersection),
				buf->cache_settings &
					HWMEM_ALLOC_HINT_INNER_CACHE_ONLY,
							&flushed_everything);

		if (flushed_everything) {
			if (!speculative_data_prefetch())
				null_range(&buf->range_in_cpu_cache);
			null_range(&buf->range_dirty_in_cpu_cache);
			null_range(&buf->range_invalid_in_cpu_cache);
		} else {
			if (!speculative_data_prefetch())
				shrink_range(&buf->range_in_cpu_cache,
							 &intersection);
			shrink_range(&buf->range_dirty_in_cpu_cache,
								&intersection);
			shrink_range(&buf->range_invalid_in_cpu_cache,
								&intersection);
		}
	}
}
Esempio n. 4
0
guint64 cache_mng_get_file_length (CacheMng *cmng, fuse_ino_t ino)
{
    struct _CacheEntry *entry;

    entry = g_hash_table_lookup (cmng->h_entries, GUINT_TO_POINTER (ino));
    if (!entry)
        return 0;

    return range_length (entry->avail_range);
}
Esempio n. 5
0
// removes file from local storage
void cache_mng_remove_file (CacheMng *cmng, fuse_ino_t ino)
{
    struct _CacheEntry *entry;
    char path[PATH_MAX];

    entry = g_hash_table_lookup (cmng->h_entries, GUINT_TO_POINTER (ino));
    if (entry) {
        cmng->size -= range_length (entry->avail_range);
        g_queue_delete_link (cmng->q_lru, entry->ll_lru);
        g_hash_table_remove (cmng->h_entries, GUINT_TO_POINTER (ino));
        cache_mng_file_name (cmng, path, sizeof (path), ino);
        unlink (path);
        LOG_debug (CMNG_LOG, INO_H"Entry is removed", INO_T (ino));
    } else {
        LOG_debug (CMNG_LOG, INO_H"Entry not found", INO_T (ino));
    }
}
Esempio n. 6
0
/*{{{ get_stats*/
void cache_mng_get_stats (CacheMng *cmng, guint32 *entries_num, guint64 *total_size, guint64 *cache_hits, guint64 *cache_miss)
{
    GHashTableIter iter;
    struct _CacheEntry *entry;
    gpointer value;

    *entries_num = g_hash_table_size (cmng->h_entries);
    *cache_hits = cmng->cache_hits;
    *cache_miss = cmng->cache_miss;
    *total_size = 0;

    g_hash_table_iter_init (&iter, cmng->h_entries);
    while (g_hash_table_iter_next (&iter, NULL, &value)) {
        entry = (struct _CacheEntry *) value;
        *total_size = *total_size + range_length (entry->avail_range);
    }

}/*}}}*/
static void invalidate_cpu_cache(struct cach_buf *buf, struct cach_range *range)
{
	struct cach_range intersection;

	intersect_range(&buf->range_invalid_in_cpu_cache, range,
								&intersection);
	if (is_non_empty_range(&intersection)) {
		bool flushed_everything;

		expand_range_2_edge(&intersection,
					&buf->range_invalid_in_cpu_cache);

		/*
		 * Cache handler never uses invalidate to discard data in the
		 * cache so we can use flush instead which is considerably
		 * faster for large buffers.
		 */
		flush_cpu_dcache(
				offset_2_vaddr(buf, intersection.start),
				offset_2_paddr(buf, intersection.start),
				range_length(&intersection),
				buf->cache_settings &
					HWMEM_ALLOC_HINT_INNER_CACHE_ONLY,
							&flushed_everything);

		if (flushed_everything) {
			null_range(&buf->range_invalid_in_cpu_cache);
			null_range(&buf->range_dirty_in_cpu_cache);
		} else {
			/*
			 * No need to shrink range_in_cpu_cache as invalidate
			 * is only used when we can't keep track of what's in
			 * the CPU cache.
			 */
			shrink_range(&buf->range_invalid_in_cpu_cache,
								&intersection);
		}
	}
}
Esempio n. 8
0
// store file buffer into local storage
// if success == TRUE then "buf" successfuly stored on disc
void cache_mng_store_file_buf (CacheMng *cmng, fuse_ino_t ino, size_t size, off_t off, unsigned char *buf,
    cache_mng_on_store_file_buf_cb on_store_file_buf_cb, void *ctx)
{
    struct _CacheContext *context;
    struct _CacheEntry *entry;
    ssize_t res;
    int fd;
    char path[PATH_MAX];
    guint64 old_length, new_length;
    guint64 range_size;
    time_t now;

    range_size = (guint64)(off + size);

    // limit the number of cache checks
    now = time (NULL);
    if (cmng->check_time < now && now - cmng->check_time >= 10) {
        // remove data until we have at least size bytes of max_size left
        while (cmng->max_size < cmng->size + size && g_queue_peek_tail (cmng->q_lru)) {
            entry = (struct _CacheEntry *) g_queue_peek_tail (cmng->q_lru);

            cache_mng_remove_file (cmng, entry->ino);
        }
        cmng->check_time = now;
    }

    context = cache_context_create (size, ctx);
    context->cb.store_cb = on_store_file_buf_cb;

    cache_mng_file_name (cmng, path, sizeof (path), ino);
    fd = open (path, O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fd < 0) {
        LOG_err (CMNG_LOG, INO_H"Failed to create / open file for writing! Path: %s", INO_T (ino), path);
        if (context->cb.store_cb)
            context->cb.store_cb (FALSE, context->user_ctx);
        cache_context_destroy (context);
        return;
    }
    res = pwrite(fd, buf, size, off);
    close (fd);

    entry = g_hash_table_lookup (cmng->h_entries, GUINT_TO_POINTER (ino));

    if (!entry) {
        entry = cache_entry_create (ino);
        g_queue_push_head (cmng->q_lru, entry);
        entry->ll_lru = g_queue_peek_head_link (cmng->q_lru);
        g_hash_table_insert (cmng->h_entries, GUINT_TO_POINTER (ino), entry);
    }

    old_length = range_length (entry->avail_range);
    range_add (entry->avail_range, off, range_size);
    new_length = range_length (entry->avail_range);
    if (new_length >= old_length)
        cmng->size += new_length - old_length;
    else {
        LOG_err (CMNG_LOG, INO_H"New length is less than the old length !: %"G_GUINT64_FORMAT" <= %"G_GUINT64_FORMAT, 
            INO_T (ino), new_length, old_length);
    }
    
    // update modification time
    entry->modification_time = time (NULL);
   
    context->success = (res == (ssize_t) size);

    LOG_debug (CMNG_LOG, INO_H"Written [%"OFF_FMT":%zu] bytes, result: %s", 
        INO_T (ino), off, size, context->success ? "OK" : "Failed");

    context->ev = event_new (application_get_evbase (cmng->app), -1,  0,
                    cache_write_cb, context);
    // fire this event at once
    event_active (context->ev, 0, 0);
    event_add (context->ev, NULL);
}