Title: [219499] trunk/Source/WebKit
Revision
219499
Author
cdu...@apple.com
Date
2017-07-13 23:39:08 -0700 (Thu, 13 Jul 2017)

Log Message

Better deal with changes to the ResourceLoadStatisticsStore file on disk
https://bugs.webkit.org/show_bug.cgi?id=174487

Reviewed by Brent Fulgham.

Rename WebResourceLoadStatisticsStore's resetDataFromDecoder() to mergeWithDataFromDecoder()
and update it so that it actual merges the data from the disk with the one we have in memory,
instead of replacing it. This avoid data loss.

We leverage the existing WebResourceLoadStatisticsStore::mergeStatistics() to merge the
statistics.

To faciliate merging the operating dates, they are now represented as OperatingDate objects
instead of WallTime objects. OperatingDate only include date precision, no time information.
As a result, the merge 2 vectors of OperatingDate objects, we can:
1. Merge the 2 sorted vectors (using std::merge())
2. Get rid of duplicates (easy because of date-level precision)
3. Drop old dates until the vector has at most 30 items.

* UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp:
(WebKit::ResourceLoadStatisticsPersistentStorage::refreshMemoryStoreFromDisk):
(WebKit::ResourceLoadStatisticsPersistentStorage::populateMemoryStoreFromDisk):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::OperatingDate::fromWallTime):
(WebKit::OperatingDate::today):
(WebKit::OperatingDate::secondsSinceEpoch):
(WebKit::OperatingDate::operator==):
(WebKit::OperatingDate::operator<):
(WebKit::OperatingDate::operator<=):
(WebKit::OperatingDate::OperatingDate):
(WebKit::mergeOperatingDates):
(WebKit::WebResourceLoadStatisticsStore::createEncoderFromData):
(WebKit::WebResourceLoadStatisticsStore::mergeWithDataFromDecoder):
(WebKit::WebResourceLoadStatisticsStore::includeTodayAsOperatingDateIfNecessary):
(WebKit::WebResourceLoadStatisticsStore::hasStatisticsExpired):
* UIProcess/WebResourceLoadStatisticsStore.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (219498 => 219499)


--- trunk/Source/WebKit/ChangeLog	2017-07-14 06:18:15 UTC (rev 219498)
+++ trunk/Source/WebKit/ChangeLog	2017-07-14 06:39:08 UTC (rev 219499)
@@ -1,3 +1,42 @@
+2017-07-13  Chris Dumez  <cdu...@apple.com>
+
+        Better deal with changes to the ResourceLoadStatisticsStore file on disk
+        https://bugs.webkit.org/show_bug.cgi?id=174487
+
+        Reviewed by Brent Fulgham.
+
+        Rename WebResourceLoadStatisticsStore's resetDataFromDecoder() to mergeWithDataFromDecoder()
+        and update it so that it actual merges the data from the disk with the one we have in memory,
+        instead of replacing it. This avoid data loss.
+
+        We leverage the existing WebResourceLoadStatisticsStore::mergeStatistics() to merge the
+        statistics.
+
+        To faciliate merging the operating dates, they are now represented as OperatingDate objects
+        instead of WallTime objects. OperatingDate only include date precision, no time information.
+        As a result, the merge 2 vectors of OperatingDate objects, we can:
+        1. Merge the 2 sorted vectors (using std::merge())
+        2. Get rid of duplicates (easy because of date-level precision)
+        3. Drop old dates until the vector has at most 30 items.
+
+        * UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp:
+        (WebKit::ResourceLoadStatisticsPersistentStorage::refreshMemoryStoreFromDisk):
+        (WebKit::ResourceLoadStatisticsPersistentStorage::populateMemoryStoreFromDisk):
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::OperatingDate::fromWallTime):
+        (WebKit::OperatingDate::today):
+        (WebKit::OperatingDate::secondsSinceEpoch):
+        (WebKit::OperatingDate::operator==):
+        (WebKit::OperatingDate::operator<):
+        (WebKit::OperatingDate::operator<=):
+        (WebKit::OperatingDate::OperatingDate):
+        (WebKit::mergeOperatingDates):
+        (WebKit::WebResourceLoadStatisticsStore::createEncoderFromData):
+        (WebKit::WebResourceLoadStatisticsStore::mergeWithDataFromDecoder):
+        (WebKit::WebResourceLoadStatisticsStore::includeTodayAsOperatingDateIfNecessary):
+        (WebKit::WebResourceLoadStatisticsStore::hasStatisticsExpired):
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+
 2017-07-13  Dan Bernstein  <m...@apple.com>
 
         Removed empty project directories left behind after the rename

Modified: trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp (219498 => 219499)


--- trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp	2017-07-14 06:18:15 UTC (rev 219498)
+++ trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp	2017-07-14 06:39:08 UTC (rev 219499)
@@ -166,7 +166,7 @@
     if (!decoder)
         return;
 
-    m_memoryStore.resetDataFromDecoder(*decoder);
+    m_memoryStore.mergeWithDataFromDecoder(*decoder);
     m_lastStatisticsFileSyncTime = readTime;
 }
 
@@ -193,7 +193,8 @@
         return;
     }
 
-    m_memoryStore.resetDataFromDecoder(*decoder);
+    ASSERT_WITH_MESSAGE(m_memoryStore.isEmpty(), "This is the initial import so the store should be empty");
+    m_memoryStore.mergeWithDataFromDecoder(*decoder);
 
     m_lastStatisticsFileSyncTime = readTime;
 

Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp (219498 => 219499)


--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp	2017-07-14 06:18:15 UTC (rev 219498)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp	2017-07-14 06:39:08 UTC (rev 219499)
@@ -37,6 +37,7 @@
 #include <WebCore/KeyedCoding.h>
 #include <WebCore/ResourceLoadStatistics.h>
 #include <wtf/CrossThreadCopier.h>
+#include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 #include <wtf/NeverDestroyed.h>
 
@@ -77,6 +78,77 @@
     return dataTypes;
 }
 
+class OperatingDate {
+public:
+    OperatingDate() = default;
+
+    static OperatingDate fromWallTime(WallTime time)
+    {
+        double ms = time.secondsSinceEpoch().milliseconds();
+        int year = msToYear(ms);
+        int yearDay = dayInYear(ms, year);
+        int month = monthFromDayInYear(yearDay, isLeapYear(year));
+        int monthDay = dayInMonthFromDayInYear(yearDay, isLeapYear(year));
+
+        return OperatingDate { year, month, monthDay };
+    }
+
+    static OperatingDate today()
+    {
+        return OperatingDate::fromWallTime(WallTime::now());
+    }
+
+    Seconds secondsSinceEpoch() const
+    {
+        return Seconds { dateToDaysFrom1970(m_year, m_month, m_monthDay) * secondsPerDay };
+    }
+
+    bool operator==(const OperatingDate& other) const
+    {
+        return m_monthDay == other.m_monthDay && m_month == other.m_month && m_year == other.m_year;
+    }
+
+    bool operator<(const OperatingDate& other) const
+    {
+        return secondsSinceEpoch() < other.secondsSinceEpoch();
+    }
+
+    bool operator<=(const OperatingDate& other) const
+    {
+        return secondsSinceEpoch() <= other.secondsSinceEpoch();
+    }
+
+private:
+    OperatingDate(int year, int month, int monthDay)
+        : m_year(year)
+        , m_month(month)
+        , m_monthDay(monthDay)
+    { }
+
+    int m_year { 0 };
+    int m_month { 0 }; // [0, 11].
+    int m_monthDay { 0 }; // [1, 31].
+};
+
+static Vector<OperatingDate> mergeOperatingDates(const Vector<OperatingDate>& existingDates, Vector<OperatingDate>&& newDates)
+{
+    if (existingDates.isEmpty())
+        return WTFMove(newDates);
+
+    Vector<OperatingDate> mergedDates(existingDates.size() + newDates.size());
+
+    // Merge the two sorted vectors of dates.
+    std::merge(existingDates.begin(), existingDates.end(), newDates.begin(), newDates.end(), mergedDates.begin());
+    // Remove duplicate dates.
+    removeRepeatedElements(mergedDates);
+
+    // Drop old dates until the Vector size reaches operatingDatesWindow.
+    while (mergedDates.size() > operatingDatesWindow)
+        mergedDates.remove(0);
+
+    return mergedDates;
+}
+
 WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory, UpdateCookiePartitioningForDomainsHandler&& updateCookiePartitioningForDomainsHandler)
     : m_statisticsQueue(WorkQueue::create("WebResourceLoadStatisticsStore Process Data Queue", WorkQueue::Type::Serial, WorkQueue::QOS::Utility))
     , m_persistentStorage(*this, resourceLoadStatisticsDirectory)
@@ -478,7 +550,7 @@
         origin.value.encode(encoderInner);
     });
 
-    encoder->encodeObjects("operatingDates", m_operatingDates.begin(), m_operatingDates.end(), [](KeyedEncoder& encoderInner, WallTime date) {
+    encoder->encodeObjects("operatingDates", m_operatingDates.begin(), m_operatingDates.end(), [](KeyedEncoder& encoderInner, OperatingDate date) {
         encoderInner.encodeDouble("date", date.secondsSinceEpoch().value());
     });
 
@@ -485,12 +557,10 @@
     return encoder;
 }
 
-void WebResourceLoadStatisticsStore::resetDataFromDecoder(KeyedDecoder& decoder)
+void WebResourceLoadStatisticsStore::mergeWithDataFromDecoder(KeyedDecoder& decoder)
 {
     ASSERT(!RunLoop::isMain());
 
-    clearInMemory();
-
     unsigned versionOnDisk;
     if (!decoder.decodeUInt32("version", versionOnDisk))
         return;
@@ -512,22 +582,16 @@
     if (!succeeded)
         return;
 
-    Vector<String> prevalentResourceDomainsWithoutUserInteraction;
-    prevalentResourceDomainsWithoutUserInteraction.reserveInitialCapacity(loadedStatistics.size());
-    for (auto& statistics : loadedStatistics) {
-        if (statistics.isPrevalentResource && !statistics.hadUserInteraction) {
-            prevalentResourceDomainsWithoutUserInteraction.uncheckedAppend(statistics.highLevelDomain);
-            statistics.isMarkedForCookiePartitioning = true;
-        }
-        m_resourceStatisticsMap.add(statistics.highLevelDomain, WTFMove(statistics));
-    }
+    mergeStatistics(WTFMove(loadedStatistics));
+    updateCookiePartitioning();
 
-    succeeded = decoder.decodeObjects("operatingDates", m_operatingDates, [](KeyedDecoder& decoder, WallTime& wallTime) {
+    Vector<OperatingDate> operatingDates;
+    succeeded = decoder.decodeObjects("operatingDates", operatingDates, [](KeyedDecoder& decoder, OperatingDate& date) {
         double value;
         if (!decoder.decodeDouble("date", value))
             return false;
 
-        wallTime = WallTime::fromRawSeconds(value);
+        date = OperatingDate::fromWallTime(WallTime::fromRawSeconds(value));
         return true;
     });
 
@@ -534,7 +598,7 @@
     if (!succeeded)
         return;
 
-    updateCookiePartitioningForDomains({ }, prevalentResourceDomainsWithoutUserInteraction, ShouldClearFirst::Yes);
+    m_operatingDates = mergeOperatingDates(m_operatingDates, WTFMove(operatingDates));
 }
 
 void WebResourceLoadStatisticsStore::clearInMemory()
@@ -660,19 +724,20 @@
 
 void WebResourceLoadStatisticsStore::includeTodayAsOperatingDateIfNecessary()
 {
-    if (!m_operatingDates.isEmpty() && (WallTime::now() - m_operatingDates.last() < 24_h))
+    auto today = OperatingDate::today();
+    if (!m_operatingDates.isEmpty() && today <= m_operatingDates.last())
         return;
 
     while (m_operatingDates.size() >= operatingDatesWindow)
-        m_operatingDates.removeFirst();
+        m_operatingDates.remove(0);
 
-    m_operatingDates.append(WallTime::now());
+    m_operatingDates.append(today);
 }
 
 bool WebResourceLoadStatisticsStore::hasStatisticsExpired(const ResourceLoadStatistics& resourceStatistic) const
 {
     if (m_operatingDates.size() >= operatingDatesWindow) {
-        if (resourceStatistic.mostRecentUserInteractionTime < m_operatingDates.first())
+        if (OperatingDate::fromWallTime(resourceStatistic.mostRecentUserInteractionTime) < m_operatingDates.first())
             return true;
     }
 

Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h (219498 => 219499)


--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h	2017-07-14 06:18:15 UTC (rev 219498)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h	2017-07-14 06:39:08 UTC (rev 219499)
@@ -51,6 +51,7 @@
 
 namespace WebKit {
 
+class OperatingDate;
 class WebProcessProxy;
 
 enum class ShouldClearFirst;
@@ -113,7 +114,7 @@
     void resetParametersToDefaultValues();
 
     std::unique_ptr<WebCore::KeyedEncoder> createEncoderFromData() const;
-    void resetDataFromDecoder(WebCore::KeyedDecoder&);
+    void mergeWithDataFromDecoder(WebCore::KeyedDecoder&);
     void clearInMemory();
     void grandfatherExistingWebsiteData();
     
@@ -165,7 +166,7 @@
 #endif
     Ref<WTF::WorkQueue> m_statisticsQueue;
     ResourceLoadStatisticsPersistentStorage m_persistentStorage;
-    Deque<WTF::WallTime> m_operatingDates;
+    Vector<OperatingDate> m_operatingDates;
 
     UpdateCookiePartitioningForDomainsHandler m_updateCookiePartitioningForDomainsHandler;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to