LCOV - code coverage report
Current view: directory - toolkit/components/url-classifier - nsUrlClassifierPrefixSet.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 254 162 63.8 %
Date: 2012-06-02 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              56 :   virtual ~nsPrefixSetReporter() {};
      76                 : 
      77                 :   NS_DECL_ISUPPORTS
      78                 :   NS_DECL_NSIMEMORYREPORTER
      79                 : 
      80                 : private:
      81                 :   nsCString mPath;
      82                 :   nsUrlClassifierPrefixSet * mParent;
      83                 : };
      84                 : 
      85              56 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsPrefixSetReporter, nsIMemoryReporter)
      86                 : 
      87               0 : NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(StoragePrefixSetMallocSizeOf,
      88                 :                                      "storage/prefixset")
      89                 : 
      90              14 : nsPrefixSetReporter::nsPrefixSetReporter(nsUrlClassifierPrefixSet * aParent,
      91                 :                                          const nsACString & aName)
      92              14 : : mParent(aParent)
      93                 : {
      94              14 :   mPath.Assign(NS_LITERAL_CSTRING("explicit/storage/prefixset"));
      95              14 :   if (!aName.IsEmpty()) {
      96              14 :     mPath.Append("/");
      97              14 :     mPath.Append(aName);
      98                 :   }
      99              14 : }
     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             134 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlClassifierPrefixSet, nsIUrlClassifierPrefixSet)
     145                 : 
     146              14 : nsUrlClassifierPrefixSet::nsUrlClassifierPrefixSet()
     147                 :   : mPrefixSetLock("mPrefixSetLock"),
     148                 :     mSetIsReady(mPrefixSetLock, "mSetIsReady"),
     149                 :     mHasPrefixes(false),
     150              14 :     mRandomKey(0)
     151                 : {
     152                 : #if defined(PR_LOGGING)
     153              14 :   if (!gUrlClassifierPrefixSetLog)
     154               8 :     gUrlClassifierPrefixSetLog = PR_NewLogModule("UrlClassifierPrefixSet");
     155                 : #endif
     156                 : 
     157              14 :   nsresult rv = InitKey();
     158              14 :   if (NS_FAILED(rv)) {
     159               0 :     LOG(("Failed to initialize PrefixSet"));
     160                 :   }
     161                 : 
     162              28 :   mReporter = new nsPrefixSetReporter(this, NS_LITERAL_CSTRING("all"));
     163              14 :   NS_RegisterMemoryReporter(mReporter);
     164              14 : }
     165                 : 
     166              42 : nsUrlClassifierPrefixSet::~nsUrlClassifierPrefixSet()
     167                 : {
     168              14 :   NS_UnregisterMemoryReporter(mReporter);
     169              56 : }
     170                 : 
     171                 : nsresult
     172              14 : nsUrlClassifierPrefixSet::InitKey()
     173                 : {
     174                 :   nsCOMPtr<nsIRandomGenerator> rg =
     175              28 :     do_GetService("@mozilla.org/security/random-generator;1");
     176              14 :   NS_ENSURE_STATE(rg);
     177                 : 
     178                 :   PRUint8 *temp;
     179              14 :   nsresult rv = rg->GenerateRandomBytes(sizeof(mRandomKey), &temp);
     180              14 :   NS_ENSURE_SUCCESS(rv, rv);
     181              14 :   memcpy(&mRandomKey, temp, sizeof(mRandomKey));
     182              14 :   NS_Free(temp);
     183                 : 
     184              14 :   LOG(("Initialized PrefixSet, key = %X", mRandomKey));
     185                 : 
     186              14 :   return NS_OK;
     187                 : }
     188                 : 
     189                 : NS_IMETHODIMP
     190             203 : nsUrlClassifierPrefixSet::SetPrefixes(const PRUint32 * aArray, PRUint32 aLength)
     191                 : {
     192             203 :   if (aLength <= 0) {
     193             112 :     MutexAutoLock lock(mPrefixSetLock);
     194              56 :     if (mHasPrefixes) {
     195              52 :       LOG(("Clearing PrefixSet"));
     196              52 :       mDeltas.Clear();
     197              52 :       mIndexPrefixes.Clear();
     198              52 :       mIndexStarts.Clear();
     199              52 :       mHasPrefixes = false;
     200                 :     }
     201                 :   } else {
     202             147 :     return MakePrefixSet(aArray, aLength);
     203                 :   }
     204                 : 
     205              56 :   return NS_OK;
     206                 : }
     207                 : 
     208                 : nsresult
     209             147 : nsUrlClassifierPrefixSet::MakePrefixSet(const PRUint32 * prefixes, PRUint32 aLength)
     210                 : {
     211             147 :   if (aLength == 0) {
     212               0 :     return NS_OK;
     213                 :   }
     214                 : 
     215                 : #ifdef DEBUG
     216            1293 :   for (PRUint32 i = 1; i < aLength; i++) {
     217            1146 :     MOZ_ASSERT(prefixes[i] >= prefixes[i-1]);
     218                 :   }
     219                 : #endif
     220                 : 
     221             294 :   FallibleTArray<PRUint32> newIndexPrefixes;
     222             294 :   FallibleTArray<PRUint32> newIndexStarts;
     223             294 :   FallibleTArray<PRUint16> newDeltas;
     224                 : 
     225             147 :   if (!newIndexPrefixes.AppendElement(prefixes[0])) {
     226               0 :     return NS_ERROR_OUT_OF_MEMORY;
     227                 :   }
     228             147 :   if (!newIndexStarts.AppendElement(newDeltas.Length())) {
     229               0 :     return NS_ERROR_OUT_OF_MEMORY;
     230                 :   }
     231                 : 
     232             147 :   PRUint32 numOfDeltas = 0;
     233             147 :   PRUint32 currentItem = prefixes[0];
     234            1293 :   for (PRUint32 i = 1; i < aLength; i++) {
     235            2292 :     if ((numOfDeltas >= DELTAS_LIMIT) ||
     236            1146 :           (prefixes[i] - currentItem >= MAX_INDEX_DIFF)) {
     237            1088 :       if (!newIndexStarts.AppendElement(newDeltas.Length())) {
     238               0 :         return NS_ERROR_OUT_OF_MEMORY;
     239                 :       }
     240            1088 :       if (!newIndexPrefixes.AppendElement(prefixes[i])) {
     241               0 :         return NS_ERROR_OUT_OF_MEMORY;
     242                 :       }
     243            1088 :       numOfDeltas = 0;
     244                 :     } else {
     245              58 :       PRUint16 delta = prefixes[i] - currentItem;
     246              58 :       if (!newDeltas.AppendElement(delta)) {
     247               0 :         return NS_ERROR_OUT_OF_MEMORY;
     248                 :       }
     249              58 :       numOfDeltas++;
     250                 :     }
     251            1146 :     currentItem = prefixes[i];
     252                 :   }
     253                 : 
     254             147 :   newIndexPrefixes.Compact();
     255             147 :   newIndexStarts.Compact();
     256             147 :   newDeltas.Compact();
     257                 : 
     258             147 :   LOG(("Total number of indices: %d", newIndexPrefixes.Length()));
     259             147 :   LOG(("Total number of deltas: %d", newDeltas.Length()));
     260                 : 
     261             294 :   MutexAutoLock lock(mPrefixSetLock);
     262                 : 
     263                 :   // This just swaps some pointers
     264             147 :   mIndexPrefixes.SwapElements(newIndexPrefixes);
     265             147 :   mIndexStarts.SwapElements(newIndexStarts);
     266             147 :   mDeltas.SwapElements(newDeltas);
     267                 : 
     268             147 :   mHasPrefixes = true;
     269             147 :   mSetIsReady.NotifyAll();
     270                 : 
     271             147 :   return NS_OK;
     272                 : }
     273                 : 
     274            2155 : PRUint32 nsUrlClassifierPrefixSet::BinSearch(PRUint32 start,
     275                 :                                              PRUint32 end,
     276                 :                                              PRUint32 target)
     277                 : {
     278           21418 :   while (start != end && end >= start) {
     279           17623 :     PRUint32 i = start + ((end - start) >> 1);
     280           17623 :     PRUint32 value = mIndexPrefixes[i];
     281           17623 :     if (value < target) {
     282            8750 :       start = i + 1;
     283            8873 :     } else if (value > target) {
     284            8358 :       end = i - 1;
     285                 :     } else {
     286             515 :       return i;
     287                 :     }
     288                 :   }
     289            1640 :   return end;
     290                 : }
     291                 : 
     292                 : nsresult
     293            2176 : nsUrlClassifierPrefixSet::Contains(PRUint32 aPrefix, bool * aFound)
     294                 : {
     295            2176 :   mPrefixSetLock.AssertCurrentThreadOwns();
     296                 : 
     297            2176 :   *aFound = false;
     298                 : 
     299            2176 :   if (!mHasPrefixes) {
     300               0 :     return NS_OK;
     301                 :   }
     302                 : 
     303            2176 :   PRUint32 target = aPrefix;
     304                 : 
     305                 :   // We want to do a "Price is Right" binary search, that is, we want to find
     306                 :   // the index of the value either equal to the target or the closest value
     307                 :   // that is less than the target.
     308                 :   //
     309            2176 :   if (target < mIndexPrefixes[0]) {
     310              21 :     return NS_OK;
     311                 :   }
     312                 : 
     313                 :   // |binsearch| does not necessarily return the correct index (when the
     314                 :   // target is not found) but rather it returns an index at least one away
     315                 :   // from the correct index.
     316                 :   // Because of this, we need to check if the target lies before the beginning
     317                 :   // of the indices.
     318                 : 
     319            2155 :   PRUint32 i = BinSearch(0, mIndexPrefixes.Length() - 1, target);
     320            2155 :   if (mIndexPrefixes[i] > target && i > 0) {
     321             482 :     i--;
     322                 :   }
     323                 : 
     324                 :   // Now search through the deltas for the target.
     325            2155 :   PRUint32 diff = target - mIndexPrefixes[i];
     326            2155 :   PRUint32 deltaIndex = mIndexStarts[i];
     327            2155 :   PRUint32 deltaSize  = mDeltas.Length();
     328            4175 :   PRUint32 end = (i + 1 < mIndexStarts.Length()) ? mIndexStarts[i+1]
     329            6330 :                                                  : deltaSize;
     330                 : 
     331                 :   // Sanity check the read values
     332            2155 :   if (end > deltaSize) {
     333               0 :     return NS_ERROR_FILE_CORRUPTED;
     334                 :   }
     335                 : 
     336            4444 :   while (diff > 0 && deltaIndex < end) {
     337             134 :     diff -= mDeltas[deltaIndex];
     338             134 :     deltaIndex++;
     339                 :   }
     340                 : 
     341            2155 :   if (diff == 0) {
     342            1024 :     *aFound = true;
     343                 :   }
     344                 : 
     345            2155 :   return NS_OK;
     346                 : }
     347                 : 
     348                 : size_t
     349               0 : nsUrlClassifierPrefixSet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
     350                 : {
     351               0 :   MutexAutoLock lock(mPrefixSetLock);
     352               0 :   size_t n = 0;
     353               0 :   n += aMallocSizeOf(this);
     354               0 :   n += mDeltas.SizeOfExcludingThis(aMallocSizeOf);
     355               0 :   n += mIndexPrefixes.SizeOfExcludingThis(aMallocSizeOf);
     356               0 :   n += mIndexStarts.SizeOfExcludingThis(aMallocSizeOf);
     357               0 :   return n;
     358                 : }
     359                 : 
     360                 : NS_IMETHODIMP
     361             141 : nsUrlClassifierPrefixSet::IsEmpty(bool * aEmpty)
     362                 : {
     363             282 :   MutexAutoLock lock(mPrefixSetLock);
     364             141 :   *aEmpty = !mHasPrefixes;
     365             141 :   return NS_OK;
     366                 : }
     367                 : 
     368                 : NS_IMETHODIMP
     369            2296 : nsUrlClassifierPrefixSet::GetKey(PRUint32 * aKey)
     370                 :  {
     371            4592 :    MutexAutoLock lock(mPrefixSetLock);
     372            2296 :    *aKey = mRandomKey;
     373            2296 :    return NS_OK;
     374                 : }
     375                 : 
     376                 : NS_IMETHODIMP
     377            2177 : nsUrlClassifierPrefixSet::Probe(PRUint32 aPrefix, PRUint32 aKey,
     378                 :                                 bool* aReady, bool* aFound)
     379                 : {
     380            4354 :   MutexAutoLock lock(mPrefixSetLock);
     381                 : 
     382            2177 :   *aFound = false;
     383                 : 
     384                 :   // We might have raced here with a LoadPrefixSet call,
     385                 :   // loading a saved PrefixSet with another key than the one used to probe us.
     386                 :   // This must occur exactly between the GetKey call and the Probe call.
     387                 :   // This could cause a false negative immediately after browser start.
     388                 :   // Claim we are still busy loading instead.
     389            2177 :   if (aKey != mRandomKey) {
     390               0 :     LOG(("Potential race condition detected, avoiding"));
     391               0 :     *aReady = false;
     392               0 :     return NS_OK;
     393                 :   }
     394                 : 
     395                 :   // check whether we are opportunistically probing or should wait
     396            2177 :   if (*aReady) {
     397                 :     // we should block until we are ready
     398               0 :     while (!mHasPrefixes) {
     399               0 :       LOG(("Set is empty, probe must wait"));
     400               0 :       mSetIsReady.Wait();
     401                 :     }
     402                 :   } else {
     403                 :     // opportunistic probe -> check if set is loaded
     404            2177 :     if (mHasPrefixes) {
     405            2176 :       *aReady = true;
     406                 :     } else {
     407               1 :       return NS_OK;
     408                 :     }
     409                 :   }
     410                 : 
     411            2176 :   nsresult rv = Contains(aPrefix, aFound);
     412            2176 :   NS_ENSURE_SUCCESS(rv, rv);
     413                 : 
     414            2176 :   return NS_OK;
     415                 : }
     416                 : 
     417                 : nsresult
     418               0 : nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose & fileFd)
     419                 : {
     420                 :   PRUint32 magic;
     421                 :   PRInt32 read;
     422                 : 
     423               0 :   read = PR_Read(fileFd, &magic, sizeof(PRUint32));
     424               0 :   NS_ENSURE_TRUE(read == sizeof(PRUint32), NS_ERROR_FAILURE);
     425                 : 
     426               0 :   if (magic == PREFIXSET_VERSION_MAGIC) {
     427                 :     PRUint32 indexSize;
     428                 :     PRUint32 deltaSize;
     429                 : 
     430               0 :     read = PR_Read(fileFd, &mRandomKey, sizeof(PRUint32));
     431               0 :     NS_ENSURE_TRUE(read == sizeof(PRUint32), NS_ERROR_FILE_CORRUPTED);
     432               0 :     read = PR_Read(fileFd, &indexSize, sizeof(PRUint32));
     433               0 :     NS_ENSURE_TRUE(read == sizeof(PRUint32), NS_ERROR_FILE_CORRUPTED);
     434               0 :     read = PR_Read(fileFd, &deltaSize, sizeof(PRUint32));
     435               0 :     NS_ENSURE_TRUE(read == sizeof(PRUint32), NS_ERROR_FILE_CORRUPTED);
     436                 : 
     437               0 :     if (indexSize == 0) {
     438               0 :       LOG(("stored PrefixSet is empty!"));
     439               0 :       return NS_ERROR_FAILURE;
     440                 :     }
     441                 : 
     442               0 :     if (deltaSize > (indexSize * DELTAS_LIMIT)) {
     443               0 :       return NS_ERROR_FILE_CORRUPTED;
     444                 :     }
     445                 : 
     446               0 :     nsTArray<PRUint32> mNewIndexPrefixes;
     447               0 :     nsTArray<PRUint32> mNewIndexStarts;
     448               0 :     nsTArray<PRUint16> mNewDeltas;
     449                 : 
     450               0 :     mNewIndexStarts.SetLength(indexSize);
     451               0 :     mNewIndexPrefixes.SetLength(indexSize);
     452               0 :     mNewDeltas.SetLength(deltaSize);
     453                 : 
     454               0 :     PRInt32 toRead = indexSize*sizeof(PRUint32);
     455               0 :     read = PR_Read(fileFd, mNewIndexPrefixes.Elements(), toRead);
     456               0 :     NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED);
     457               0 :     read = PR_Read(fileFd, mNewIndexStarts.Elements(), toRead);
     458               0 :     NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED);
     459               0 :     if (deltaSize > 0) {
     460               0 :       toRead = deltaSize*sizeof(PRUint16);
     461               0 :       read = PR_Read(fileFd, mNewDeltas.Elements(), toRead);
     462               0 :       NS_ENSURE_TRUE(read == toRead, NS_ERROR_FILE_CORRUPTED);
     463                 :     }
     464                 : 
     465               0 :     MutexAutoLock lock(mPrefixSetLock);
     466                 : 
     467               0 :     mIndexPrefixes.SwapElements(mNewIndexPrefixes);
     468               0 :     mIndexStarts.SwapElements(mNewIndexStarts);
     469               0 :     mDeltas.SwapElements(mNewDeltas);
     470                 : 
     471               0 :     mHasPrefixes = true;
     472               0 :     mSetIsReady.NotifyAll();
     473                 :   } else {
     474               0 :     LOG(("Version magic mismatch, not loading"));
     475               0 :     return NS_ERROR_FAILURE;
     476                 :   }
     477                 : 
     478               0 :   LOG(("Loading PrefixSet successful"));
     479                 : 
     480               0 :   return NS_OK;
     481                 : }
     482                 : 
     483                 : NS_IMETHODIMP
     484               0 : nsUrlClassifierPrefixSet::LoadFromFile(nsIFile * aFile)
     485                 : {
     486                 :   nsresult rv;
     487               0 :   nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
     488               0 :   NS_ENSURE_SUCCESS(rv, rv);
     489                 : 
     490               0 :   AutoFDClose fileFd;
     491               0 :   rv = file->OpenNSPRFileDesc(PR_RDONLY | nsILocalFile::OS_READAHEAD, 0, &fileFd);
     492               0 :   NS_ENSURE_SUCCESS(rv, rv);
     493                 : 
     494               0 :   return LoadFromFd(fileFd);
     495                 : }
     496                 : 
     497                 : nsresult
     498             140 : nsUrlClassifierPrefixSet::StoreToFd(AutoFDClose & fileFd)
     499                 : {
     500                 :   {
     501             280 :       Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_PS_FALLOCATE_TIME> timer;
     502             140 :       PRInt64 size = 4 * sizeof(PRUint32);
     503             140 :       size += 2 * mIndexStarts.Length() * sizeof(PRUint32);
     504             140 :       size +=     mDeltas.Length() * sizeof(PRUint16);
     505                 : 
     506             140 :       mozilla::fallocate(fileFd, size);
     507                 :   }
     508                 : 
     509                 :   PRInt32 written;
     510             140 :   PRUint32 magic = PREFIXSET_VERSION_MAGIC;
     511             140 :   written = PR_Write(fileFd, &magic, sizeof(PRUint32));
     512             140 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     513                 : 
     514             140 :   written = PR_Write(fileFd, &mRandomKey, sizeof(PRUint32));
     515             140 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     516                 : 
     517             140 :   PRUint32 indexSize = mIndexStarts.Length();
     518             140 :   PRUint32 deltaSize = mDeltas.Length();
     519             140 :   written = PR_Write(fileFd, &indexSize, sizeof(PRUint32));
     520             140 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     521             140 :   written = PR_Write(fileFd, &deltaSize, sizeof(PRUint32));
     522             140 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     523                 : 
     524             140 :   written = PR_Write(fileFd, mIndexPrefixes.Elements(), indexSize * sizeof(PRUint32));
     525             140 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     526             140 :   written = PR_Write(fileFd, mIndexStarts.Elements(), indexSize * sizeof(PRUint32));
     527             140 :   NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     528             140 :   if (deltaSize > 0) {
     529               4 :     written = PR_Write(fileFd, mDeltas.Elements(), deltaSize * sizeof(PRUint16));
     530               4 :     NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
     531                 :   }
     532                 : 
     533             140 :   LOG(("Saving PrefixSet successful\n"));
     534                 : 
     535             140 :   return NS_OK;
     536                 : }
     537                 : 
     538                 : NS_IMETHODIMP
     539             140 : nsUrlClassifierPrefixSet::StoreToFile(nsIFile * aFile)
     540                 : {
     541             140 :   if (!mHasPrefixes) {
     542               0 :     LOG(("Attempt to serialize empty PrefixSet"));
     543               0 :     return NS_ERROR_FAILURE;
     544                 :   }
     545                 : 
     546                 :   nsresult rv;
     547             280 :   nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
     548             140 :   NS_ENSURE_SUCCESS(rv, rv);
     549                 : 
     550             280 :   AutoFDClose fileFd;
     551             140 :   rv = file->OpenNSPRFileDesc(PR_RDWR | PR_TRUNCATE | PR_CREATE_FILE,
     552             140 :                               0644, &fileFd);
     553             140 :   NS_ENSURE_SUCCESS(rv, rv);
     554                 : 
     555             280 :   MutexAutoLock lock(mPrefixSetLock);
     556                 : 
     557             140 :   return StoreToFd(fileFd);
     558                 : }

Generated by: LCOV version 1.7