LCOV - code coverage report
Current view: directory - toolkit/components/url-classifier - nsUrlClassifierPrefixSet.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 261 177 67.8 %
Date: 2012-04-21 Functions: 32 21 65.6 %

       1                 : //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 et sw=2 tw=80: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Url Classifier code
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * the Mozilla Foundation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2011
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Gian-Carlo Pascutto <gpascutto@mozilla.com>
      25                 :  *   Mehdi Mulani <mars.martian+bugmail@gmail.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsAutoPtr.h"
      42                 : #include "nsCOMPtr.h"
      43                 : #include "nsDebug.h"
      44                 : #include "nsTArray.h"
      45                 : #include "nsString.h"
      46                 : #include "nsUrlClassifierPrefixSet.h"
      47                 : #include "nsIUrlClassifierPrefixSet.h"
      48                 : #include "nsIRandomGenerator.h"
      49                 : #include "nsIFile.h"
      50                 : #include "nsILocalFile.h"
      51                 : #include "nsToolkitCompsCID.h"
      52                 : #include "nsTArray.h"
      53                 : #include "nsThreadUtils.h"
      54                 : #include "mozilla/Mutex.h"
      55                 : #include "mozilla/Telemetry.h"
      56                 : #include "mozilla/FileUtils.h"
      57                 : #include "prlog.h"
      58                 : 
      59                 : using namespace mozilla;
      60                 : 
      61                 : // NSPR_LOG_MODULES=UrlClassifierPrefixSet:5
      62                 : #if defined(PR_LOGGING)
      63                 : static const PRLogModuleInfo *gUrlClassifierPrefixSetLog = nsnull;
      64                 : #define LOG(args) PR_LOG(gUrlClassifierPrefixSetLog, PR_LOG_DEBUG, args)
      65                 : #define LOG_ENABLED() PR_LOG_TEST(gUrlClassifierPrefixSetLog, 4)
      66                 : #else
      67                 : #define LOG(args)
      68                 : #define LOG_ENABLED() (false)
      69                 : #endif
      70                 : 
      71                 : class nsPrefixSetReporter : public nsIMemoryReporter
      72                 : {
      73                 : public:
      74                 :   nsPrefixSetReporter(nsUrlClassifierPrefixSet* aParent, const nsACString& aName);
      75             192 :   virtual ~nsPrefixSetReporter() {};
      76                 : 
      77                 :   NS_DECL_ISUPPORTS
      78                 :   NS_DECL_NSIMEMORYREPORTER
      79                 : 
      80                 : private:
      81                 :   nsCString mPath;
      82                 :   nsUrlClassifierPrefixSet* mParent;
      83                 : };
      84                 : 
      85             192 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsPrefixSetReporter, nsIMemoryReporter)
      86                 : 
      87               0 : NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(StoragePrefixSetMallocSizeOf,
      88                 :                                      "storage/prefixset")
      89                 : 
      90              48 : nsPrefixSetReporter::nsPrefixSetReporter(nsUrlClassifierPrefixSet* aParent,
      91                 :                                          const nsACString& aName)
      92              48 : : mParent(aParent)
      93                 : {
      94              48 :   mPath.Assign(NS_LITERAL_CSTRING("explicit/storage/prefixset"));
      95              48 :   if (!aName.IsEmpty()) {
      96              48 :     mPath.Append("/");
      97              48 :     mPath.Append(aName);
      98                 :   }
      99              48 : }
     100                 : 
     101                 : NS_IMETHODIMP
     102               0 : nsPrefixSetReporter::GetProcess(nsACString& aProcess)
     103                 : {
     104               0 :   aProcess.Truncate();
     105               0 :   return NS_OK;
     106                 : }
     107                 : 
     108                 : NS_IMETHODIMP
     109               0 : nsPrefixSetReporter::GetPath(nsACString& aPath)
     110                 : {
     111               0 :   aPath.Assign(mPath);
     112               0 :   return NS_OK;
     113                 : }
     114                 : 
     115                 : NS_IMETHODIMP
     116               0 : nsPrefixSetReporter::GetKind(PRInt32* aKind)
     117                 : {
     118               0 :   *aKind = nsIMemoryReporter::KIND_HEAP;
     119               0 :   return NS_OK;
     120                 : }
     121                 : 
     122                 : NS_IMETHODIMP
     123               0 : nsPrefixSetReporter::GetUnits(PRInt32* aUnits)
     124                 : {
     125               0 :   *aUnits = nsIMemoryReporter::UNITS_BYTES;
     126               0 :   return NS_OK;
     127                 : }
     128                 : 
     129                 : NS_IMETHODIMP
     130               0 : nsPrefixSetReporter::GetAmount(PRInt64* aAmount)
     131                 : {
     132               0 :   *aAmount = mParent->SizeOfIncludingThis(StoragePrefixSetMallocSizeOf);
     133               0 :   return NS_OK;
     134                 : }
     135                 : 
     136                 : NS_IMETHODIMP
     137               0 : nsPrefixSetReporter::GetDescription(nsACString& aDescription)
     138                 : {
     139               0 :   aDescription.Assign(NS_LITERAL_CSTRING("Memory used by a PrefixSet for "
     140               0 :                                          "UrlClassifier, in bytes."));
     141               0 :   return NS_OK;
     142                 : }
     143                 : 
     144             192 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlClassifierPrefixSet, nsIUrlClassifierPrefixSet)
     145                 : 
     146              51 : nsUrlClassifierPrefixSet::nsUrlClassifierPrefixSet()
     147                 :   : mPrefixSetLock("mPrefixSetLock"),
     148                 :     mSetIsReady(mPrefixSetLock, "mSetIsReady"),
     149              51 :     mHasPrefixes(false)
     150                 : {
     151                 : #if defined(PR_LOGGING)
     152              51 :   if (!gUrlClassifierPrefixSetLog)
     153               5 :     gUrlClassifierPrefixSetLog = PR_NewLogModule("UrlClassifierPrefixSet");
     154                 : #endif
     155              51 : }
     156                 : 
     157                 : NS_IMETHODIMP
     158              48 : nsUrlClassifierPrefixSet::Init(const nsACString& aName)
     159                 : {
     160              48 :   mReporter = new nsPrefixSetReporter(this, aName);
     161              48 :   NS_RegisterMemoryReporter(mReporter);
     162                 : 
     163              48 :   return NS_OK;
     164                 : }
     165                 : 
     166             153 : nsUrlClassifierPrefixSet::~nsUrlClassifierPrefixSet()
     167                 : {
     168              51 :   NS_UnregisterMemoryReporter(mReporter);
     169             204 : }
     170                 : 
     171                 : NS_IMETHODIMP
     172             150 : nsUrlClassifierPrefixSet::SetPrefixes(const PRUint32* aArray, PRUint32 aLength)
     173                 : {
     174             150 :   if (aLength <= 0) {
     175              92 :     MutexAutoLock lock(mPrefixSetLock);
     176              46 :     if (mHasPrefixes) {
     177               1 :       LOG(("Clearing PrefixSet"));
     178               1 :       mDeltas.Clear();
     179               1 :       mIndexPrefixes.Clear();
     180               1 :       mIndexStarts.Clear();
     181               1 :       mHasPrefixes = false;
     182                 :     }
     183                 :   } else {
     184             104 :     return MakePrefixSet(aArray, aLength);
     185                 :   }
     186                 : 
     187              46 :   return NS_OK;
     188                 : }
     189                 : 
     190                 : nsresult
     191             104 : nsUrlClassifierPrefixSet::MakePrefixSet(const PRUint32* aPrefixes, PRUint32 aLength)
     192                 : {
     193             104 :   if (aLength == 0) {
     194               0 :     return NS_OK;
     195                 :   }
     196                 : 
     197                 : #ifdef DEBUG
     198            1208 :   for (PRUint32 i = 1; i < aLength; i++) {
     199            1104 :     MOZ_ASSERT(aPrefixes[i] >= aPrefixes[i-1]);
     200                 :   }
     201                 : #endif
     202                 : 
     203             208 :   FallibleTArray<PRUint32> newIndexPrefixes;
     204             208 :   FallibleTArray<PRUint32> newIndexStarts;
     205             208 :   FallibleTArray<PRUint16> newDeltas;
     206                 : 
     207             104 :   if (!newIndexPrefixes.AppendElement(aPrefixes[0])) {
     208               0 :     return NS_ERROR_OUT_OF_MEMORY;
     209                 :   }
     210             104 :   if (!newIndexStarts.AppendElement(newDeltas.Length())) {
     211               0 :     return NS_ERROR_OUT_OF_MEMORY;
     212                 :   }
     213                 : 
     214             104 :   PRUint32 numOfDeltas = 0;
     215             104 :   PRUint32 currentItem = aPrefixes[0];
     216            1208 :   for (PRUint32 i = 1; i < aLength; i++) {
     217            2208 :     if ((numOfDeltas >= DELTAS_LIMIT) ||
     218            1104 :           (aPrefixes[i] - currentItem >= MAX_INDEX_DIFF)) {
     219            1055 :       if (!newIndexStarts.AppendElement(newDeltas.Length())) {
     220               0 :         return NS_ERROR_OUT_OF_MEMORY;
     221                 :       }
     222            1055 :       if (!newIndexPrefixes.AppendElement(aPrefixes[i])) {
     223               0 :         return NS_ERROR_OUT_OF_MEMORY;
     224                 :       }
     225            1055 :       numOfDeltas = 0;
     226                 :     } else {
     227              49 :       PRUint16 delta = aPrefixes[i] - currentItem;
     228              49 :       if (!newDeltas.AppendElement(delta)) {
     229               0 :         return NS_ERROR_OUT_OF_MEMORY;
     230                 :       }
     231              49 :       numOfDeltas++;
     232                 :     }
     233            1104 :     currentItem = aPrefixes[i];
     234                 :   }
     235                 : 
     236             104 :   newIndexPrefixes.Compact();
     237             104 :   newIndexStarts.Compact();
     238             104 :   newDeltas.Compact();
     239                 : 
     240             104 :   LOG(("Total number of indices: %d", newIndexPrefixes.Length()));
     241             104 :   LOG(("Total number of deltas: %d", newDeltas.Length()));
     242                 : 
     243             208 :   MutexAutoLock lock(mPrefixSetLock);
     244                 : 
     245                 :   // This just swaps some pointers
     246             104 :   mIndexPrefixes.SwapElements(newIndexPrefixes);
     247             104 :   mIndexStarts.SwapElements(newIndexStarts);
     248             104 :   mDeltas.SwapElements(newDeltas);
     249                 : 
     250             104 :   mHasPrefixes = true;
     251             104 :   mSetIsReady.NotifyAll();
     252                 : 
     253             104 :   return NS_OK;
     254                 : }
     255                 : 
     256                 : NS_IMETHODIMP
     257              59 : nsUrlClassifierPrefixSet::GetPrefixes(PRUint32* aCount,
     258                 :                                       PRUint32** aPrefixes)
     259                 : {
     260              59 :   NS_ENSURE_ARG_POINTER(aCount);
     261              59 :   *aCount = 0;
     262              59 :   NS_ENSURE_ARG_POINTER(aPrefixes);
     263              59 :   *aPrefixes = nsnull;
     264                 : 
     265             118 :   nsTArray<PRUint32> aArray;
     266              59 :   PRUint32 prefixLength = mIndexPrefixes.Length();
     267                 : 
     268            1142 :   for (PRUint32 i = 0; i < prefixLength; i++) {
     269            1083 :     PRUint32 prefix = mIndexPrefixes[i];
     270            1083 :     PRUint32 start = mIndexStarts[i];
     271              58 :     PRUint32 end = (i == (prefixLength - 1)) ? mDeltas.Length()
     272            1141 :                                              : mIndexStarts[i + 1];
     273            1083 :     aArray.AppendElement(prefix);
     274            1129 :     for (PRUint32 j = start; j < end; j++) {
     275              46 :       prefix += mDeltas[j];
     276              46 :       aArray.AppendElement(prefix);
     277                 :     }
     278                 :   }
     279                 : 
     280              59 :   NS_ASSERTION(mIndexStarts.Length() + mDeltas.Length() == aArray.Length(),
     281                 :                "Lengths are inconsistent");
     282                 : 
     283              59 :   PRUint32 itemCount = aArray.Length();
     284                 : 
     285              59 :   if (itemCount == 1 && aArray[0] == 0) {
     286                 :     /* sentinel for empty set */
     287              28 :     aArray.Clear();
     288              28 :     itemCount = 0;
     289                 :   }
     290                 : 
     291              59 :   PRUint32* retval = static_cast<PRUint32*>(nsMemory::Alloc(itemCount * sizeof(PRUint32)));
     292              59 :   NS_ENSURE_TRUE(retval, NS_ERROR_OUT_OF_MEMORY);
     293            1160 :   for (PRUint32 i = 0; i < itemCount; i++) {
     294            1101 :     retval[i] = aArray[i];
     295                 :   }
     296                 : 
     297              59 :   *aCount = itemCount;
     298              59 :   *aPrefixes = retval;
     299                 : 
     300              59 :   return NS_OK;
     301                 : }
     302                 : 
     303            2392 : PRUint32 nsUrlClassifierPrefixSet::BinSearch(PRUint32 start,
     304                 :                                              PRUint32 end,
     305                 :                                              PRUint32 target)
     306                 : {
     307           21935 :   while (start != end && end >= start) {
     308           17681 :     PRUint32 i = start + ((end - start) >> 1);
     309           17681 :     PRUint32 value = mIndexPrefixes[i];
     310           17681 :     if (value < target) {
     311            8771 :       start = i + 1;
     312            8910 :     } else if (value > target) {
     313            8380 :       end = i - 1;
     314                 :     } else {
     315             530 :       return i;
     316                 :     }
     317                 :   }
     318            1862 :   return end;
     319                 : }
     320                 : 
     321                 : nsresult
     322            2408 : nsUrlClassifierPrefixSet::Contains(PRUint32 aPrefix, bool* aFound)
     323                 : {
     324            2408 :   mPrefixSetLock.AssertCurrentThreadOwns();
     325                 : 
     326            2408 :   *aFound = false;
     327                 : 
     328            2408 :   if (!mHasPrefixes) {
     329               0 :     return NS_OK;
     330                 :   }
     331                 : 
     332            2408 :   PRUint32 target = aPrefix;
     333                 : 
     334                 :   // We want to do a "Price is Right" binary search, that is, we want to find
     335                 :   // the index of the value either equal to the target or the closest value
     336                 :   // that is less than the target.
     337                 :   //
     338            2408 :   if (target < mIndexPrefixes[0]) {
     339              16 :     return NS_OK;
     340                 :   }
     341                 : 
     342                 :   // |binsearch| does not necessarily return the correct index (when the
     343                 :   // target is not found) but rather it returns an index at least one away
     344                 :   // from the correct index.
     345                 :   // Because of this, we need to check if the target lies before the beginning
     346                 :   // of the indices.
     347                 : 
     348            2392 :   PRUint32 i = BinSearch(0, mIndexPrefixes.Length() - 1, target);
     349            2392 :   if (mIndexPrefixes[i] > target && i > 0) {
     350             550 :     i--;
     351                 :   }
     352                 : 
     353                 :   // Now search through the deltas for the target.
     354            2392 :   PRUint32 diff = target - mIndexPrefixes[i];
     355            2392 :   PRUint32 deltaIndex = mIndexStarts[i];
     356            2392 :   PRUint32 deltaSize  = mDeltas.Length();
     357            4444 :   PRUint32 end = (i + 1 < mIndexStarts.Length()) ? mIndexStarts[i+1]
     358            6836 :                                                  : deltaSize;
     359                 : 
     360                 :   // Sanity check the read values
     361            2392 :   if (end > deltaSize) {
     362               0 :     return NS_ERROR_FILE_CORRUPTED;
     363                 :   }
     364                 : 
     365            4916 :   while (diff > 0 && deltaIndex < end) {
     366             132 :     diff -= mDeltas[deltaIndex];
     367             132 :     deltaIndex++;
     368                 :   }
     369                 : 
     370            2392 :   if (diff == 0) {
     371            1068 :     *aFound = true;
     372                 :   }
     373                 : 
     374            2392 :   return NS_OK;
     375                 : }
     376                 : 
     377                 : size_t
     378              97 : nsUrlClassifierPrefixSet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
     379                 : {
     380             194 :   MutexAutoLock lock(mPrefixSetLock);
     381              97 :   size_t n = 0;
     382              97 :   n += aMallocSizeOf(this);
     383              97 :   n += mDeltas.SizeOfExcludingThis(aMallocSizeOf);
     384              97 :   n += mIndexPrefixes.SizeOfExcludingThis(aMallocSizeOf);
     385              97 :   n += mIndexStarts.SizeOfExcludingThis(aMallocSizeOf);
     386              97 :   return n;
     387                 : }
     388                 : 
     389                 : NS_IMETHODIMP
     390               0 : nsUrlClassifierPrefixSet::IsEmpty(bool * aEmpty)
     391                 : {
     392               0 :   MutexAutoLock lock(mPrefixSetLock);
     393               0 :   *aEmpty = !mHasPrefixes;
     394               0 :   return NS_OK;
     395                 : }
     396                 : 
     397                 : NS_IMETHODIMP
     398            2409 : nsUrlClassifierPrefixSet::Probe(PRUint32 aPrefix,
     399                 :                                 bool* aReady, bool* aFound)
     400                 : {
     401            4818 :   MutexAutoLock lock(mPrefixSetLock);
     402                 : 
     403            2409 :   *aFound = false;
     404                 : 
     405                 :   // check whether we are opportunistically probing or should wait
     406            2409 :   if (*aReady) {
     407                 :     // we should block until we are ready
     408             548 :     while (!mHasPrefixes) {
     409               0 :       LOG(("Set is empty, probe must wait"));
     410               0 :       mSetIsReady.Wait();
     411                 :     }
     412                 :   } else {
     413                 :     // opportunistic probe -> check if set is loaded
     414            2135 :     if (mHasPrefixes) {
     415            2134 :       *aReady = true;
     416                 :     } else {
     417               1 :       return NS_OK;
     418                 :     }
     419                 :   }
     420                 : 
     421            2408 :   nsresult rv = Contains(aPrefix, aFound);
     422            2408 :   NS_ENSURE_SUCCESS(rv, rv);
     423                 : 
     424            2408 :   return NS_OK;
     425                 : }
     426                 : 
     427                 : nsresult
     428               0 : nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose& fileFd)
     429                 : {
     430                 :   PRUint32 magic;
     431                 :   PRInt32 read;
     432                 : 
     433               0 :   read = PR_Read(fileFd, &magic, sizeof(PRUint32));
     434               0 :   NS_ENSURE_TRUE(read == sizeof(PRUint32), NS_ERROR_FAILURE);
     435                 : 
     436               0 :   if (magic == PREFIXSET_VERSION_MAGIC) {
     437                 :     PRUint32 indexSize;
     438                 :     PRUint32 deltaSize;
     439                 : 
     440               0 :     read = PR_Read(fileFd, &indexSize, sizeof(PRUint32));
     441               0 :     NS_ENSURE_TRUE(read == sizeof(PRUint32), NS_ERROR_FILE_CORRUPTED);
     442               0 :     read = PR_Read(fileFd, &deltaSize, sizeof(PRUint32));
     443               0 :     NS_ENSURE_TRUE(read == sizeof(PRUint32), NS_ERROR_FILE_CORRUPTED);
     444                 : 
     445               0 :     if (indexSize == 0) {
     446               0 :       LOG(("stored PrefixSet is empty!"));
     447               0 :       return NS_ERROR_FAILURE;
     448                 :     }
     449                 : 
     450               0 :     if (deltaSize > (indexSize * DELTAS_LIMIT)) {
     451               0 :       return NS_ERROR_FILE_CORRUPTED;
     452                 :     }
     453                 : 
     454               0 :     nsTArray<PRUint32> mNewIndexPrefixes;
     455               0 :     nsTArray<PRUint32> mNewIndexStarts;
     456               0 :     nsTArray<PRUint16> mNewDeltas;
     457                 : 
     458               0 :     mNewIndexStarts.SetLength(indexSize);
     459               0 :     mNewIndexPrefixes.SetLength(indexSize);
     460               0 :     mNewDeltas.SetLength(deltaSize);
     461                 : 
     462               0 :     PRInt32 toRead = indexSize*sizeof(PRUint32);
     463               0 :     read = PR_Read(fileFd, mNewIndexPrefixes.Elements(), toRead);
     464               0 :     NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED);
     465               0 :     read = PR_Read(fileFd, mNewIndexStarts.Elements(), toRead);
     466               0 :     NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED);
     467               0 :     if (deltaSize > 0) {
     468               0 :       toRead = deltaSize*sizeof(PRUint16);
     469               0 :       read = PR_Read(fileFd, mNewDeltas.Elements(), toRead);
     470               0 :       NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED);
     471                 :     }
     472                 : 
     473               0 :     MutexAutoLock lock(mPrefixSetLock);
     474                 : 
     475               0 :     mIndexPrefixes.SwapElements(mNewIndexPrefixes);
     476               0 :     mIndexStarts.SwapElements(mNewIndexStarts);
     477               0 :     mDeltas.SwapElements(mNewDeltas);
     478                 : 
     479               0 :     mHasPrefixes = true;
     480               0 :     mSetIsReady.NotifyAll();
     481                 :   } else {
     482               0 :     LOG(("Version magic mismatch, not loading"));
     483               0 :     return NS_ERROR_FAILURE;
     484                 :   }
     485                 : 
     486               0 :   LOG(("Loading PrefixSet successful"));
     487                 : 
     488               0 :   return NS_OK;
     489                 : }
     490                 : 
     491                 : NS_IMETHODIMP
     492               0 : nsUrlClassifierPrefixSet::LoadFromFile(nsIFile* aFile)
     493                 : {
     494               0 :   Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_PS_FILELOAD_TIME> timer;
     495                 : 
     496                 :   nsresult rv;
     497               0 :   nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
     498               0 :   NS_ENSURE_SUCCESS(rv, rv);
     499                 : 
     500               0 :   AutoFDClose fileFd;
     501               0 :   rv = file->OpenNSPRFileDesc(PR_RDONLY | nsILocalFile::OS_READAHEAD, 0, &fileFd);
     502               0 :   NS_ENSURE_SUCCESS(rv, rv);
     503                 : 
     504               0 :   return LoadFromFd(fileFd);
     505                 : }
     506                 : 
     507                 : nsresult
     508              97 : nsUrlClassifierPrefixSet::StoreToFd(AutoFDClose& fileFd)
     509                 : {
     510                 :   {
     511             194 :       Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_PS_FALLOCATE_TIME> timer;
     512              97 :       PRInt64 size = 4 * sizeof(PRUint32);
     513              97 :       size += 2 * mIndexStarts.Length() * sizeof(PRUint32);
     514              97 :       size +=     mDeltas.Length() * sizeof(PRUint16);
     515                 : 
     516              97 :       mozilla::fallocate(fileFd, size);
     517                 :   }
     518                 : 
     519                 :   PRInt32 written;
     520              97 :   PRUint32 magic = PREFIXSET_VERSION_MAGIC;
     521              97 :   written = PR_Write(fileFd, &magic, sizeof(PRUint32));
     522              97 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     523                 : 
     524              97 :   PRUint32 indexSize = mIndexStarts.Length();
     525              97 :   PRUint32 deltaSize = mDeltas.Length();
     526              97 :   written = PR_Write(fileFd, &indexSize, sizeof(PRUint32));
     527              97 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     528              97 :   written = PR_Write(fileFd, &deltaSize, sizeof(PRUint32));
     529              97 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     530                 : 
     531              97 :   written = PR_Write(fileFd, mIndexPrefixes.Elements(), indexSize * sizeof(PRUint32));
     532              97 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     533              97 :   written = PR_Write(fileFd, mIndexStarts.Elements(), indexSize * sizeof(PRUint32));
     534              97 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     535              97 :   if (deltaSize > 0) {
     536               0 :     written = PR_Write(fileFd, mDeltas.Elements(), deltaSize * sizeof(PRUint16));
     537               0 :     NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     538                 :   }
     539                 : 
     540              97 :   LOG(("Saving PrefixSet successful\n"));
     541                 : 
     542              97 :   return NS_OK;
     543                 : }
     544                 : 
     545                 : NS_IMETHODIMP
     546              97 : nsUrlClassifierPrefixSet::StoreToFile(nsIFile* aFile)
     547                 : {
     548              97 :   if (!mHasPrefixes) {
     549               0 :     LOG(("Attempt to serialize empty PrefixSet"));
     550               0 :     return NS_ERROR_FAILURE;
     551                 :   }
     552                 : 
     553                 :   nsresult rv;
     554             194 :   nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
     555              97 :   NS_ENSURE_SUCCESS(rv, rv);
     556                 : 
     557             194 :   AutoFDClose fileFd;
     558              97 :   rv = file->OpenNSPRFileDesc(PR_RDWR | PR_TRUNCATE | PR_CREATE_FILE,
     559              97 :                               0644, &fileFd);
     560              97 :   NS_ENSURE_SUCCESS(rv, rv);
     561                 : 
     562             194 :   MutexAutoLock lock(mPrefixSetLock);
     563                 : 
     564              97 :   return StoreToFd(fileFd);
     565                 : }

Generated by: LCOV version 1.7