typedef struct _Shared_Array Shared_Array;
typedef struct _Shared_Mempool Shared_Mempool;
-typedef Eina_Bool (* Shared_Array_Repack_Skip_Cb) (Shared_Array *, const void *);
+typedef Eina_Bool (* Shared_Array_Repack_Skip_Cb) (Shared_Array *sa,
+ const void *elem,
+ void *user_data);
// Shared arrays (arrays of fixed size object)
Shared_Array *cserve2_shared_array_new(int tag, int elemsize, int initcount);
void *cserve2_shared_array_item_data_get(Shared_Array *sa, int elemid);
Shared_Array *cserve2_shared_array_repack(Shared_Array *sa,
Shared_Array_Repack_Skip_Cb skip,
- Eina_Compare_Cb cmp);
+ Eina_Compare_Cb cmp, void *user_data);
int cserve2_shared_array_item_find(Shared_Array *sa, void *data,
Eina_Compare_Cb cmp);
void *cserve2_shared_array_item_data_find(Shared_Array *sa, void *data,
};
static unsigned int _entry_id = 0;
+static unsigned int _freed_entry_count = 0;
+
static Shared_Array *_file_data_array = NULL;
static Eina_Hash *file_ids = NULL; // maps path + key --> file_id
static int
-_shm_object_id_find_cb(const void *data1, const void *data2)
+_shm_object_id_cmp_cb(const void *data1, const void *data2)
{
const Shm_Object *obj;
unsigned int key;
File_Data *fd;
fd = cserve2_shared_array_item_data_find(_file_data_array, &file_id,
- _shm_object_id_find_cb);
+ _shm_object_id_cmp_cb);
if (fd && !fd->refcount)
{
ERR("Can not access object %u with refcount 0", file_id);
return NULL;
}
+ else if (!fd)
+ ERR("Could not find file %u", file_id);
return fd;
}
return (File_Entry *) e;
}
+static Eina_Bool
+_repack_skip_cb(Shared_Array *sa EINA_UNUSED, const void *elem,
+ void *user_data EINA_UNUSED)
+{
+ const File_Data *fd = elem;
+ return (!fd->refcount);
+}
+
+static void
+_repack()
+{
+ Shared_Array *sa;
+ int count;
+
+ count = cserve2_shared_array_size_get(_file_data_array);
+ if (count <= 0) return;
+
+ // Repack when we have 10% fragmentation over the whole shm buffer
+ if (_freed_entry_count > 100 ||
+ ((_freed_entry_count * 100) / count >= 10))
+ {
+ DBG("Repacking file data array: %s",
+ cserve2_shared_array_name_get(_file_data_array));
+
+ sa = cserve2_shared_array_repack(_file_data_array,
+ _repack_skip_cb,
+ _shm_object_id_cmp_cb, NULL);
+ if (!sa)
+ {
+ ERR("Failed to repack array. Keeping previous references!");
+ return;
+ }
+
+ cserve2_shared_array_del(_file_data_array);
+ _freed_entry_count = 0;
+ _file_data_array = sa;
+ }
+}
+
static Msg_Opened *
_image_opened_msg_create(File_Data *fd, int *size)
fd = _file_data_find(ASENTRY(fentry)->id);
_file_id_free(fd);
- _file_entry_free(fentry);
_file_data_free(fd);
+ _file_entry_free(fentry);
+
+ _freed_entry_count++;
+ _repack();
}
static void
if (fd)
{
- if (fd->invalid)
- {
- _file_entry_free(fentry);
- _file_data_free(fd);
- }
- else if (!fentry->images)
+ // FIXME: Check difference with master (2 cases vs. only one)
+ if (fd->invalid || !fentry->images)
eina_hash_del_by_key(file_entries, &entry->id);
}
else
ASENTRY(fentry)->request = NULL;
}
if (!fentry->images && !ASENTRY(fentry)->references)
- {
- _file_entry_free(fentry);
- _file_data_free(fd);
- }
+ _hash_file_entry_free(fentry);
}
eina_hash_del_by_key(file_watch, fw->path);
Shared_Array *
cserve2_shared_array_repack(Shared_Array *sa,
Shared_Array_Repack_Skip_Cb skip,
- Eina_Compare_Cb cmp)
+ Eina_Compare_Cb cmp,
+ void *user_data)
{
Eina_List *l = NULL;
Shared_Array *sa2;
for (k = 0; k < sa->header->emptyidx; k++)
{
const char *data = srcdata + k * elemsize;
- if (skip(sa, data)) continue;
+ if (skip(sa, data, user_data)) continue;
l = eina_list_sorted_insert(l, cmp, data);
newcount++;
}
const char *data = eina_list_data_get(l);
l = eina_list_remove_list(l, l);
memcpy(dstdata, data, elemsize);
+ dstdata += elemsize;
}
// Finalize & return