LCOV - code coverage report
Current view: directory - rdf/base/src - nsRDFService.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 605 363 60.0 %
Date: 2012-06-02 Functions: 84 53 63.1 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  *
       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 mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Benjamin Smedberg <benjamin@smedbergs.us>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK *****
      39                 :  *
      40                 :  *
      41                 :  * This Original Code has been modified by IBM Corporation.
      42                 :  * Modifications made by IBM described herein are
      43                 :  * Copyright (c) International Business Machines
      44                 :  * Corporation, 2000
      45                 :  *
      46                 :  * Modifications to Mozilla code or documentation
      47                 :  * identified per MPL Section 3.3
      48                 :  *
      49                 :  * Date         Modified by     Description of modification
      50                 :  * 03/27/2000   IBM Corp.       Added PR_CALLBACK for Optlink
      51                 :  *                               use in OS2
      52                 :  */
      53                 : 
      54                 : /*
      55                 : 
      56                 :   This file provides the implementation for the RDF service manager.
      57                 : 
      58                 :   TO DO
      59                 :   -----
      60                 : 
      61                 :   1) Implement the CreateDataBase() methods.
      62                 : 
      63                 :   2) Cache date and int literals.
      64                 : 
      65                 :  */
      66                 : 
      67                 : #include "nsRDFService.h"
      68                 : #include "nsCOMPtr.h"
      69                 : #include "nsAutoPtr.h"
      70                 : #include "nsMemory.h"
      71                 : #include "nsIAtom.h"
      72                 : #include "nsIComponentManager.h"
      73                 : #include "nsIRDFDataSource.h"
      74                 : #include "nsIRDFNode.h"
      75                 : #include "nsIRDFRemoteDataSource.h"
      76                 : #include "nsIServiceManager.h"
      77                 : #include "nsIFactory.h"
      78                 : #include "nsRDFCID.h"
      79                 : #include "nsString.h"
      80                 : #include "nsXPIDLString.h"
      81                 : #include "nsNetUtil.h"
      82                 : #include "pldhash.h"
      83                 : #include "plhash.h"
      84                 : #include "plstr.h"
      85                 : #include "prlog.h"
      86                 : #include "prprf.h"
      87                 : #include "prmem.h"
      88                 : #include "rdf.h"
      89                 : #include "nsCRT.h"
      90                 : #include "nsCRTGlue.h"
      91                 : #include "prbit.h"
      92                 : #include "mozilla/HashFunctions.h"
      93                 : 
      94                 : using namespace mozilla;
      95                 : 
      96                 : ////////////////////////////////////////////////////////////////////////
      97                 : 
      98                 : static NS_DEFINE_CID(kRDFXMLDataSourceCID,    NS_RDFXMLDATASOURCE_CID);
      99                 : static NS_DEFINE_CID(kRDFDefaultResourceCID,  NS_RDFDEFAULTRESOURCE_CID);
     100                 : 
     101                 : static NS_DEFINE_IID(kIRDFLiteralIID,         NS_IRDFLITERAL_IID);
     102                 : static NS_DEFINE_IID(kIRDFDateIID,         NS_IRDFDATE_IID);
     103                 : static NS_DEFINE_IID(kIRDFIntIID,         NS_IRDFINT_IID);
     104                 : static NS_DEFINE_IID(kIRDFNodeIID,            NS_IRDFNODE_IID);
     105                 : static NS_DEFINE_IID(kISupportsIID,           NS_ISUPPORTS_IID);
     106                 : 
     107                 : #ifdef PR_LOGGING
     108                 : static PRLogModuleInfo* gLog = nsnull;
     109                 : #endif
     110                 : 
     111                 : class BlobImpl;
     112                 : 
     113                 : // These functions are copied from nsprpub/lib/ds/plhash.c, with one
     114                 : // change to free the key in DataSourceFreeEntry.
     115                 : // XXX sigh, why were DefaultAllocTable et. al. declared static, anyway?
     116                 : 
     117                 : static void *
     118            2815 : DataSourceAllocTable(void *pool, PRSize size)
     119                 : {
     120            2815 :     return PR_MALLOC(size);
     121                 : }
     122                 : 
     123                 : static void
     124            2813 : DataSourceFreeTable(void *pool, void *item)
     125                 : {
     126            2813 :     PR_Free(item);
     127            2813 : }
     128                 : 
     129                 : static PLHashEntry *
     130              10 : DataSourceAllocEntry(void *pool, const void *key)
     131                 : {
     132              10 :     return PR_NEW(PLHashEntry);
     133                 : }
     134                 : 
     135                 : static void
     136              10 : DataSourceFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
     137                 : {
     138              10 :     if (flag == HT_FREE_ENTRY) {
     139              10 :         PL_strfree((char*) he->key);
     140              10 :         PR_Free(he);
     141                 :     }
     142              10 : }
     143                 : 
     144                 : static PLHashAllocOps dataSourceHashAllocOps = {
     145                 :     DataSourceAllocTable, DataSourceFreeTable,
     146                 :     DataSourceAllocEntry, DataSourceFreeEntry
     147                 : };
     148                 : 
     149                 : //----------------------------------------------------------------------
     150                 : //
     151                 : // For the mResources hashtable.
     152                 : //
     153                 : 
     154                 : struct ResourceHashEntry : public PLDHashEntryHdr {
     155                 :     const char *mKey;
     156                 :     nsIRDFResource *mResource;
     157                 : 
     158                 :     static PLDHashNumber
     159          364509 :     HashKey(PLDHashTable *table, const void *key)
     160                 :     {
     161          364509 :         return HashString(static_cast<const char *>(key));
     162                 :     }
     163                 : 
     164                 :     static bool
     165          195237 :     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
     166                 :                const void *key)
     167                 :     {
     168                 :         const ResourceHashEntry *entry =
     169          195237 :             static_cast<const ResourceHashEntry *>(hdr);
     170                 : 
     171                 :         return 0 == nsCRT::strcmp(static_cast<const char *>(key),
     172          195237 :                                   entry->mKey);
     173                 :     }
     174                 : };
     175                 : 
     176                 : static PLDHashTableOps gResourceTableOps = {
     177                 :     PL_DHashAllocTable,
     178                 :     PL_DHashFreeTable,
     179                 :     ResourceHashEntry::HashKey,
     180                 :     ResourceHashEntry::MatchEntry,
     181                 :     PL_DHashMoveEntryStub,
     182                 :     PL_DHashClearEntryStub,
     183                 :     PL_DHashFinalizeStub,
     184                 :     nsnull
     185                 : };
     186                 : 
     187                 : // ----------------------------------------------------------------------
     188                 : //
     189                 : // For the mLiterals hashtable.
     190                 : //
     191                 : 
     192                 : struct LiteralHashEntry : public PLDHashEntryHdr {
     193                 :     nsIRDFLiteral *mLiteral;
     194                 :     const PRUnichar *mKey;
     195                 : 
     196                 :     static PLDHashNumber
     197           65008 :     HashKey(PLDHashTable *table, const void *key)
     198                 :     {
     199           65008 :         return HashString(static_cast<const PRUnichar *>(key));
     200                 :     }
     201                 : 
     202                 :     static bool
     203           36976 :     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
     204                 :                const void *key)
     205                 :     {
     206                 :         const LiteralHashEntry *entry =
     207           36976 :             static_cast<const LiteralHashEntry *>(hdr);
     208                 : 
     209                 :         return 0 == nsCRT::strcmp(static_cast<const PRUnichar *>(key),
     210           36976 :                                   entry->mKey);
     211                 :     }
     212                 : };
     213                 : 
     214                 : static PLDHashTableOps gLiteralTableOps = {
     215                 :     PL_DHashAllocTable,
     216                 :     PL_DHashFreeTable,
     217                 :     LiteralHashEntry::HashKey,
     218                 :     LiteralHashEntry::MatchEntry,
     219                 :     PL_DHashMoveEntryStub,
     220                 :     PL_DHashClearEntryStub,
     221                 :     PL_DHashFinalizeStub,
     222                 :     nsnull
     223                 : };
     224                 : 
     225                 : // ----------------------------------------------------------------------
     226                 : //
     227                 : // For the mInts hashtable.
     228                 : //
     229                 : 
     230                 : struct IntHashEntry : public PLDHashEntryHdr {
     231                 :     nsIRDFInt *mInt;
     232                 :     PRInt32    mKey;
     233                 : 
     234                 :     static PLDHashNumber
     235              64 :     HashKey(PLDHashTable *table, const void *key)
     236                 :     {
     237              64 :         return PLDHashNumber(*static_cast<const PRInt32 *>(key));
     238                 :     }
     239                 : 
     240                 :     static bool
     241              40 :     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
     242                 :                const void *key)
     243                 :     {
     244                 :         const IntHashEntry *entry =
     245              40 :             static_cast<const IntHashEntry *>(hdr);
     246                 : 
     247              40 :         return *static_cast<const PRInt32 *>(key) == entry->mKey;
     248                 :     }
     249                 : };
     250                 : 
     251                 : static PLDHashTableOps gIntTableOps = {
     252                 :     PL_DHashAllocTable,
     253                 :     PL_DHashFreeTable,
     254                 :     IntHashEntry::HashKey,
     255                 :     IntHashEntry::MatchEntry,
     256                 :     PL_DHashMoveEntryStub,
     257                 :     PL_DHashClearEntryStub,
     258                 :     PL_DHashFinalizeStub,
     259                 :     nsnull
     260                 : };
     261                 : 
     262                 : // ----------------------------------------------------------------------
     263                 : //
     264                 : // For the mDates hashtable.
     265                 : //
     266                 : 
     267                 : struct DateHashEntry : public PLDHashEntryHdr {
     268                 :     nsIRDFDate *mDate;
     269                 :     PRTime      mKey;
     270                 : 
     271                 :     static PLDHashNumber
     272               0 :     HashKey(PLDHashTable *table, const void *key)
     273                 :     {
     274                 :         // xor the low 32 bits with the high 32 bits.
     275               0 :         PRTime t = *static_cast<const PRTime *>(key);
     276                 :         PRInt64 h64, l64;
     277               0 :         LL_USHR(h64, t, 32);
     278               0 :         l64 = LL_INIT(0, 0xffffffff);
     279               0 :         LL_AND(l64, l64, t);
     280                 :         PRInt32 h32, l32;
     281               0 :         LL_L2I(h32, h64);
     282               0 :         LL_L2I(l32, l64);
     283               0 :         return PLDHashNumber(l32 ^ h32);
     284                 :     }
     285                 : 
     286                 :     static bool
     287               0 :     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
     288                 :                const void *key)
     289                 :     {
     290                 :         const DateHashEntry *entry =
     291               0 :             static_cast<const DateHashEntry *>(hdr);
     292                 : 
     293               0 :         return LL_EQ(*static_cast<const PRTime *>(key), entry->mKey);
     294                 :     }
     295                 : };
     296                 : 
     297                 : static PLDHashTableOps gDateTableOps = {
     298                 :     PL_DHashAllocTable,
     299                 :     PL_DHashFreeTable,
     300                 :     DateHashEntry::HashKey,
     301                 :     DateHashEntry::MatchEntry,
     302                 :     PL_DHashMoveEntryStub,
     303                 :     PL_DHashClearEntryStub,
     304                 :     PL_DHashFinalizeStub,
     305                 :     nsnull
     306                 : };
     307                 : 
     308                 : class BlobImpl : public nsIRDFBlob
     309                 : {
     310                 : public:
     311                 :     struct Data {
     312                 :         PRInt32  mLength;
     313                 :         PRUint8 *mBytes;
     314                 :     };
     315                 : 
     316               0 :     BlobImpl(const PRUint8 *aBytes, PRInt32 aLength)
     317               0 :     {
     318               0 :         mData.mLength = aLength;
     319               0 :         mData.mBytes = new PRUint8[aLength];
     320               0 :         memcpy(mData.mBytes, aBytes, aLength);
     321               0 :         NS_ADDREF(RDFServiceImpl::gRDFService);
     322               0 :         RDFServiceImpl::gRDFService->RegisterBlob(this);
     323               0 :     }
     324                 : 
     325               0 :     virtual ~BlobImpl()
     326               0 :     {
     327               0 :         RDFServiceImpl::gRDFService->UnregisterBlob(this);
     328                 :         // Use NS_RELEASE2() here, because we want to decrease the
     329                 :         // refcount, but not null out the gRDFService pointer (which is
     330                 :         // what a vanilla NS_RELEASE() would do).
     331                 :         nsrefcnt refcnt;
     332               0 :         NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
     333               0 :         delete[] mData.mBytes;
     334               0 :     }
     335                 : 
     336                 :     NS_DECL_ISUPPORTS
     337                 :     NS_DECL_NSIRDFNODE
     338                 :     NS_DECL_NSIRDFBLOB
     339                 : 
     340                 :     Data mData;
     341                 : };
     342                 : 
     343               0 : NS_IMPL_ISUPPORTS2(BlobImpl, nsIRDFNode, nsIRDFBlob)
     344                 : 
     345                 : NS_IMETHODIMP
     346               0 : BlobImpl::EqualsNode(nsIRDFNode *aNode, bool *aEquals)
     347                 : {
     348               0 :     nsCOMPtr<nsIRDFBlob> blob = do_QueryInterface(aNode);
     349               0 :     if (blob) {
     350                 :         PRInt32 length;
     351               0 :         blob->GetLength(&length);
     352                 : 
     353               0 :         if (length == mData.mLength) {
     354                 :             const PRUint8 *bytes;
     355               0 :             blob->GetValue(&bytes);
     356                 : 
     357               0 :             if (0 == memcmp(bytes, mData.mBytes, length)) {
     358               0 :                 *aEquals = true;
     359               0 :                 return NS_OK;
     360                 :             }
     361                 :         }
     362                 :     }
     363                 : 
     364               0 :     *aEquals = false;
     365               0 :     return NS_OK;
     366                 : }
     367                 : 
     368                 : NS_IMETHODIMP
     369               0 : BlobImpl::GetValue(const PRUint8 **aResult)
     370                 : {
     371               0 :     *aResult = mData.mBytes;
     372               0 :     return NS_OK;
     373                 : }
     374                 : 
     375                 : NS_IMETHODIMP
     376               0 : BlobImpl::GetLength(PRInt32 *aResult)
     377                 : {
     378               0 :     *aResult = mData.mLength;
     379               0 :     return NS_OK;
     380                 : }
     381                 : 
     382                 : // ----------------------------------------------------------------------
     383                 : //
     384                 : // For the mBlobs hashtable.
     385                 : //
     386                 : 
     387                 : struct BlobHashEntry : public PLDHashEntryHdr {
     388                 :     BlobImpl *mBlob;
     389                 : 
     390                 :     static PLDHashNumber
     391               0 :     HashKey(PLDHashTable *table, const void *key)
     392                 :     {
     393                 :         const BlobImpl::Data *data =
     394               0 :             static_cast<const BlobImpl::Data *>(key);
     395               0 :         return HashBytes(data->mBytes, data->mLength);
     396                 :     }
     397                 : 
     398                 :     static bool
     399               0 :     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
     400                 :                const void *key)
     401                 :     {
     402                 :         const BlobHashEntry *entry =
     403               0 :             static_cast<const BlobHashEntry *>(hdr);
     404                 : 
     405               0 :         const BlobImpl::Data *left = &entry->mBlob->mData;
     406                 : 
     407                 :         const BlobImpl::Data *right =
     408               0 :             static_cast<const BlobImpl::Data *>(key);
     409                 : 
     410                 :         return (left->mLength == right->mLength)
     411               0 :             && 0 == memcmp(left->mBytes, right->mBytes, right->mLength);
     412                 :     }
     413                 : };
     414                 : 
     415                 : static PLDHashTableOps gBlobTableOps = {
     416                 :     PL_DHashAllocTable,
     417                 :     PL_DHashFreeTable,
     418                 :     BlobHashEntry::HashKey,
     419                 :     BlobHashEntry::MatchEntry,
     420                 :     PL_DHashMoveEntryStub,
     421                 :     PL_DHashClearEntryStub,
     422                 :     PL_DHashFinalizeStub,
     423                 :     nsnull
     424                 : };
     425                 : 
     426                 : ////////////////////////////////////////////////////////////////////////
     427                 : // LiteralImpl
     428                 : //
     429                 : //   Currently, all literals are implemented exactly the same way;
     430                 : //   i.e., there is are no resource factories to allow you to generate
     431                 : //   customer resources. I doubt that makes sense, anyway.
     432                 : //
     433                 : class LiteralImpl : public nsIRDFLiteral {
     434                 : public:
     435                 :     static nsresult
     436                 :     Create(const PRUnichar* aValue, nsIRDFLiteral** aResult);
     437                 : 
     438                 :     // nsISupports
     439                 :     NS_DECL_ISUPPORTS
     440                 : 
     441                 :     // nsIRDFNode
     442                 :     NS_DECL_NSIRDFNODE
     443                 : 
     444                 :     // nsIRDFLiteral
     445                 :     NS_DECL_NSIRDFLITERAL
     446                 : 
     447                 : protected:
     448                 :     LiteralImpl(const PRUnichar* s);
     449                 :     virtual ~LiteralImpl();
     450                 : 
     451           37607 :     const PRUnichar* GetValue() const {
     452           37607 :         size_t objectSize = ((sizeof(LiteralImpl) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
     453           37607 :         return reinterpret_cast<const PRUnichar*>(reinterpret_cast<const unsigned char*>(this) + objectSize);
     454                 :     }
     455                 : };
     456                 : 
     457                 : 
     458                 : nsresult
     459            9344 : LiteralImpl::Create(const PRUnichar* aValue, nsIRDFLiteral** aResult)
     460                 : {
     461                 :     // Goofy math to get alignment right. Copied from nsSharedString.h.
     462            9344 :     size_t objectSize = ((sizeof(LiteralImpl) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
     463            9344 :     size_t stringLen = nsCharTraits<PRUnichar>::length(aValue);
     464            9344 :     size_t stringSize = (stringLen + 1) * sizeof(PRUnichar);
     465                 : 
     466           18688 :     void* objectPtr = operator new(objectSize + stringSize);
     467            9344 :     if (! objectPtr)
     468               0 :         return NS_ERROR_NULL_POINTER;
     469                 : 
     470            9344 :     PRUnichar* buf = reinterpret_cast<PRUnichar*>(static_cast<unsigned char*>(objectPtr) + objectSize);
     471            9344 :     nsCharTraits<PRUnichar>::copy(buf, aValue, stringLen + 1);
     472                 : 
     473            9344 :     NS_ADDREF(*aResult = new (objectPtr) LiteralImpl(buf));
     474            9344 :     return NS_OK;
     475                 : }
     476                 : 
     477                 : 
     478            9344 : LiteralImpl::LiteralImpl(const PRUnichar* s)
     479                 : {
     480            9344 :     RDFServiceImpl::gRDFService->RegisterLiteral(this);
     481            9344 :     NS_ADDREF(RDFServiceImpl::gRDFService);
     482            9344 : }
     483                 : 
     484           18686 : LiteralImpl::~LiteralImpl()
     485                 : {
     486            9343 :     RDFServiceImpl::gRDFService->UnregisterLiteral(this);
     487                 : 
     488                 :     // Use NS_RELEASE2() here, because we want to decrease the
     489                 :     // refcount, but not null out the gRDFService pointer (which is
     490                 :     // what a vanilla NS_RELEASE() would do).
     491                 :     nsrefcnt refcnt;
     492            9343 :     NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
     493           37372 : }
     494                 : 
     495          140354 : NS_IMPL_THREADSAFE_ADDREF(LiteralImpl)
     496          140353 : NS_IMPL_THREADSAFE_RELEASE(LiteralImpl)
     497                 : 
     498                 : nsresult
     499          148000 : LiteralImpl::QueryInterface(REFNSIID iid, void** result)
     500                 : {
     501          148000 :     if (! result)
     502               0 :         return NS_ERROR_NULL_POINTER;
     503                 : 
     504          148000 :     *result = nsnull;
     505          376029 :     if (iid.Equals(kIRDFLiteralIID) ||
     506          131165 :         iid.Equals(kIRDFNodeIID) ||
     507           96864 :         iid.Equals(kISupportsIID)) {
     508           66782 :         *result = static_cast<nsIRDFLiteral*>(this);
     509           66782 :         AddRef();
     510           66782 :         return NS_OK;
     511                 :     }
     512           81218 :     return NS_NOINTERFACE;
     513                 : }
     514                 : 
     515                 : NS_IMETHODIMP
     516               0 : LiteralImpl::EqualsNode(nsIRDFNode* aNode, bool* aResult)
     517                 : {
     518                 :     nsresult rv;
     519                 :     nsIRDFLiteral* literal;
     520               0 :     rv = aNode->QueryInterface(kIRDFLiteralIID, (void**) &literal);
     521               0 :     if (NS_SUCCEEDED(rv)) {
     522               0 :         *aResult = (static_cast<nsIRDFLiteral*>(this) == literal);
     523               0 :         NS_RELEASE(literal);
     524               0 :         return NS_OK;
     525                 :     }
     526               0 :     else if (rv == NS_NOINTERFACE) {
     527               0 :         *aResult = false;
     528               0 :         return NS_OK;
     529                 :     }
     530                 :     else {
     531               0 :         return rv;
     532                 :     }
     533                 : }
     534                 : 
     535                 : NS_IMETHODIMP
     536           15130 : LiteralImpl::GetValue(PRUnichar* *value)
     537                 : {
     538           15130 :     NS_ASSERTION(value, "null ptr");
     539           15130 :     if (! value)
     540               0 :         return NS_ERROR_NULL_POINTER;
     541                 : 
     542           15130 :     const PRUnichar *temp = GetValue();
     543           15130 :     *value = temp? NS_strdup(temp) : 0;
     544           15130 :     return NS_OK;
     545                 : }
     546                 : 
     547                 : 
     548                 : NS_IMETHODIMP
     549           22477 : LiteralImpl::GetValueConst(const PRUnichar** aValue)
     550                 : {
     551           22477 :     *aValue = GetValue();
     552           22477 :     return NS_OK;
     553                 : }
     554                 : 
     555                 : ////////////////////////////////////////////////////////////////////////
     556                 : // DateImpl
     557                 : //
     558                 : 
     559                 : class DateImpl : public nsIRDFDate {
     560                 : public:
     561                 :     DateImpl(const PRTime s);
     562                 :     virtual ~DateImpl();
     563                 : 
     564                 :     // nsISupports
     565                 :     NS_DECL_ISUPPORTS
     566                 : 
     567                 :     // nsIRDFNode
     568                 :     NS_DECL_NSIRDFNODE
     569                 : 
     570                 :     // nsIRDFDate
     571                 :     NS_IMETHOD GetValue(PRTime *value);
     572                 : 
     573                 : private:
     574                 :     nsresult EqualsDate(nsIRDFDate* date, bool* result);
     575                 :     PRTime mValue;
     576                 : };
     577                 : 
     578                 : 
     579               0 : DateImpl::DateImpl(const PRTime s)
     580               0 :     : mValue(s)
     581                 : {
     582               0 :     RDFServiceImpl::gRDFService->RegisterDate(this);
     583               0 :     NS_ADDREF(RDFServiceImpl::gRDFService);
     584               0 : }
     585                 : 
     586               0 : DateImpl::~DateImpl()
     587                 : {
     588               0 :     RDFServiceImpl::gRDFService->UnregisterDate(this);
     589                 : 
     590                 :     // Use NS_RELEASE2() here, because we want to decrease the
     591                 :     // refcount, but not null out the gRDFService pointer (which is
     592                 :     // what a vanilla NS_RELEASE() would do).
     593                 :     nsrefcnt refcnt;
     594               0 :     NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
     595               0 : }
     596                 : 
     597               0 : NS_IMPL_ADDREF(DateImpl)
     598               0 : NS_IMPL_RELEASE(DateImpl)
     599                 : 
     600                 : nsresult
     601               0 : DateImpl::QueryInterface(REFNSIID iid, void** result)
     602                 : {
     603               0 :     if (! result)
     604               0 :         return NS_ERROR_NULL_POINTER;
     605                 : 
     606               0 :     *result = nsnull;
     607               0 :     if (iid.Equals(kIRDFDateIID) ||
     608               0 :         iid.Equals(kIRDFNodeIID) ||
     609               0 :         iid.Equals(kISupportsIID)) {
     610               0 :         *result = static_cast<nsIRDFDate*>(this);
     611               0 :         AddRef();
     612               0 :         return NS_OK;
     613                 :     }
     614               0 :     return NS_NOINTERFACE;
     615                 : }
     616                 : 
     617                 : NS_IMETHODIMP
     618               0 : DateImpl::EqualsNode(nsIRDFNode* node, bool* result)
     619                 : {
     620                 :     nsresult rv;
     621                 :     nsIRDFDate* date;
     622               0 :     if (NS_SUCCEEDED(node->QueryInterface(kIRDFDateIID, (void**) &date))) {
     623               0 :         rv = EqualsDate(date, result);
     624               0 :         NS_RELEASE(date);
     625                 :     }
     626                 :     else {
     627               0 :         *result = false;
     628               0 :         rv = NS_OK;
     629                 :     }
     630               0 :     return rv;
     631                 : }
     632                 : 
     633                 : NS_IMETHODIMP
     634               0 : DateImpl::GetValue(PRTime *value)
     635                 : {
     636               0 :     NS_ASSERTION(value, "null ptr");
     637               0 :     if (! value)
     638               0 :         return NS_ERROR_NULL_POINTER;
     639                 : 
     640               0 :     *value = mValue;
     641               0 :     return NS_OK;
     642                 : }
     643                 : 
     644                 : 
     645                 : nsresult
     646               0 : DateImpl::EqualsDate(nsIRDFDate* date, bool* result)
     647                 : {
     648               0 :     NS_ASSERTION(date && result, "null ptr");
     649               0 :     if (!date || !result)
     650               0 :         return NS_ERROR_NULL_POINTER;
     651                 : 
     652                 :     nsresult rv;
     653                 :     PRTime p;
     654               0 :     if (NS_FAILED(rv = date->GetValue(&p)))
     655               0 :         return rv;
     656                 : 
     657               0 :     *result = LL_EQ(p, mValue);
     658               0 :     return NS_OK;
     659                 : }
     660                 : 
     661                 : ////////////////////////////////////////////////////////////////////////
     662                 : // IntImpl
     663                 : //
     664                 : 
     665                 : class IntImpl : public nsIRDFInt {
     666                 : public:
     667                 :     IntImpl(PRInt32 s);
     668                 :     virtual ~IntImpl();
     669                 : 
     670                 :     // nsISupports
     671                 :     NS_DECL_ISUPPORTS
     672                 : 
     673                 :     // nsIRDFNode
     674                 :     NS_DECL_NSIRDFNODE
     675                 : 
     676                 :     // nsIRDFInt
     677                 :     NS_IMETHOD GetValue(PRInt32 *value);
     678                 : 
     679                 : private:
     680                 :     nsresult EqualsInt(nsIRDFInt* value, bool* result);
     681                 :     PRInt32 mValue;
     682                 : };
     683                 : 
     684                 : 
     685               8 : IntImpl::IntImpl(PRInt32 s)
     686               8 :     : mValue(s)
     687                 : {
     688               8 :     RDFServiceImpl::gRDFService->RegisterInt(this);
     689               8 :     NS_ADDREF(RDFServiceImpl::gRDFService);
     690               8 : }
     691                 : 
     692              16 : IntImpl::~IntImpl()
     693                 : {
     694               8 :     RDFServiceImpl::gRDFService->UnregisterInt(this);
     695                 : 
     696                 :     // Use NS_RELEASE2() here, because we want to decrease the
     697                 :     // refcount, but not null out the gRDFService pointer (which is
     698                 :     // what a vanilla NS_RELEASE() would do).
     699                 :     nsrefcnt refcnt;
     700               8 :     NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
     701              32 : }
     702                 : 
     703              96 : NS_IMPL_ADDREF(IntImpl)
     704              96 : NS_IMPL_RELEASE(IntImpl)
     705                 : 
     706                 : nsresult
     707              32 : IntImpl::QueryInterface(REFNSIID iid, void** result)
     708                 : {
     709              32 :     if (! result)
     710               0 :         return NS_ERROR_NULL_POINTER;
     711                 : 
     712              32 :     *result = nsnull;
     713              64 :     if (iid.Equals(kIRDFIntIID) ||
     714              32 :         iid.Equals(kIRDFNodeIID) ||
     715               0 :         iid.Equals(kISupportsIID)) {
     716              32 :         *result = static_cast<nsIRDFInt*>(this);
     717              32 :         AddRef();
     718              32 :         return NS_OK;
     719                 :     }
     720               0 :     return NS_NOINTERFACE;
     721                 : }
     722                 : 
     723                 : NS_IMETHODIMP
     724               0 : IntImpl::EqualsNode(nsIRDFNode* node, bool* result)
     725                 : {
     726                 :     nsresult rv;
     727                 :     nsIRDFInt* intValue;
     728               0 :     if (NS_SUCCEEDED(node->QueryInterface(kIRDFIntIID, (void**) &intValue))) {
     729               0 :         rv = EqualsInt(intValue, result);
     730               0 :         NS_RELEASE(intValue);
     731                 :     }
     732                 :     else {
     733               0 :         *result = false;
     734               0 :         rv = NS_OK;
     735                 :     }
     736               0 :     return rv;
     737                 : }
     738                 : 
     739                 : NS_IMETHODIMP
     740              16 : IntImpl::GetValue(PRInt32 *value)
     741                 : {
     742              16 :     NS_ASSERTION(value, "null ptr");
     743              16 :     if (! value)
     744               0 :         return NS_ERROR_NULL_POINTER;
     745                 : 
     746              16 :     *value = mValue;
     747              16 :     return NS_OK;
     748                 : }
     749                 : 
     750                 : 
     751                 : nsresult
     752               0 : IntImpl::EqualsInt(nsIRDFInt* intValue, bool* result)
     753                 : {
     754               0 :     NS_ASSERTION(intValue && result, "null ptr");
     755               0 :     if (!intValue || !result)
     756               0 :         return NS_ERROR_NULL_POINTER;
     757                 : 
     758                 :     nsresult rv;
     759                 :     PRInt32 p;
     760               0 :     if (NS_FAILED(rv = intValue->GetValue(&p)))
     761               0 :         return rv;
     762                 : 
     763               0 :     *result = (p == mValue);
     764               0 :     return NS_OK;
     765                 : }
     766                 : 
     767                 : ////////////////////////////////////////////////////////////////////////
     768                 : // RDFServiceImpl
     769                 : 
     770                 : RDFServiceImpl*
     771                 : RDFServiceImpl::gRDFService;
     772                 : 
     773            1404 : RDFServiceImpl::RDFServiceImpl()
     774            1404 :     :  mNamedDataSources(nsnull)
     775                 : {
     776            1404 :     mResources.ops = nsnull;
     777            1404 :     mLiterals.ops = nsnull;
     778            1404 :     mInts.ops = nsnull;
     779            1404 :     mDates.ops = nsnull;
     780            1404 :     mBlobs.ops = nsnull;
     781            1404 :     gRDFService = this;
     782            1404 : }
     783                 : 
     784                 : nsresult
     785            1404 : RDFServiceImpl::Init()
     786                 : {
     787                 :     nsresult rv;
     788                 : 
     789                 :     mNamedDataSources = PL_NewHashTable(23,
     790                 :                                         PL_HashString,
     791                 :                                         PL_CompareStrings,
     792                 :                                         PL_CompareValues,
     793            1404 :                                         &dataSourceHashAllocOps, nsnull);
     794                 : 
     795            1404 :     if (! mNamedDataSources)
     796               0 :         return NS_ERROR_OUT_OF_MEMORY;
     797                 : 
     798            1404 :     if (!PL_DHashTableInit(&mResources, &gResourceTableOps, nsnull,
     799            1404 :                            sizeof(ResourceHashEntry), PL_DHASH_MIN_SIZE)) {
     800               0 :         mResources.ops = nsnull;
     801               0 :         return NS_ERROR_OUT_OF_MEMORY;
     802                 :     }
     803            1404 :     if (!PL_DHashTableInit(&mLiterals, &gLiteralTableOps, nsnull,
     804            1404 :                            sizeof(LiteralHashEntry), PL_DHASH_MIN_SIZE)) {
     805               0 :         mLiterals.ops = nsnull;
     806               0 :         return NS_ERROR_OUT_OF_MEMORY;
     807                 :     }
     808            1404 :     if (!PL_DHashTableInit(&mInts, &gIntTableOps, nsnull,
     809            1404 :                            sizeof(IntHashEntry), PL_DHASH_MIN_SIZE)) {
     810               0 :         mInts.ops = nsnull;
     811               0 :         return NS_ERROR_OUT_OF_MEMORY;
     812                 :     }
     813            1404 :     if (!PL_DHashTableInit(&mDates, &gDateTableOps, nsnull,
     814            1404 :                            sizeof(DateHashEntry), PL_DHASH_MIN_SIZE)) {
     815               0 :         mDates.ops = nsnull;
     816               0 :         return NS_ERROR_OUT_OF_MEMORY;
     817                 :     }
     818            1404 :     if (!PL_DHashTableInit(&mBlobs, &gBlobTableOps, nsnull,
     819            1404 :                            sizeof(BlobHashEntry), PL_DHASH_MIN_SIZE)) {
     820               0 :         mBlobs.ops = nsnull;
     821               0 :         return NS_ERROR_OUT_OF_MEMORY;
     822                 :     }
     823            1404 :     mDefaultResourceFactory = do_GetClassObject(kRDFDefaultResourceCID, &rv);
     824            1404 :     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get default resource factory");
     825            1404 :     if (NS_FAILED(rv)) return rv;
     826                 : 
     827                 : #ifdef PR_LOGGING
     828            1404 :     if (! gLog)
     829            1404 :         gLog = PR_NewLogModule("nsRDFService");
     830                 : #endif
     831                 : 
     832            1404 :     return NS_OK;
     833                 : }
     834                 : 
     835                 : 
     836            4209 : RDFServiceImpl::~RDFServiceImpl()
     837                 : {
     838            1403 :     if (mNamedDataSources) {
     839            1403 :         PL_HashTableDestroy(mNamedDataSources);
     840            1403 :         mNamedDataSources = nsnull;
     841                 :     }
     842            1403 :     if (mResources.ops)
     843            1403 :         PL_DHashTableFinish(&mResources);
     844            1403 :     if (mLiterals.ops)
     845            1403 :         PL_DHashTableFinish(&mLiterals);
     846            1403 :     if (mInts.ops)
     847            1403 :         PL_DHashTableFinish(&mInts);
     848            1403 :     if (mDates.ops)
     849            1403 :         PL_DHashTableFinish(&mDates);
     850            1403 :     if (mBlobs.ops)
     851            1403 :         PL_DHashTableFinish(&mBlobs);
     852            1403 :     gRDFService = nsnull;
     853            5612 : }
     854                 : 
     855                 : 
     856                 : // static
     857                 : nsresult
     858            1404 : RDFServiceImpl::CreateSingleton(nsISupports* aOuter,
     859                 :                                 const nsIID& aIID, void **aResult)
     860                 : {
     861            1404 :     NS_ENSURE_NO_AGGREGATION(aOuter);
     862                 : 
     863            1404 :     if (gRDFService) {
     864               0 :         NS_ERROR("Trying to create RDF serviec twice.");
     865               0 :         return gRDFService->QueryInterface(aIID, aResult);
     866                 :     }
     867                 : 
     868            2808 :     nsRefPtr<RDFServiceImpl> serv = new RDFServiceImpl();
     869            1404 :     if (!serv)
     870               0 :         return NS_ERROR_OUT_OF_MEMORY;
     871                 : 
     872            1404 :     nsresult rv = serv->Init();
     873            1404 :     if (NS_FAILED(rv))
     874               0 :         return rv;
     875                 : 
     876            1404 :     return serv->QueryInterface(aIID, aResult);
     877                 : }
     878                 : 
     879           68912 : NS_IMPL_THREADSAFE_ISUPPORTS2(RDFServiceImpl, nsIRDFService, nsISupportsWeakReference)
     880                 : 
     881                 : // Per RFC2396.
     882                 : static const PRUint8
     883                 : kLegalSchemeChars[] = {
     884                 :           //        ASCII    Bits     Ordered  Hex
     885                 :           //                 01234567 76543210
     886                 :     0x00, // 00-07
     887                 :     0x00, // 08-0F
     888                 :     0x00, // 10-17
     889                 :     0x00, // 18-1F
     890                 :     0x00, // 20-27   !"#$%&' 00000000 00000000
     891                 :     0x28, // 28-2F  ()*+,-./ 00010100 00101000 0x28
     892                 :     0xff, // 30-37  01234567 11111111 11111111 0xFF
     893                 :     0x03, // 38-3F  89:;<=>? 11000000 00000011 0x03
     894                 :     0xfe, // 40-47  @ABCDEFG 01111111 11111110 0xFE
     895                 :     0xff, // 48-4F  HIJKLMNO 11111111 11111111 0xFF
     896                 :     0xff, // 50-57  PQRSTUVW 11111111 11111111 0xFF
     897                 :     0x87, // 58-5F  XYZ[\]^_ 11100001 10000111 0x87
     898                 :     0xfe, // 60-67  `abcdefg 01111111 11111110 0xFE
     899                 :     0xff, // 68-6F  hijklmno 11111111 11111111 0xFF
     900                 :     0xff, // 70-77  pqrstuvw 11111111 11111111 0xFF
     901                 :     0x07, // 78-7F  xyz{|}~  11100000 00000111 0x07
     902                 :     0x00, 0x00, 0x00, 0x00, // >= 80
     903                 :     0x00, 0x00, 0x00, 0x00,
     904                 :     0x00, 0x00, 0x00, 0x00,
     905                 :     0x00, 0x00, 0x00, 0x00
     906                 : };
     907                 : 
     908                 : static inline bool
     909          243780 : IsLegalSchemeCharacter(const char aChar)
     910                 : {
     911          243780 :     PRUint8 mask = kLegalSchemeChars[aChar >> 3];
     912          243780 :     PRUint8 bit = PR_BIT(aChar & 0x7);
     913          243780 :     return bool((mask & bit) != 0);
     914                 : }
     915                 : 
     916                 : 
     917                 : NS_IMETHODIMP
     918          138819 : RDFServiceImpl::GetResource(const nsACString& aURI, nsIRDFResource** aResource)
     919                 : {
     920                 :     // Sanity checks
     921          138819 :     NS_PRECONDITION(aResource != nsnull, "null ptr");
     922          138819 :     NS_PRECONDITION(!aURI.IsEmpty(), "URI is empty");
     923          138819 :     if (! aResource)
     924               0 :         return NS_ERROR_NULL_POINTER;
     925          138819 :     if (aURI.IsEmpty())
     926               0 :         return NS_ERROR_INVALID_ARG;
     927                 : 
     928          277638 :     const nsAFlatCString& flatURI = PromiseFlatCString(aURI);
     929          138819 :     PR_LOG(gLog, PR_LOG_DEBUG, ("rdfserv get-resource %s", flatURI.get()));
     930                 : 
     931                 :     // First, check the cache to see if we've already created and
     932                 :     // registered this thing.
     933                 :     PLDHashEntryHdr *hdr =
     934          138819 :         PL_DHashTableOperate(&mResources, flatURI.get(), PL_DHASH_LOOKUP);
     935                 : 
     936          138819 :     if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
     937           82395 :         ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
     938           82395 :         NS_ADDREF(*aResource = entry->mResource);
     939           82395 :         return NS_OK;
     940                 :     }
     941                 : 
     942                 :     // Nope. So go to the repository to create it.
     943                 : 
     944                 :     // Compute the scheme of the URI. Scan forward until we either:
     945                 :     //
     946                 :     // 1. Reach the end of the string
     947                 :     // 2. Encounter a non-alpha character
     948                 :     // 3. Encouter a colon.
     949                 :     //
     950                 :     // If we encounter a colon _before_ encountering a non-alpha
     951                 :     // character, then assume it's the scheme.
     952                 :     //
     953                 :     // XXX Although it's really not correct, we'll allow underscore
     954                 :     // characters ('_'), too.
     955           56424 :     nsACString::const_iterator p, end;
     956           56424 :     aURI.BeginReading(p);
     957           56424 :     aURI.EndReading(end);
     958          300204 :     while (p != end && IsLegalSchemeCharacter(*p))
     959          187356 :         ++p;
     960                 : 
     961                 :     nsresult rv;
     962          112848 :     nsCOMPtr<nsIFactory> factory;
     963                 : 
     964           56424 :     nsACString::const_iterator begin;
     965           56424 :     aURI.BeginReading(begin);
     966           56424 :     if (*p == ':') {
     967                 :         // There _was_ a scheme. First see if it's the same scheme
     968                 :         // that we just tried to use...
     969           56424 :         if (mLastFactory && mLastURIPrefix.Equals(Substring(begin, p)))
     970           41801 :             factory = mLastFactory;
     971                 :         else {
     972                 :             // Try to find a factory using the component manager.
     973           14623 :             nsACString::const_iterator begin;
     974           14623 :             aURI.BeginReading(begin);
     975           29246 :             nsCAutoString contractID;
     976           14623 :             contractID = NS_LITERAL_CSTRING(NS_RDF_RESOURCE_FACTORY_CONTRACTID_PREFIX) +
     977           29246 :                          Substring(begin, p);
     978                 : 
     979           14623 :             factory = do_GetClassObject(contractID.get());
     980           14623 :             if (factory) {
     981                 :                 // Store the factory in our one-element cache.
     982               0 :                 if (p != begin) {
     983               0 :                     mLastFactory = factory;
     984               0 :                     mLastURIPrefix = Substring(begin, p);
     985                 :                 }
     986                 :             }
     987                 :         }
     988                 :     }
     989                 : 
     990           56424 :     if (! factory) {
     991                 :         // fall through to using the "default" resource factory if either:
     992                 :         //
     993                 :         // 1. The URI didn't have a scheme, or
     994                 :         // 2. There was no resource factory registered for the scheme.
     995           14623 :         factory = mDefaultResourceFactory;
     996                 : 
     997                 :         // Store the factory in our one-element cache.
     998           14623 :         if (p != begin) {
     999           14623 :             mLastFactory = factory;
    1000           14623 :             mLastURIPrefix = Substring(begin, p);
    1001                 :         }
    1002                 :     }
    1003                 : 
    1004                 :     nsIRDFResource *result;
    1005           56424 :     rv = factory->CreateInstance(nsnull, NS_GET_IID(nsIRDFResource), (void**) &result);
    1006           56424 :     if (NS_FAILED(rv)) return rv;
    1007                 : 
    1008                 :     // Now initialize it with its URI. At this point, the resource
    1009                 :     // implementation should register itself with the RDF service.
    1010           56424 :     rv = result->Init(flatURI.get());
    1011           56424 :     if (NS_FAILED(rv)) {
    1012               0 :         NS_ERROR("unable to initialize resource");
    1013               0 :         NS_RELEASE(result);
    1014               0 :         return rv;
    1015                 :     }
    1016                 : 
    1017           56424 :     *aResource = result; // already refcounted from repository
    1018           56424 :     return rv;
    1019                 : }
    1020                 : 
    1021                 : NS_IMETHODIMP
    1022               2 : RDFServiceImpl::GetUnicodeResource(const nsAString& aURI, nsIRDFResource** aResource)
    1023                 : {
    1024               2 :     return GetResource(NS_ConvertUTF16toUTF8(aURI), aResource);
    1025                 : }
    1026                 : 
    1027                 : 
    1028                 : NS_IMETHODIMP
    1029           36222 : RDFServiceImpl::GetAnonymousResource(nsIRDFResource** aResult)
    1030                 : {
    1031                 : static PRUint32 gCounter = 0;
    1032                 : static char gChars[] = "0123456789abcdef"
    1033                 :                        "ghijklmnopqrstuv"
    1034                 :                        "wxyzABCDEFGHIJKL"
    1035                 :                        "MNOPQRSTUVWXYZ.+";
    1036                 : 
    1037                 : static PRInt32 kMask  = 0x003f;
    1038                 : static PRInt32 kShift = 6;
    1039                 : 
    1040           36222 :     if (! gCounter) {
    1041                 :         // Start it at a semi-unique value, just to minimize the
    1042                 :         // chance that we get into a situation where
    1043                 :         //
    1044                 :         // 1. An anonymous resource gets serialized out in a graph
    1045                 :         // 2. Reboot
    1046                 :         // 3. The same anonymous resource gets requested, and refers
    1047                 :         //    to something completely different.
    1048                 :         // 4. The serialization is read back in.
    1049             169 :         LL_L2UI(gCounter, PR_Now());
    1050                 :     }
    1051                 : 
    1052                 :     nsresult rv;
    1053           72444 :     nsCAutoString s;
    1054                 : 
    1055               0 :     do {
    1056                 :         // Ugh, this is a really sloppy way to do this; I copied the
    1057                 :         // implementation from the days when it lived outside the RDF
    1058                 :         // service. Now that it's a member we can be more cleverer.
    1059                 : 
    1060           36222 :         s.Truncate();
    1061           36222 :         s.Append("rdf:#$");
    1062                 : 
    1063           36222 :         PRUint32 id = ++gCounter;
    1064          289776 :         while (id) {
    1065          217332 :             char ch = gChars[(id & kMask)];
    1066          217332 :             s.Append(ch);
    1067          217332 :             id >>= kShift;
    1068                 :         }
    1069                 : 
    1070                 :         nsIRDFResource* resource;
    1071           36222 :         rv = GetResource(s, &resource);
    1072           36222 :         if (NS_FAILED(rv)) return rv;
    1073                 : 
    1074                 :         // XXX an ugly but effective way to make sure that this
    1075                 :         // resource is really unique in the world.
    1076           36222 :         resource->AddRef();
    1077           36222 :         nsrefcnt refcnt = resource->Release();
    1078                 : 
    1079           36222 :         if (refcnt == 1) {
    1080           36222 :             *aResult = resource;
    1081                 :             break;
    1082                 :         }
    1083                 : 
    1084               0 :         NS_RELEASE(resource);
    1085                 :     } while (1);
    1086                 : 
    1087           36222 :     return NS_OK;
    1088                 : }
    1089                 : 
    1090                 : 
    1091                 : NS_IMETHODIMP
    1092           27634 : RDFServiceImpl::GetLiteral(const PRUnichar* aValue, nsIRDFLiteral** aLiteral)
    1093                 : {
    1094           27634 :     NS_PRECONDITION(aValue != nsnull, "null ptr");
    1095           27634 :     if (! aValue)
    1096               0 :         return NS_ERROR_NULL_POINTER;
    1097                 : 
    1098           27634 :     NS_PRECONDITION(aLiteral != nsnull, "null ptr");
    1099           27634 :     if (! aLiteral)
    1100               0 :         return NS_ERROR_NULL_POINTER;
    1101                 : 
    1102                 :     // See if we have one already cached
    1103                 :     PLDHashEntryHdr *hdr =
    1104           27634 :         PL_DHashTableOperate(&mLiterals, aValue, PL_DHASH_LOOKUP);
    1105                 : 
    1106           27634 :     if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
    1107           18290 :         LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
    1108           18290 :         NS_ADDREF(*aLiteral = entry->mLiteral);
    1109           18290 :         return NS_OK;
    1110                 :     }
    1111                 : 
    1112                 :     // Nope. Create a new one
    1113            9344 :     return LiteralImpl::Create(aValue, aLiteral);
    1114                 : }
    1115                 : 
    1116                 : NS_IMETHODIMP
    1117               0 : RDFServiceImpl::GetDateLiteral(PRTime aTime, nsIRDFDate** aResult)
    1118                 : {
    1119                 :     // See if we have one already cached
    1120                 :     PLDHashEntryHdr *hdr =
    1121               0 :         PL_DHashTableOperate(&mDates, &aTime, PL_DHASH_LOOKUP);
    1122                 : 
    1123               0 :     if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
    1124               0 :         DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
    1125               0 :         NS_ADDREF(*aResult = entry->mDate);
    1126               0 :         return NS_OK;
    1127                 :     }
    1128                 : 
    1129               0 :     DateImpl* result = new DateImpl(aTime);
    1130               0 :     if (! result)
    1131               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1132                 : 
    1133               0 :     NS_ADDREF(*aResult = result);
    1134               0 :     return NS_OK;
    1135                 : }
    1136                 : 
    1137                 : NS_IMETHODIMP
    1138              32 : RDFServiceImpl::GetIntLiteral(PRInt32 aInt, nsIRDFInt** aResult)
    1139                 : {
    1140                 :     // See if we have one already cached
    1141                 :     PLDHashEntryHdr *hdr =
    1142              32 :         PL_DHashTableOperate(&mInts, &aInt, PL_DHASH_LOOKUP);
    1143                 : 
    1144              32 :     if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
    1145              24 :         IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
    1146              24 :         NS_ADDREF(*aResult = entry->mInt);
    1147              24 :         return NS_OK;
    1148                 :     }
    1149                 : 
    1150               8 :     IntImpl* result = new IntImpl(aInt);
    1151               8 :     if (! result)
    1152               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1153                 : 
    1154               8 :     NS_ADDREF(*aResult = result);
    1155               8 :     return NS_OK;
    1156                 : }
    1157                 : 
    1158                 : NS_IMETHODIMP
    1159               0 : RDFServiceImpl::GetBlobLiteral(const PRUint8 *aBytes, PRInt32 aLength,
    1160                 :                                nsIRDFBlob **aResult)
    1161                 : {
    1162               0 :     BlobImpl::Data key = { aLength, const_cast<PRUint8 *>(aBytes) };
    1163                 : 
    1164                 :     PLDHashEntryHdr *hdr =
    1165               0 :         PL_DHashTableOperate(&mBlobs, &key, PL_DHASH_LOOKUP);
    1166                 : 
    1167               0 :     if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
    1168               0 :         BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
    1169               0 :         NS_ADDREF(*aResult = entry->mBlob);
    1170               0 :         return NS_OK;
    1171                 :     }
    1172                 : 
    1173               0 :     BlobImpl *result = new BlobImpl(aBytes, aLength);
    1174               0 :     if (! result)
    1175               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1176                 : 
    1177               0 :     NS_ADDREF(*aResult = result);
    1178               0 :     return NS_OK;
    1179                 : }
    1180                 : 
    1181                 : NS_IMETHODIMP
    1182              56 : RDFServiceImpl::IsAnonymousResource(nsIRDFResource* aResource, bool* _result)
    1183                 : {
    1184              56 :     NS_PRECONDITION(aResource != nsnull, "null ptr");
    1185              56 :     if (! aResource)
    1186               0 :         return NS_ERROR_NULL_POINTER;
    1187                 : 
    1188                 :     nsresult rv;
    1189                 : 
    1190                 :     const char* uri;
    1191              56 :     rv = aResource->GetValueConst(&uri);
    1192              56 :     if (NS_FAILED(rv)) return rv;
    1193                 : 
    1194             266 :     if ((uri[0] == 'r') &&
    1195              42 :         (uri[1] == 'd') &&
    1196              42 :         (uri[2] == 'f') &&
    1197              42 :         (uri[3] == ':') &&
    1198              42 :         (uri[4] == '#') &&
    1199              42 :         (uri[5] == '$')) {
    1200              42 :         *_result = true;
    1201                 :     }
    1202                 :     else {
    1203              14 :         *_result = false;
    1204                 :     }
    1205                 : 
    1206              56 :     return NS_OK;
    1207                 : }
    1208                 : 
    1209                 : NS_IMETHODIMP
    1210           56424 : RDFServiceImpl::RegisterResource(nsIRDFResource* aResource, bool aReplace)
    1211                 : {
    1212           56424 :     NS_PRECONDITION(aResource != nsnull, "null ptr");
    1213           56424 :     if (! aResource)
    1214               0 :         return NS_ERROR_NULL_POINTER;
    1215                 : 
    1216                 :     nsresult rv;
    1217                 : 
    1218                 :     const char* uri;
    1219           56424 :     rv = aResource->GetValueConst(&uri);
    1220           56424 :     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get URI from resource");
    1221           56424 :     if (NS_FAILED(rv)) return rv;
    1222                 : 
    1223           56424 :     NS_ASSERTION(uri != nsnull, "resource has no URI");
    1224           56424 :     if (! uri)
    1225               0 :         return NS_ERROR_NULL_POINTER;
    1226                 : 
    1227                 :     PLDHashEntryHdr *hdr =
    1228           56424 :         PL_DHashTableOperate(&mResources, uri, PL_DHASH_LOOKUP);
    1229                 : 
    1230           56424 :     if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
    1231               0 :         if (!aReplace) {
    1232               0 :             NS_WARNING("resource already registered, and replace not specified");
    1233               0 :             return NS_ERROR_FAILURE;    // already registered
    1234                 :         }
    1235                 : 
    1236                 :         // N.B., we do _not_ release the original resource because we
    1237                 :         // only ever held a weak reference to it. We simply replace
    1238                 :         // it.
    1239                 : 
    1240               0 :         PR_LOG(gLog, PR_LOG_DEBUG,
    1241                 :                ("rdfserv   replace-resource [%p] <-- [%p] %s",
    1242                 :                 static_cast<ResourceHashEntry *>(hdr)->mResource,
    1243                 :                 aResource, (const char*) uri));
    1244                 :     }
    1245                 :     else {
    1246           56424 :         hdr = PL_DHashTableOperate(&mResources, uri, PL_DHASH_ADD);
    1247           56424 :         if (! hdr)
    1248               0 :             return NS_ERROR_OUT_OF_MEMORY;
    1249                 : 
    1250           56424 :         PR_LOG(gLog, PR_LOG_DEBUG,
    1251                 :                ("rdfserv   register-resource [%p] %s",
    1252                 :                 aResource, (const char*) uri));
    1253                 :     }
    1254                 : 
    1255                 :     // N.B., we only hold a weak reference to the resource: that way,
    1256                 :     // the resource can be destroyed when the last refcount goes
    1257                 :     // away. The single addref that the CreateResource() call made
    1258                 :     // will be owned by the callee.
    1259           56424 :     ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
    1260           56424 :     entry->mResource = aResource;
    1261           56424 :     entry->mKey = uri;
    1262                 : 
    1263           56424 :     return NS_OK;
    1264                 : }
    1265                 : 
    1266                 : NS_IMETHODIMP
    1267           56421 : RDFServiceImpl::UnregisterResource(nsIRDFResource* aResource)
    1268                 : {
    1269           56421 :     NS_PRECONDITION(aResource != nsnull, "null ptr");
    1270           56421 :     if (! aResource)
    1271               0 :         return NS_ERROR_NULL_POINTER;
    1272                 : 
    1273                 :     nsresult rv;
    1274                 : 
    1275                 :     const char* uri;
    1276           56421 :     rv = aResource->GetValueConst(&uri);
    1277           56421 :     if (NS_FAILED(rv)) return rv;
    1278                 : 
    1279           56421 :     NS_ASSERTION(uri != nsnull, "resource has no URI");
    1280           56421 :     if (! uri)
    1281               0 :         return NS_ERROR_UNEXPECTED;
    1282                 : 
    1283           56421 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1284                 :            ("rdfserv unregister-resource [%p] %s",
    1285                 :             aResource, (const char*) uri));
    1286                 : 
    1287                 : #ifdef DEBUG
    1288           56421 :     if (PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mResources, uri, PL_DHASH_LOOKUP)))
    1289               0 :         NS_WARNING("resource was never registered");
    1290                 : #endif
    1291                 : 
    1292           56421 :     PL_DHashTableOperate(&mResources, uri, PL_DHASH_REMOVE);
    1293           56421 :     return NS_OK;
    1294                 : }
    1295                 : 
    1296                 : NS_IMETHODIMP
    1297              10 : RDFServiceImpl::RegisterDataSource(nsIRDFDataSource* aDataSource, bool aReplace)
    1298                 : {
    1299              10 :     NS_PRECONDITION(aDataSource != nsnull, "null ptr");
    1300              10 :     if (! aDataSource)
    1301               0 :         return NS_ERROR_NULL_POINTER;
    1302                 : 
    1303                 :     nsresult rv;
    1304                 : 
    1305              20 :     nsXPIDLCString uri;
    1306              10 :     rv = aDataSource->GetURI(getter_Copies(uri));
    1307              10 :     if (NS_FAILED(rv)) return rv;
    1308                 : 
    1309                 :     PLHashEntry** hep =
    1310              10 :         PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
    1311                 : 
    1312              10 :     if (*hep) {
    1313               0 :         if (! aReplace)
    1314               0 :             return NS_ERROR_FAILURE; // already registered
    1315                 : 
    1316                 :         // N.B., we only hold a weak reference to the datasource, so
    1317                 :         // just replace the old with the new and don't touch any
    1318                 :         // refcounts.
    1319               0 :         PR_LOG(gLog, PR_LOG_NOTICE,
    1320                 :                ("rdfserv    replace-datasource [%p] <-- [%p] %s",
    1321                 :                 (*hep)->value, aDataSource, (const char*) uri));
    1322                 : 
    1323               0 :         (*hep)->value = aDataSource;
    1324                 :     }
    1325                 :     else {
    1326              10 :         const char* key = PL_strdup(uri);
    1327              10 :         if (! key)
    1328               0 :             return NS_ERROR_OUT_OF_MEMORY;
    1329                 : 
    1330              10 :         PL_HashTableAdd(mNamedDataSources, key, aDataSource);
    1331                 : 
    1332              10 :         PR_LOG(gLog, PR_LOG_NOTICE,
    1333                 :                ("rdfserv   register-datasource [%p] %s",
    1334                 :                 aDataSource, (const char*) uri));
    1335                 : 
    1336                 :         // N.B., we only hold a weak reference to the datasource, so don't
    1337                 :         // addref.
    1338                 :     }
    1339                 : 
    1340              10 :     return NS_OK;
    1341                 : }
    1342                 : 
    1343                 : NS_IMETHODIMP
    1344              10 : RDFServiceImpl::UnregisterDataSource(nsIRDFDataSource* aDataSource)
    1345                 : {
    1346              10 :     NS_PRECONDITION(aDataSource != nsnull, "null ptr");
    1347              10 :     if (! aDataSource)
    1348               0 :         return NS_ERROR_NULL_POINTER;
    1349                 : 
    1350                 :     nsresult rv;
    1351                 : 
    1352              20 :     nsXPIDLCString uri;
    1353              10 :     rv = aDataSource->GetURI(getter_Copies(uri));
    1354              10 :     if (NS_FAILED(rv)) return rv;
    1355                 : 
    1356                 :     //NS_ASSERTION(uri != nsnull, "datasource has no URI");
    1357              10 :     if (! uri)
    1358               0 :         return NS_ERROR_UNEXPECTED;
    1359                 : 
    1360                 :     PLHashEntry** hep =
    1361              10 :         PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
    1362                 : 
    1363                 :     // It may well be that this datasource was never registered. If
    1364                 :     // so, don't unregister it.
    1365              10 :     if (! *hep || ((*hep)->value != aDataSource))
    1366               0 :         return NS_OK;
    1367                 : 
    1368                 :     // N.B., we only held a weak reference to the datasource, so we
    1369                 :     // don't release here.
    1370              10 :     PL_HashTableRawRemove(mNamedDataSources, hep, *hep);
    1371                 : 
    1372              10 :     PR_LOG(gLog, PR_LOG_NOTICE,
    1373                 :            ("rdfserv unregister-datasource [%p] %s",
    1374                 :             aDataSource, (const char*) uri));
    1375                 : 
    1376              10 :     return NS_OK;
    1377                 : }
    1378                 : 
    1379                 : NS_IMETHODIMP
    1380               4 : RDFServiceImpl::GetDataSource(const char* aURI, nsIRDFDataSource** aDataSource)
    1381                 : {
    1382                 :     // Use the other GetDataSource and ask for a non-blocking Refresh.
    1383                 :     // If you wanted it loaded synchronously, then you should've tried to do it
    1384                 :     // yourself, or used GetDataSourceBlocking.
    1385               4 :     return GetDataSource( aURI, false, aDataSource );
    1386                 : }
    1387                 : 
    1388                 : NS_IMETHODIMP
    1389               7 : RDFServiceImpl::GetDataSourceBlocking(const char* aURI, nsIRDFDataSource** aDataSource)
    1390                 : {
    1391                 :     // Use GetDataSource and ask for a blocking Refresh.
    1392               7 :     return GetDataSource( aURI, true, aDataSource );
    1393                 : }
    1394                 : 
    1395                 : nsresult
    1396              11 : RDFServiceImpl::GetDataSource(const char* aURI, bool aBlock, nsIRDFDataSource** aDataSource)
    1397                 : {
    1398              11 :     NS_PRECONDITION(aURI != nsnull, "null ptr");
    1399              11 :     if (! aURI)
    1400               0 :         return NS_ERROR_NULL_POINTER;
    1401                 : 
    1402                 :     nsresult rv;
    1403                 : 
    1404                 :     // Attempt to canonify the URI before we look for it in the
    1405                 :     // cache. We won't bother doing this on `rdf:' URIs to avoid
    1406                 :     // useless (and expensive) protocol handler lookups.
    1407              22 :     nsCAutoString spec(aURI);
    1408                 : 
    1409              11 :     if (!StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
    1410              22 :         nsCOMPtr<nsIURI> uri;
    1411              11 :         NS_NewURI(getter_AddRefs(uri), spec);
    1412              11 :         if (uri)
    1413              11 :             uri->GetSpec(spec);
    1414                 :     }
    1415                 : 
    1416                 :     // First, check the cache to see if we already have this
    1417                 :     // datasource loaded and initialized.
    1418                 :     {
    1419                 :         nsIRDFDataSource* cached =
    1420              11 :             static_cast<nsIRDFDataSource*>(PL_HashTableLookup(mNamedDataSources, spec.get()));
    1421                 : 
    1422              11 :         if (cached) {
    1423               1 :             NS_ADDREF(cached);
    1424               1 :             *aDataSource = cached;
    1425               1 :             return NS_OK;
    1426                 :         }
    1427                 :     }
    1428                 : 
    1429                 :     // Nope. So go to the repository to try to create it.
    1430              20 :     nsCOMPtr<nsIRDFDataSource> ds;
    1431              10 :     if (StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
    1432                 :         // It's a built-in data source. Convert it to a contract ID.
    1433                 :         nsCAutoString contractID(
    1434               0 :                 NS_LITERAL_CSTRING(NS_RDF_DATASOURCE_CONTRACTID_PREFIX) +
    1435               0 :                 Substring(spec, 4, spec.Length() - 4));
    1436                 : 
    1437                 :         // Strip params to get ``base'' contractID for data source.
    1438               0 :         PRInt32 p = contractID.FindChar(PRUnichar('&'));
    1439               0 :         if (p >= 0)
    1440               0 :             contractID.Truncate(p);
    1441                 : 
    1442               0 :         ds = do_GetService(contractID.get(), &rv);
    1443               0 :         if (NS_FAILED(rv)) return rv;
    1444                 : 
    1445               0 :         nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(ds);
    1446               0 :         if (remote) {
    1447               0 :             rv = remote->Init(spec.get());
    1448               0 :             if (NS_FAILED(rv)) return rv;
    1449                 :         }
    1450                 :     }
    1451                 :     else {
    1452                 :         // Try to load this as an RDF/XML data source
    1453              10 :         ds = do_CreateInstance(kRDFXMLDataSourceCID, &rv);
    1454              10 :         if (NS_FAILED(rv)) return rv;
    1455                 : 
    1456              20 :         nsCOMPtr<nsIRDFRemoteDataSource> remote(do_QueryInterface(ds));
    1457              10 :         NS_ASSERTION(remote, "not a remote RDF/XML data source!");
    1458              10 :         if (! remote) return NS_ERROR_UNEXPECTED;
    1459                 : 
    1460              10 :         rv = remote->Init(spec.get());
    1461              10 :         if (NS_FAILED(rv)) return rv;
    1462                 : 
    1463              10 :         rv = remote->Refresh(aBlock);
    1464              10 :         if (NS_FAILED(rv)) return rv;
    1465                 :     }
    1466                 : 
    1467              10 :     *aDataSource = ds;
    1468              10 :     NS_ADDREF(*aDataSource);
    1469              10 :     return NS_OK;
    1470                 : }
    1471                 : 
    1472                 : ////////////////////////////////////////////////////////////////////////
    1473                 : 
    1474                 : nsresult
    1475            9344 : RDFServiceImpl::RegisterLiteral(nsIRDFLiteral* aLiteral)
    1476                 : {
    1477                 :     const PRUnichar* value;
    1478            9344 :     aLiteral->GetValueConst(&value);
    1479                 : 
    1480            9344 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mLiterals,
    1481                 :                                                              value,
    1482                 :                                                              PL_DHASH_LOOKUP)),
    1483                 :                  "literal already registered");
    1484                 : 
    1485                 :     PLDHashEntryHdr *hdr =
    1486            9344 :         PL_DHashTableOperate(&mLiterals, value, PL_DHASH_ADD);
    1487                 : 
    1488            9344 :     if (! hdr)
    1489               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1490                 : 
    1491            9344 :     LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
    1492                 : 
    1493                 :     // N.B., we only hold a weak reference to the literal: that
    1494                 :     // way, the literal can be destroyed when the last refcount
    1495                 :     // goes away. The single addref that the CreateLiteral() call
    1496                 :     // made will be owned by the callee.
    1497            9344 :     entry->mLiteral = aLiteral;
    1498            9344 :     entry->mKey = value;
    1499                 : 
    1500            9344 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1501                 :            ("rdfserv   register-literal [%p] %s",
    1502                 :             aLiteral, (const PRUnichar*) value));
    1503                 : 
    1504            9344 :     return NS_OK;
    1505                 : }
    1506                 : 
    1507                 : 
    1508                 : nsresult
    1509            9343 : RDFServiceImpl::UnregisterLiteral(nsIRDFLiteral* aLiteral)
    1510                 : {
    1511                 :     const PRUnichar* value;
    1512            9343 :     aLiteral->GetValueConst(&value);
    1513                 : 
    1514            9343 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mLiterals,
    1515                 :                                                              value,
    1516                 :                                                              PL_DHASH_LOOKUP)),
    1517                 :                  "literal was never registered");
    1518                 : 
    1519            9343 :     PL_DHashTableOperate(&mLiterals, value, PL_DHASH_REMOVE);
    1520                 : 
    1521                 :     // N.B. that we _don't_ release the literal: we only held a weak
    1522                 :     // reference to it in the hashtable.
    1523            9343 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1524                 :            ("rdfserv unregister-literal [%p] %s",
    1525                 :             aLiteral, (const PRUnichar*) value));
    1526                 : 
    1527            9343 :     return NS_OK;
    1528                 : }
    1529                 : 
    1530                 : //----------------------------------------------------------------------
    1531                 : 
    1532                 : nsresult
    1533               8 : RDFServiceImpl::RegisterInt(nsIRDFInt* aInt)
    1534                 : {
    1535                 :     PRInt32 value;
    1536               8 :     aInt->GetValue(&value);
    1537                 : 
    1538               8 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mInts,
    1539                 :                                                              &value,
    1540                 :                                                              PL_DHASH_LOOKUP)),
    1541                 :                  "int already registered");
    1542                 : 
    1543                 :     PLDHashEntryHdr *hdr =
    1544               8 :         PL_DHashTableOperate(&mInts, &value, PL_DHASH_ADD);
    1545                 : 
    1546               8 :     if (! hdr)
    1547               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1548                 : 
    1549               8 :     IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
    1550                 : 
    1551                 :     // N.B., we only hold a weak reference to the literal: that
    1552                 :     // way, the literal can be destroyed when the last refcount
    1553                 :     // goes away. The single addref that the CreateInt() call
    1554                 :     // made will be owned by the callee.
    1555               8 :     entry->mInt = aInt;
    1556               8 :     entry->mKey = value;
    1557                 : 
    1558               8 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1559                 :            ("rdfserv   register-int [%p] %d",
    1560                 :             aInt, value));
    1561                 : 
    1562               8 :     return NS_OK;
    1563                 : }
    1564                 : 
    1565                 : 
    1566                 : nsresult
    1567               8 : RDFServiceImpl::UnregisterInt(nsIRDFInt* aInt)
    1568                 : {
    1569                 :     PRInt32 value;
    1570               8 :     aInt->GetValue(&value);
    1571                 : 
    1572               8 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mInts,
    1573                 :                                                              &value,
    1574                 :                                                              PL_DHASH_LOOKUP)),
    1575                 :                  "int was never registered");
    1576                 : 
    1577               8 :     PL_DHashTableOperate(&mInts, &value, PL_DHASH_REMOVE);
    1578                 : 
    1579                 :     // N.B. that we _don't_ release the literal: we only held a weak
    1580                 :     // reference to it in the hashtable.
    1581               8 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1582                 :            ("rdfserv unregister-int [%p] %d",
    1583                 :             aInt, value));
    1584                 : 
    1585               8 :     return NS_OK;
    1586                 : }
    1587                 : 
    1588                 : //----------------------------------------------------------------------
    1589                 : 
    1590                 : nsresult
    1591               0 : RDFServiceImpl::RegisterDate(nsIRDFDate* aDate)
    1592                 : {
    1593                 :     PRTime value;
    1594               0 :     aDate->GetValue(&value);
    1595                 : 
    1596               0 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mDates,
    1597                 :                                                              &value,
    1598                 :                                                              PL_DHASH_LOOKUP)),
    1599                 :                  "date already registered");
    1600                 : 
    1601                 :     PLDHashEntryHdr *hdr =
    1602               0 :         PL_DHashTableOperate(&mDates, &value, PL_DHASH_ADD);
    1603                 : 
    1604               0 :     if (! hdr)
    1605               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1606                 : 
    1607               0 :     DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
    1608                 : 
    1609                 :     // N.B., we only hold a weak reference to the literal: that
    1610                 :     // way, the literal can be destroyed when the last refcount
    1611                 :     // goes away. The single addref that the CreateDate() call
    1612                 :     // made will be owned by the callee.
    1613               0 :     entry->mDate = aDate;
    1614               0 :     entry->mKey = value;
    1615                 : 
    1616               0 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1617                 :            ("rdfserv   register-date [%p] %ld",
    1618                 :             aDate, value));
    1619                 : 
    1620               0 :     return NS_OK;
    1621                 : }
    1622                 : 
    1623                 : 
    1624                 : nsresult
    1625               0 : RDFServiceImpl::UnregisterDate(nsIRDFDate* aDate)
    1626                 : {
    1627                 :     PRTime value;
    1628               0 :     aDate->GetValue(&value);
    1629                 : 
    1630               0 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mDates,
    1631                 :                                                              &value,
    1632                 :                                                              PL_DHASH_LOOKUP)),
    1633                 :                  "date was never registered");
    1634                 : 
    1635               0 :     PL_DHashTableOperate(&mDates, &value, PL_DHASH_REMOVE);
    1636                 : 
    1637                 :     // N.B. that we _don't_ release the literal: we only held a weak
    1638                 :     // reference to it in the hashtable.
    1639               0 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1640                 :            ("rdfserv unregister-date [%p] %ld",
    1641                 :             aDate, value));
    1642                 : 
    1643               0 :     return NS_OK;
    1644                 : }
    1645                 : 
    1646                 : nsresult
    1647               0 : RDFServiceImpl::RegisterBlob(BlobImpl *aBlob)
    1648                 : {
    1649               0 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mBlobs,
    1650                 :                                                              &aBlob->mData,
    1651                 :                                                              PL_DHASH_LOOKUP)),
    1652                 :                  "blob already registered");
    1653                 : 
    1654                 :     PLDHashEntryHdr *hdr = 
    1655               0 :         PL_DHashTableOperate(&mBlobs, &aBlob->mData, PL_DHASH_ADD);
    1656                 : 
    1657               0 :     if (! hdr)
    1658               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1659                 : 
    1660               0 :     BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
    1661                 : 
    1662                 :     // N.B., we only hold a weak reference to the literal: that
    1663                 :     // way, the literal can be destroyed when the last refcount
    1664                 :     // goes away. The single addref that the CreateInt() call
    1665                 :     // made will be owned by the callee.
    1666               0 :     entry->mBlob = aBlob;
    1667                 : 
    1668               0 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1669                 :            ("rdfserv   register-blob [%p] %s",
    1670                 :             aBlob, aBlob->mData.mBytes));
    1671                 : 
    1672               0 :     return NS_OK;
    1673                 : }
    1674                 : 
    1675                 : nsresult
    1676               0 : RDFServiceImpl::UnregisterBlob(BlobImpl *aBlob)
    1677                 : {
    1678               0 :     NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mBlobs,
    1679                 :                                                              &aBlob->mData,
    1680                 :                                                              PL_DHASH_LOOKUP)),
    1681                 :                  "blob was never registered");
    1682                 : 
    1683               0 :     PL_DHashTableOperate(&mBlobs, &aBlob->mData, PL_DHASH_REMOVE);
    1684                 :  
    1685                 :      // N.B. that we _don't_ release the literal: we only held a weak
    1686                 :      // reference to it in the hashtable.
    1687               0 :     PR_LOG(gLog, PR_LOG_DEBUG,
    1688                 :            ("rdfserv unregister-blob [%p] %s",
    1689                 :             aBlob, aBlob->mData.mBytes));
    1690                 : 
    1691               0 :     return NS_OK;
    1692                 : }

Generated by: LCOV version 1.7