summaryrefslogtreecommitdiff
path: root/src/lib/evas/cserve2/evas_cs2_client.c
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2013-07-31 20:29:41 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2013-10-28 15:47:13 +0900
commitf5d0f0aec37fae9e974ce1b5b2e518863297ba3f (patch)
tree98a6bdbd8c1cf296ebac3a400f8f661e324651e7 /src/lib/evas/cserve2/evas_cs2_client.c
parent08648ab2a5033da4f6c835c049238074802fb232 (diff)
evas/cserve2: Scan shared indexes in client side
Read Image descriptors from the shared arrays But, accessing the shared index can be a bit expensive, so try to read from the socket before scanning the index, without blocking.
Diffstat (limited to '')
-rw-r--r--src/lib/evas/cserve2/evas_cs2_client.c577
1 files changed, 323 insertions, 254 deletions
diff --git a/src/lib/evas/cserve2/evas_cs2_client.c b/src/lib/evas/cserve2/evas_cs2_client.c
index d7cd8147c5..5b8e463f10 100644
--- a/src/lib/evas/cserve2/evas_cs2_client.c
+++ b/src/lib/evas/cserve2/evas_cs2_client.c
@@ -17,6 +17,9 @@
17 17
18#ifdef EVAS_CSERVE2 18#ifdef EVAS_CSERVE2
19 19
20#define USE_SHARED_INDEX 1
21#define SHARED_INDEX_ADD_TO_HASH 1
22#define HKEY_LOAD_OPTS_STR_LEN 215
20typedef void (*Op_Callback)(void *data, const void *msg, int size); 23typedef void (*Op_Callback)(void *data, const void *msg, int size);
21 24
22struct _File_Entry { 25struct _File_Entry {
@@ -47,6 +50,8 @@ static Eina_List *_requests = NULL;
47static Index_Table _index; 50static Index_Table _index;
48static const char *_shared_string_get(int id); 51static const char *_shared_string_get(int id);
49static int _server_index_list_set(Msg_Base *data, int size); 52static int _server_index_list_set(Msg_Base *data, int size);
53static const File_Data *_shared_file_data_get_by_id(unsigned int id);
54static const Shm_Object *_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id);
50static const File_Data *_shared_image_entry_file_data_find(Image_Entry *ie); 55static const File_Data *_shared_image_entry_file_data_find(Image_Entry *ie);
51static const Image_Data *_shared_image_entry_image_data_find(Image_Entry *ie); 56static const Image_Data *_shared_image_entry_image_data_find(Image_Entry *ie);
52 57
@@ -902,10 +907,21 @@ int
902evas_cserve2_image_load_wait(Image_Entry *ie) 907evas_cserve2_image_load_wait(Image_Entry *ie)
903{ 908{
904 const File_Data *fd; 909 const File_Data *fd;
910 Eina_Bool failed;
911 unsigned int rrid, rid;
905 912
906 if (!ie) 913 if (!ie)
907 return CSERVE2_GENERIC; 914 return CSERVE2_GENERIC;
908 915
916 if (!ie->open_rid)
917 return CSERVE2_NONE;
918
919 rid = ie->open_rid;
920 rrid = _server_dispatch(&failed);
921 if (rid == rrid)
922 return CSERVE2_NONE;
923
924#if USE_SHARED_INDEX
909 fd = _shared_image_entry_file_data_find(ie); 925 fd = _shared_image_entry_file_data_find(ie);
910 if (fd) 926 if (fd)
911 { 927 {
@@ -919,6 +935,7 @@ evas_cserve2_image_load_wait(Image_Entry *ie)
919 ie->open_rid = 0; 935 ie->open_rid = 0;
920 return CSERVE2_NONE; 936 return CSERVE2_NONE;
921 } 937 }
938#endif
922 939
923 if (ie->open_rid) 940 if (ie->open_rid)
924 { 941 {
@@ -959,6 +976,7 @@ evas_cserve2_image_load_data_wait(Image_Entry *ie)
959 if (!ie) 976 if (!ie)
960 return CSERVE2_GENERIC; 977 return CSERVE2_GENERIC;
961 978
979#if USE_SHARED_INDEX
962 idata = _shared_image_entry_image_data_find(ie); 980 idata = _shared_image_entry_image_data_find(ie);
963 if (idata) 981 if (idata)
964 { 982 {
@@ -997,6 +1015,7 @@ evas_cserve2_image_load_data_wait(Image_Entry *ie)
997 ie->load_rid = 0; 1015 ie->load_rid = 0;
998 return CSERVE2_NONE; 1016 return CSERVE2_NONE;
999 } 1017 }
1018#endif
1000 1019
1001load_wait: 1020load_wait:
1002 if (ie->load_rid) 1021 if (ie->load_rid)
@@ -1607,6 +1626,7 @@ evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx, Font_Hint_F
1607 1626
1608// Fast access to shared index tables 1627// Fast access to shared index tables
1609 1628
1629static Eina_Bool _shared_index_remap_check(Shared_Index *si, int elemsize);
1610 1630
1611// Returns the number of correctly opened index arrays 1631// Returns the number of correctly opened index arrays
1612static int 1632static int
@@ -1614,7 +1634,6 @@ _server_index_list_set(Msg_Base *data, int size)
1614{ 1634{
1615 Msg_Index_List *msg = (Msg_Index_List *) data; 1635 Msg_Index_List *msg = (Msg_Index_List *) data;
1616 unsigned sz; 1636 unsigned sz;
1617 int ret = 0;
1618 1637
1619 // TODO #1: Check populate rule. 1638 // TODO #1: Check populate rule.
1620 // TODO #2: Protect memory for read-only access. 1639 // TODO #2: Protect memory for read-only access.
@@ -1627,276 +1646,162 @@ _server_index_list_set(Msg_Base *data, int size)
1627 return -1; 1646 return -1;
1628 } 1647 }
1629 1648
1630 // Reset index table 1649 if (_index.generation_id == msg->generation_id)
1631 if (_index.strings.index_file)
1632 { 1650 {
1633 if (_index.strings.index_header) 1651 ERR("New index generation_id is the same as before: %d",
1634 eina_file_map_free(_index.strings.index_file, 1652 _index.generation_id);
1635 (void *) _index.strings.index_header);
1636 eina_file_close(_index.strings.index_file);
1637 } 1653 }
1638 if (_index.strings.entries_file) 1654
1639 { 1655 _index.generation_id = msg->generation_id;
1640 if (_index.strings.index_header) 1656
1641 eina_file_map_free(_index.strings.entries_file, 1657 // 1. Strings (indexes and entries)
1642 (void *) _index.strings.index_header); 1658
1643 eina_file_close(_index.strings.entries_file); 1659 if (_index.strings_entries.data
1644 } 1660 && strncmp(_index.strings_entries.path, msg->strings_entries_path,
1645 if (_index.files.f) 1661 SHARED_BUFFER_PATH_MAX) != 0)
1646 {
1647 if (_index.files.header)
1648 eina_file_map_free(_index.files.f, (void *) _index.files.header);
1649 eina_file_close(_index.files.f);
1650 }
1651 if (_index.images.f)
1652 { 1662 {
1653 if (_index.images.header) 1663 DBG("Updating string entries shm to: '%s'", msg->strings_entries_path);
1654 eina_file_map_free(_index.images.f, (void *) _index.images.header); 1664 eina_file_map_free(_index.strings_entries.f, _index.strings_entries.data);
1655 eina_file_close(_index.images.f); 1665 eina_file_close(_index.strings_entries.f);
1666 _index.strings_entries.f = NULL;
1667 _index.strings_entries.data = NULL;
1656 } 1668 }
1657 if (_index.fonts.f) 1669
1670 if (_index.strings_index.data
1671 && strncmp(_index.strings_index.path, msg->strings_index_path,
1672 SHARED_BUFFER_PATH_MAX) != 0)
1658 { 1673 {
1659 if (_index.fonts.header) 1674 DBG("Updating string indexes shm to: '%s'", msg->strings_index_path);
1660 eina_file_map_free(_index.fonts.f, (void *) _index.fonts.header); 1675 eina_file_map_free(_index.strings_index.f, _index.strings_index.data);
1661 eina_file_close(_index.fonts.f); 1676 eina_file_close(_index.strings_index.f);
1677 _index.strings_index.f = NULL;
1678 _index.strings_index.data = NULL;
1662 } 1679 }
1663 1680
1664 // Open new indexes 1681 eina_strlcpy(_index.strings_entries.path, msg->strings_entries_path, SHARED_BUFFER_PATH_MAX);
1665 eina_strlcpy(_index.strings.index_path, msg->strings_index_path, 64); 1682 eina_strlcpy(_index.strings_index.path, msg->strings_index_path, SHARED_BUFFER_PATH_MAX);
1666 eina_strlcpy(_index.strings.entries_path, msg->strings_entries_path, 64);
1667 eina_strlcpy(_index.files.path, msg->files_index_path, 64);
1668 eina_strlcpy(_index.images.path, msg->images_index_path, 64);
1669 eina_strlcpy(_index.fonts.path, msg->fonts_index_path, 64);
1670 1683
1671 if (_index.strings.index_path[0] && _index.strings.entries_path[0]) 1684 if (!_index.strings_entries.data
1685 && _index.strings_entries.path[0]
1686 && _index.strings_index.path[0])
1672 { 1687 {
1673 _index.strings.index_file = eina_file_open(_index.strings.index_path, 1688 _index.strings_entries.f = eina_file_open(_index.strings_entries.path, EINA_TRUE);
1674 EINA_TRUE); 1689 _index.strings_entries.size = eina_file_size_get(_index.strings_entries.f);
1675 sz = eina_file_size_get(_index.strings.index_file); 1690 if (_index.strings_entries.size > 0)
1676 _index.strings.index_header = eina_file_map_all( 1691 _index.strings_entries.data = eina_file_map_all(_index.strings_entries.f, EINA_FILE_RANDOM);
1677 _index.strings.index_file, EINA_FILE_POPULATE); 1692
1678 if (_index.strings.index_header && sz > sizeof(Shared_Array_Header) 1693 if (!_index.strings_entries.data)
1679 && sz >= (_index.strings.index_header->count * sizeof(Index_Entry)
1680 + sizeof(Shared_Array_Header)))
1681 {
1682 _index.strings.indexes = (Index_Entry *)
1683 &(_index.strings.index_header[1]);
1684 _index.strings.entries_file = eina_file_open(
1685 _index.strings.entries_path, EINA_TRUE);
1686 _index.strings.entries_size = eina_file_size_get(
1687 _index.strings.entries_file);
1688 _index.strings.data = eina_file_map_all(
1689 _index.strings.entries_file, EINA_FILE_RANDOM);
1690 if (!_index.strings.entries_size || !_index.strings.data)
1691 goto strings_map_failed;
1692 DBG("Mapped shared string table with indexes in %s and data in %s",
1693 _index.strings.index_path, _index.strings.entries_path);
1694 }
1695 else
1696 { 1694 {
1697strings_map_failed: 1695 ERR("Could not map strings entries from: '%s'", _index.strings_entries.path);
1698 eina_file_map_free(_index.strings.entries_file, 1696 eina_file_close(_index.strings_entries.f);
1699 (void *) _index.strings.data); 1697 _index.strings_entries.f = NULL;
1700 eina_file_close(_index.strings.entries_file); 1698 _index.strings_entries.data = NULL;
1701 eina_file_map_free(_index.strings.index_file,
1702 (void *) _index.strings.index_header);
1703 eina_file_close(_index.strings.index_file);
1704 memset(&_index.strings, 0, sizeof(_index.strings));
1705 } 1699 }
1700 else DBG("Mapped string entries from %s", _index.strings_entries.path);
1706 } 1701 }
1707 1702
1708 if (_index.files.path[0]) 1703 if (_index.strings_entries.data &&
1704 (!_index.strings_index.data && _index.strings_index.path[0]))
1709 { 1705 {
1710 _index.files.f = eina_file_open(_index.files.path, EINA_TRUE); 1706 _index.strings_index.f = eina_file_open(_index.strings_index.path, EINA_TRUE);
1711 sz = eina_file_size_get(_index.files.f); 1707 sz = eina_file_size_get(_index.strings_index.f);
1712 if (sz < sizeof(Shared_Array_Header)) 1708 if (sz >= sizeof(Shared_Array_Header))
1709 _index.strings_index.data = eina_file_map_all(_index.strings_index.f, EINA_FILE_RANDOM);
1710
1711 if (_index.strings_index.data)
1713 { 1712 {
1714 ERR("Shared index for files is too small: %u", sz); 1713 DBG("Mapped string indexes from %s", _index.strings_index.path);
1715 eina_file_close(_index.files.f); 1714 sz = eina_file_size_get(_index.strings_index.f);
1716 _index.files.f = NULL; 1715 _index.strings_index.count = (sz - sizeof(Shared_Array_Header)) / sizeof(Index_Entry);
1716 if (_index.strings_index.count > _index.strings_index.header->count)
1717 {
1718 WRN("Detected larger index than advertised: %d > %d",
1719 _index.strings_index.count, _index.strings_index.header->count);
1720 _index.strings_index.count = _index.strings_index.header->count;
1721 }
1717 } 1722 }
1718 else 1723 else
1719 { 1724 {
1720 _index.files.header = eina_file_map_all(_index.files.f, 1725 ERR("Could not map string indexes from %s", _index.strings_index.path);
1721 EINA_FILE_POPULATE); 1726 eina_file_close(_index.strings_index.f);
1722 if (sz < (_index.files.header->count * sizeof(File_Data) 1727 eina_file_map_free(_index.strings_entries.f, _index.strings_entries.data);
1723 + sizeof(Shared_Array_Header))) 1728 eina_file_close(_index.strings_entries.f);
1724 { 1729 _index.strings_index.f = NULL;
1725 ERR("Shared index size does not match array size: %u / %u", 1730 _index.strings_entries.f = NULL;
1726 sz, _index.files.header->count); 1731 _index.strings_entries.data = NULL;
1727 eina_file_map_free(_index.files.f,
1728 (void *) _index.files.header);
1729 eina_file_close(_index.files.f);
1730 _index.files.f = NULL;
1731 _index.files.header = NULL;
1732 }
1733 else
1734 {
1735 _index.files.entries.fdata =
1736 (File_Data *) &(_index.files.header[1]);
1737 DBG("Mapped files shared index '%s' at %p: %u entries max",
1738 _index.files.path, _index.files.header,
1739 _index.files.header->count);
1740 ret++;
1741 }
1742 } 1732 }
1743 } 1733 }
1744 1734
1745 if (_index.images.path[0]) 1735 _shared_index_remap_check(&_index.strings_index, sizeof(Index_Entry));
1736 if (_index.strings_entries.data)
1746 { 1737 {
1747 _index.images.f = eina_file_open(_index.images.path, EINA_TRUE); 1738 if (eina_file_refresh(_index.strings_entries.f))
1748 sz = eina_file_size_get(_index.images.f);
1749 if (sz < sizeof(Shared_Array_Header))
1750 { 1739 {
1751 ERR("Shared index for images is too small: %u", sz); 1740 eina_file_map_free(_index.strings_entries.f, _index.strings_entries.data);
1752 eina_file_close(_index.images.f); 1741 _index.strings_entries.data = eina_file_map_all(_index.strings_entries.f, EINA_FILE_RANDOM);
1753 _index.images.f = NULL; 1742 _index.strings_entries.size = eina_file_size_get(_index.strings_entries.f);
1754 }
1755 else
1756 {
1757 int size = eina_file_size_get(_index.images.f);
1758 _index.images.header = eina_file_map_all(_index.images.f,
1759 EINA_FILE_POPULATE);
1760 if (sz < (_index.images.header->count * sizeof(Image_Data)
1761 + sizeof(Shared_Array_Header)))
1762 {
1763 ERR("Shared index size does not match array size: %u / %u",
1764 sz, _index.images.header->count);
1765 eina_file_map_free(_index.images.f,
1766 (void *) _index.images.header);
1767 eina_file_close(_index.images.f);
1768 _index.images.f = NULL;
1769 _index.images.header = NULL;
1770 }
1771 else
1772 {
1773 _index.images.count = (size - sizeof(Shared_Array_Header))
1774 / sizeof(Image_Data);
1775 _index.images.entries.idata =
1776 (Image_Data *) &(_index.images.header[1]);
1777 DBG("Mapped images shared index '%s' at %p: %u entries max",
1778 _index.images.path, _index.images.header,
1779 _index.images.header->count);
1780 ret++;
1781 }
1782 } 1743 }
1783 } 1744 }
1784 1745
1785 if (_index.fonts.path[0])
1786 ERR("Not implemented yet: fonts shared index");
1787 1746
1788 return ret; 1747 // 2. File indexes
1789}
1790 1748
1791// FIXME: Copy & paste from evas_cserve2_cache.c 1749 eina_strlcpy(_index.files.path, msg->files_index_path, SHARED_BUFFER_PATH_MAX);
1792static int 1750 _shared_index_remap_check(&_index.files, sizeof(File_Data));
1793_shm_object_id_cmp_cb(const void *data1, const void *data2)
1794{
1795 const Shm_Object *obj;
1796 unsigned int key;
1797 1751
1798 if (data1 == data2) return 0;
1799 if (!data1) return 1;
1800 if (!data2) return -1;
1801 1752
1802 obj = data1; 1753 // 3. Image indexes
1803 key = *((unsigned int *) data2); 1754
1804 if (obj->id == key) return 0; 1755 eina_strlcpy(_index.images.path, msg->images_index_path, SHARED_BUFFER_PATH_MAX);
1805 if (obj->id < key) 1756 _shared_index_remap_check(&_index.images, sizeof(Image_Data));
1806 return -1; 1757
1807 else 1758
1808 return +1; 1759 // 4. Font indexes
1760 // TODO
1761
1762 return 0;
1809} 1763}
1810 1764
1811// FIXME: (almost) copy & paste from evas_cserve2_cache.c 1765// FIXME: (almost) copy & paste from evas_cserve2_cache.c
1812static const char * 1766static const char *
1813_shared_string_get(int id) 1767_shared_string_get(int id)
1814{ 1768{
1815 const char *ret; 1769 Index_Entry *ie;
1816 const Index_Entry *ie = NULL;
1817 int k;
1818
1819 if (id <= 0) return NULL;
1820 if (!_index.strings.data) return NULL;
1821 1770
1822 // Binary search 1771 ie = (Index_Entry *)
1823 if (_index.strings.index_header->sortedidx > 0) 1772 _shared_index_item_get_by_id(&_index.strings_index, sizeof(*ie), id);
1824 {
1825 int low = 0;
1826 int high = _index.strings.index_header->sortedidx;
1827 int prev = -1;
1828 int r;
1829 k = high / 2;
1830 while (prev != k)
1831 {
1832 ie = &(_index.strings.indexes[k]);
1833 r = _shm_object_id_cmp_cb(ie, &id);
1834 if (!r)
1835 goto found;
1836 else if (r > 0)
1837 high = k;
1838 else
1839 low = k;
1840 prev = k;
1841 k = low + (high - low) / 2;
1842 }
1843 }
1844
1845 // Linear search O(n)
1846 k = _index.strings.index_header->sortedidx;
1847 for (; k < _index.strings.index_header->emptyidx; k++)
1848 {
1849 ie = &(_index.strings.indexes[k]);
1850 if (!_shm_object_id_cmp_cb(ie, &id))
1851 goto found;
1852 }
1853
1854 return NULL;
1855
1856found:
1857 if (!ie) return NULL; 1773 if (!ie) return NULL;
1774 if (ie->offset < 0) return NULL;
1858 if (!ie->refcount) return NULL; 1775 if (!ie->refcount) return NULL;
1859 if (ie->length + ie->offset > (int) _index.strings.entries_size) 1776 if (ie->offset + ie->length > _index.strings_entries.size) return NULL;
1860 return NULL;
1861 1777
1862 ret = _index.strings.data + ie->offset; 1778 return _index.strings_entries.data + ie->offset;
1863 return ret;
1864} 1779}
1865 1780
1866static inline Eina_Bool 1781#define SHARED_INDEX_CHECK(si, typ) \
1867_shared_image_entry_file_data_match(Image_Entry *ie, const File_Data *fd) 1782 do { if (!_shared_index_remap_check(&(si), sizeof(typ))) { \
1868{ 1783 CRIT("Failed to remap index"); return NULL; } } while (0)
1869 const char *path, *key, *loader;
1870
1871 if (!fd || !ie) return EINA_FALSE;
1872 if (!ie->file && !ie->key)
1873 return EINA_FALSE;
1874 1784
1875 path = _shared_string_get(fd->path); 1785static const char *
1876 key = _shared_string_get(fd->key); 1786_shared_file_data_hkey_get(char *hkey, const char *file, const char *key,
1877 loader = _shared_string_get(fd->loader_data); 1787 size_t hkey_size)
1788{
1789 size_t keylen, filelen;
1878 1790
1879 if (!path && ie->file) 1791 if (key) keylen = strlen(key) + 1;
1880 return EINA_FALSE; 1792 filelen = strlen(file);
1881 if (ie->file && strcmp(path, ie->file))
1882 return EINA_FALSE;
1883 1793
1884 if (!key && ie->key) 1794 if (filelen + keylen + 1 > hkey_size)
1885 return EINA_FALSE; 1795 return NULL;
1886 if (ie->key && strcmp(key, ie->key))
1887 return EINA_FALSE;
1888 1796
1889 /* 1797 memcpy(hkey, file, filelen);
1890 if (!loader && ie->loader_data) 1798 hkey[filelen] = ':';
1891 return EINA_FALSE; 1799 if (key)
1892 if (strcmp(loader, ie->loader_data)) 1800 memcpy(hkey + filelen + 1, key, keylen);
1893 return EINA_FALSE; 1801 else
1894 */ 1802 memcpy(hkey + filelen + 1, "(null)", 7);
1895 1803
1896 // Check w,h ? 1804 return hkey;
1897 // Not sure which load opts should be checked here
1898 DBG("Found a match for %s:%s", ie->file, ie->key);
1899 return EINA_TRUE;
1900} 1805}
1901 1806
1902static const File_Data * 1807static const File_Data *
@@ -1904,32 +1809,122 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
1904{ 1809{
1905 const File_Data *fdata = NULL; 1810 const File_Data *fdata = NULL;
1906 File_Entry *fe; 1811 File_Entry *fe;
1812 Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
1813 char hkey[PATH_MAX];
1907 int k; 1814 int k;
1908 1815
1909 DBG("Trying to find if image '%s:%s' is already opened by cserve2", 1816 DBG("Trying to find if image '%s:%s' is already opened by cserve2",
1910 ie->file, ie->key); 1817 ie->file, ie->key);
1911 1818
1912 if (!_index.files.entries.fdata) 1819 SHARED_INDEX_CHECK(_index.files, File_Data);
1820
1821 if (!_index.strings_index.header || !_index.strings_entries.data)
1822 return NULL;
1823
1824 if (!_index.files.header || !_index.files.entries.fdata)
1913 return NULL; 1825 return NULL;
1914 1826
1915#warning FIXME Use safe count 1827 // Direct access
1916 for (k = 0; k < _index.files.header->count; k++) 1828 fe = ie->data1;
1829 if (fe->server_file_id)
1830 {
1831 if ((fdata = _shared_file_data_get_by_id(fe->server_file_id)) != NULL)
1832 return fdata;
1833 }
1834
1835 // Check hash
1836 _shared_file_data_hkey_get(hkey, ie->file, ie->key, PATH_MAX);
1837 fdata = eina_hash_find(_index.files.entries_by_hkey, hkey);
1838 if (fdata)
1839 return fdata;
1840
1841 // Scan shared index
1842 for (k = _index.files.last_entry_in_hash;
1843 k < _index.files.count && k < _index.files.header->emptyidx; k++)
1917 { 1844 {
1918 const File_Data *fd = &(_index.files.entries.fdata[k]); 1845 const char *file, *key;
1919 if (!fd->id) return NULL; 1846 const File_Data *fd;
1847 char fd_hkey[PATH_MAX];
1848
1849 fd = &(_index.files.entries.fdata[k]);
1850 if (!fd->id) break;
1920 if (!fd->refcount) continue; 1851 if (!fd->refcount) continue;
1921 1852
1922 if (_shared_image_entry_file_data_match(ie, fd)) 1853 file = _shared_string_get(fd->path);
1854 if (!file)
1923 { 1855 {
1924 fdata = fd; 1856 ERR("Could not find filename for file %d", fd->id);
1925 break; 1857 add_to_hash = EINA_FALSE;
1858 continue;
1926 } 1859 }
1860 key = _shared_string_get(fd->key);
1861
1862 _shared_file_data_hkey_get(fd_hkey, file, key, PATH_MAX);
1863
1864 if (add_to_hash)
1865 {
1866 eina_hash_add(_index.files.entries_by_hkey, fd_hkey, fd);
1867 _index.files.last_entry_in_hash = k;
1868 }
1869
1870 if (!strcmp(hkey, fd_hkey))
1871 return fd;
1927 } 1872 }
1928 1873
1929 DBG("Found file data for %s:%s: %d", ie->file, ie->key, fdata->id); 1874 return NULL;
1930 fe = ie->data1; 1875}
1931 fe->server_file_id = fdata->id; 1876
1932 return fdata; 1877static const Shm_Object *
1878_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id)
1879{
1880 const Shm_Object *obj;
1881 const char *base;
1882 int low = 0, high, start_high;
1883 int cur;
1884
1885 if (!si || elemsize <= 0 || !id)
1886 return NULL;
1887
1888 // FIXME: HACK (consider all arrays always sorted by id)
1889 high = si->header->emptyidx; // Should be si->header->sortedidx
1890
1891 if (high > si->count)
1892 high = si->count;
1893
1894 base = si->data + sizeof(Shared_Array_Header);
1895
1896 // Binary search
1897 start_high = high;
1898 while(high != low)
1899 {
1900 cur = low + ((high - low) / 2);
1901 obj = (Shm_Object *) (base + (elemsize * cur));
1902 if (obj->id == id)
1903 return obj;
1904 if (obj->id < id)
1905 low = cur + 1;
1906 else
1907 high = cur;
1908 }
1909
1910 // Linear search
1911 for (cur = start_high; cur < si->count; cur++)
1912 {
1913 obj = (Shm_Object *) (base + (elemsize * cur));
1914 if (!obj->id)
1915 return NULL;
1916 if (obj->id == id)
1917 return obj;
1918 }
1919
1920 return NULL;
1921}
1922
1923static const File_Data *
1924_shared_file_data_get_by_id(unsigned int id)
1925{
1926 return (const File_Data *)
1927 _shared_index_item_get_by_id(&_index.files, sizeof(File_Data), id);
1933} 1928}
1934 1929
1935static inline Eina_Bool 1930static inline Eina_Bool
@@ -1945,9 +1940,6 @@ _shared_image_entry_image_data_match(Image_Entry *ie, const Image_Data *id)
1945 return EINA_FALSE; 1940 return EINA_FALSE;
1946} 1941}
1947 1942
1948#define SHARED_INDEX_CHECK(si, typ) \
1949 if (!_shared_index_remap_check(&(si), sizeof(typ))) return NULL
1950
1951static Eina_Bool 1943static Eina_Bool
1952_shared_index_remap_check(Shared_Index *si, int elemsize) 1944_shared_index_remap_check(Shared_Index *si, int elemsize)
1953{ 1945{
@@ -1957,22 +1949,39 @@ _shared_index_remap_check(Shared_Index *si, int elemsize)
1957 // Note: all checks are unlikely to be true. 1949 // Note: all checks are unlikely to be true.
1958 1950
1959 if (!si || elemsize <= 0) return EINA_FALSE; 1951 if (!si || elemsize <= 0) return EINA_FALSE;
1952
1960 if (si->generation_id != _index.generation_id) 1953 if (si->generation_id != _index.generation_id)
1961 { 1954 {
1962 DBG("Generation ID changed."); 1955 DBG("Generation ID changed from %d to %d.",
1963 if (si->f && si->data) 1956 si->generation_id, _index.generation_id);
1957 if (si->f)
1964 { 1958 {
1965 if (eina_file_refresh(si->f)) 1959 if (strncmp(si->path, eina_file_filename_get(si->f),
1960 SHARED_BUFFER_PATH_MAX) != 0)
1966 { 1961 {
1967 DBG("Remapping index."); 1962 DBG("Index file changed. Closing and reopening.");
1968 eina_file_map_free(si->f, si->data); 1963 eina_file_map_free(si->f, si->data);
1964 eina_file_close(si->f);
1965 si->f = NULL;
1969 si->data = NULL; 1966 si->data = NULL;
1970 } 1967 }
1971 } 1968 else
1972 else if (si->f) 1969 {
1973 { 1970 if (si->data)
1974 eina_file_close(si->f); 1971 {
1975 si->f = NULL; 1972 if (eina_file_refresh(si->f))
1973 {
1974 DBG("Remapping index.");
1975 eina_file_map_free(si->f, si->data);
1976 si->data = NULL;
1977 }
1978 }
1979 else
1980 {
1981 eina_file_close(si->f);
1982 si->f = NULL;
1983 }
1984 }
1976 } 1985 }
1977 si->generation_id = _index.generation_id; 1986 si->generation_id = _index.generation_id;
1978 } 1987 }
@@ -2039,6 +2048,7 @@ _shared_index_remap_check(Shared_Index *si, int elemsize)
2039 if (si->entries_by_hkey) eina_hash_free_buckets(si->entries_by_hkey); 2048 if (si->entries_by_hkey) eina_hash_free_buckets(si->entries_by_hkey);
2040 else si->entries_by_hkey = eina_hash_string_small_new(NULL); 2049 else si->entries_by_hkey = eina_hash_string_small_new(NULL);
2041 si->last_entry_in_hash = 0; 2050 si->last_entry_in_hash = 0;
2051 si->entries.p = si->data + sizeof(Shared_Array_Header);
2042 } 2052 }
2043 2053
2044 return EINA_TRUE; 2054 return EINA_TRUE;
@@ -2048,16 +2058,28 @@ static const Image_Data *
2048_shared_image_entry_image_data_find(Image_Entry *ie) 2058_shared_image_entry_image_data_find(Image_Entry *ie)
2049{ 2059{
2050 const Image_Data *idata = NULL; 2060 const Image_Data *idata = NULL;
2061 const char *shmpath;
2051 File_Entry *fe; 2062 File_Entry *fe;
2052 unsigned int file_id = 0; 2063 unsigned int file_id = 0;
2064 Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
2053 int k; 2065 int k;
2054 2066
2067
2055 DBG("Trying to find if image '%s:%s' is already loaded by cserve2", 2068 DBG("Trying to find if image '%s:%s' is already loaded by cserve2",
2056 ie->file, ie->key); 2069 ie->file, ie->key);
2057 2070
2071 if (!_index.strings_entries.data || !_index.strings_index.data)
2072 return NULL;
2073
2058 if (!_index.images.entries.idata || !_index.images.count) 2074 if (!_index.images.entries.idata || !_index.images.count)
2059 return NULL; 2075 return NULL;
2060 2076
2077 if (!ie->cache_key)
2078 {
2079 CRIT("Looking for an image in remote cache without hash key?");
2080 return NULL;
2081 }
2082
2061 fe = ie->data1; 2083 fe = ie->data1;
2062 if (fe && fe->server_file_id) 2084 if (fe && fe->server_file_id)
2063 file_id = fe->server_file_id; 2085 file_id = fe->server_file_id;
@@ -2074,32 +2096,79 @@ _shared_image_entry_image_data_find(Image_Entry *ie)
2074 2096
2075 SHARED_INDEX_CHECK(_index.images, Image_Data); 2097 SHARED_INDEX_CHECK(_index.images, Image_Data);
2076 2098
2099 // Find in known entries hash. O(log n)
2100 DBG("Looking for %s in hash", ie->cache_key);
2101 idata = (const Image_Data *)
2102 eina_hash_find(_index.images.entries_by_hkey, ie->cache_key);
2103 if (idata)
2104 {
2105 ERR("Image found in shared index (by cache_key).");
2106 goto found;
2107 }
2108
2109 // Linear search in non-hashed entries. O(n)
2077 DBG("Looking for loaded image with file id %d", file_id); 2110 DBG("Looking for loaded image with file id %d", file_id);
2078 for (k = 0; k < _index.images.count; k++) 2111 for (k = _index.images.last_entry_in_hash; k < _index.images.count; k++)
2079 { 2112 {
2113 const char *file, *key;
2114 size_t keylen, filelen;
2115 const File_Data *fd;
2116 char *hkey;
2080 const Image_Data *id = &(_index.images.entries.idata[k]); 2117 const Image_Data *id = &(_index.images.entries.idata[k]);
2118
2081 if (!id->id) return NULL; 2119 if (!id->id) return NULL;
2082 if (!id->refcount) continue; 2120 if (!id->refcount) continue;
2121
2122 if (add_to_hash)
2123 {
2124 fd = _shared_file_data_get_by_id(id->file_id);
2125 if (!fd)
2126 {
2127 ERR("Did not find file data for %d", id->file_id);
2128 add_to_hash = EINA_FALSE;
2129 continue;
2130 }
2131
2132 key = _shared_string_get(fd->key);
2133 file = _shared_string_get(fd->path);
2134 if (!file)
2135 {
2136 ERR("No filename for file %d", fd->id);
2137 add_to_hash = EINA_FALSE;
2138 continue;
2139 }
2140 keylen = key ? strlen(key) : 0;
2141 filelen = strlen(file);
2142
2143 hkey = alloca(filelen + keylen + HKEY_LOAD_OPTS_STR_LEN);
2144 evas_cache2_image_cache_key_create(hkey, file, filelen,
2145 key, keylen, &id->opts);
2146 eina_hash_add(_index.images.entries_by_hkey, hkey, id);
2147 _index.images.last_entry_in_hash = k;
2148 }
2149
2083 if (id->file_id != file_id) continue; 2150 if (id->file_id != file_id) continue;
2084 2151
2085 if (_shared_image_entry_image_data_match(ie, id)) 2152 if (_shared_image_entry_image_data_match(ie, id))
2086 { 2153 {
2087 idata = id; 2154 idata = id;
2088 break; 2155 goto found;
2089 } 2156 }
2090 } 2157 }
2091 2158
2092 if (!idata) 2159 if (!idata)
2093 return NULL; 2160 return NULL;
2094 2161
2095 if (!_shared_string_get(idata->shm_id)) 2162found:
2163 shmpath = _shared_string_get(idata->shm_id);
2164 if (!shmpath)
2096 { 2165 {
2097 ERR("Found image but it is not loaded yet: %d (doload %d shm %s)", 2166 ERR("Found image but it is not loaded yet: %d (doload %d)",
2098 idata->id, idata->doload, _shared_string_get(idata->shm_id)); 2167 idata->id, idata->doload);
2099 return NULL; 2168 return NULL;
2100 } 2169 }
2101 2170
2102 DBG("Found image, loaded, in shm %s", _shared_string_get(idata->shm_id)); 2171 DBG("Found image, loaded, in shm %s", shmpath);
2103 return idata; 2172 return idata;
2104} 2173}
2105 2174