nsInMemoryDataSource.cpp 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. *
  3. * This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. *
  7. *
  8. * This Original Code has been modified by IBM Corporation.
  9. * Modifications made by IBM described herein are
  10. * Copyright (c) International Business Machines
  11. * Corporation, 2000
  12. *
  13. * Modifications to Mozilla code or documentation
  14. * identified per MPL Section 3.3
  15. *
  16. * Date Modified by Description of modification
  17. * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
  18. * use in OS2
  19. */
  20. /*
  21. Implementation for an in-memory RDF data store.
  22. TO DO
  23. 1) Instrument this code to gather space and time performance
  24. characteristics.
  25. 2) Optimize lookups for datasources which have a small number
  26. of properties + fanning out to a large number of targets.
  27. 3) Complete implementation of thread-safety; specifically, make
  28. assertions be reference counted objects (so that a cursor can
  29. still refer to an assertion that gets removed from the graph).
  30. */
  31. #include "nsAgg.h"
  32. #include "nsCOMPtr.h"
  33. #include "nscore.h"
  34. #include "nsArrayEnumerator.h"
  35. #include "nsIOutputStream.h"
  36. #include "nsIRDFDataSource.h"
  37. #include "nsIRDFLiteral.h"
  38. #include "nsIRDFNode.h"
  39. #include "nsIRDFObserver.h"
  40. #include "nsIRDFInMemoryDataSource.h"
  41. #include "nsIRDFPropagatableDataSource.h"
  42. #include "nsIRDFPurgeableDataSource.h"
  43. #include "nsIRDFService.h"
  44. #include "nsIServiceManager.h"
  45. #include "nsCOMArray.h"
  46. #include "nsEnumeratorUtils.h"
  47. #include "nsTArray.h"
  48. #include "nsCRT.h"
  49. #include "nsRDFCID.h"
  50. #include "nsRDFBaseDataSources.h"
  51. #include "nsString.h"
  52. #include "nsReadableUtils.h"
  53. #include "nsXPIDLString.h"
  54. #include "rdfutil.h"
  55. #include "PLDHashTable.h"
  56. #include "plstr.h"
  57. #include "mozilla/Logging.h"
  58. #include "rdf.h"
  59. #include "rdfIDataSource.h"
  60. #include "rdfITripleVisitor.h"
  61. using mozilla::LogLevel;
  62. // This struct is used as the slot value in the forward and reverse
  63. // arcs hash tables.
  64. //
  65. // Assertion objects are reference counted, because each Assertion's
  66. // ownership is shared between the datasource and any enumerators that
  67. // are currently iterating over the datasource.
  68. //
  69. class Assertion
  70. {
  71. public:
  72. Assertion(nsIRDFResource* aSource, // normal assertion
  73. nsIRDFResource* aProperty,
  74. nsIRDFNode* aTarget,
  75. bool aTruthValue);
  76. explicit Assertion(nsIRDFResource* aSource); // PLDHashTable assertion variant
  77. private:
  78. ~Assertion();
  79. public:
  80. void AddRef() {
  81. if (mRefCnt == UINT16_MAX) {
  82. NS_WARNING("refcount overflow, leaking Assertion");
  83. return;
  84. }
  85. ++mRefCnt;
  86. }
  87. void Release() {
  88. if (mRefCnt == UINT16_MAX) {
  89. NS_WARNING("refcount overflow, leaking Assertion");
  90. return;
  91. }
  92. if (--mRefCnt == 0)
  93. delete this;
  94. }
  95. // For nsIRDFPurgeableDataSource
  96. inline void Mark() { u.as.mMarked = true; }
  97. inline bool IsMarked() { return u.as.mMarked; }
  98. inline void Unmark() { u.as.mMarked = false; }
  99. // public for now, because I'm too lazy to go thru and clean this up.
  100. // These are shared between hash/as (see the union below)
  101. nsIRDFResource* mSource;
  102. Assertion* mNext;
  103. union
  104. {
  105. struct hash
  106. {
  107. PLDHashTable* mPropertyHash;
  108. } hash;
  109. struct as
  110. {
  111. nsIRDFResource* mProperty;
  112. nsIRDFNode* mTarget;
  113. Assertion* mInvNext;
  114. // make sure bool are final elements
  115. bool mTruthValue;
  116. bool mMarked;
  117. } as;
  118. } u;
  119. // also shared between hash/as (see the union above)
  120. // but placed after union definition to ensure that
  121. // all 32-bit entries are long aligned
  122. uint16_t mRefCnt;
  123. bool mHashEntry;
  124. };
  125. struct Entry : PLDHashEntryHdr {
  126. nsIRDFNode* mNode;
  127. Assertion* mAssertions;
  128. };
  129. Assertion::Assertion(nsIRDFResource* aSource)
  130. : mSource(aSource),
  131. mNext(nullptr),
  132. mRefCnt(0),
  133. mHashEntry(true)
  134. {
  135. MOZ_COUNT_CTOR(Assertion);
  136. NS_ADDREF(mSource);
  137. u.hash.mPropertyHash =
  138. new PLDHashTable(PLDHashTable::StubOps(), sizeof(Entry));
  139. }
  140. Assertion::Assertion(nsIRDFResource* aSource,
  141. nsIRDFResource* aProperty,
  142. nsIRDFNode* aTarget,
  143. bool aTruthValue)
  144. : mSource(aSource),
  145. mNext(nullptr),
  146. mRefCnt(0),
  147. mHashEntry(false)
  148. {
  149. MOZ_COUNT_CTOR(Assertion);
  150. u.as.mProperty = aProperty;
  151. u.as.mTarget = aTarget;
  152. NS_ADDREF(mSource);
  153. NS_ADDREF(u.as.mProperty);
  154. NS_ADDREF(u.as.mTarget);
  155. u.as.mInvNext = nullptr;
  156. u.as.mTruthValue = aTruthValue;
  157. u.as.mMarked = false;
  158. }
  159. Assertion::~Assertion()
  160. {
  161. if (mHashEntry && u.hash.mPropertyHash) {
  162. for (auto i = u.hash.mPropertyHash->Iter(); !i.Done(); i.Next()) {
  163. auto entry = static_cast<Entry*>(i.Get());
  164. Assertion* as = entry->mAssertions;
  165. while (as) {
  166. Assertion* doomed = as;
  167. as = as->mNext;
  168. // Unlink, and release the datasource's reference.
  169. doomed->mNext = doomed->u.as.mInvNext = nullptr;
  170. doomed->Release();
  171. }
  172. }
  173. delete u.hash.mPropertyHash;
  174. u.hash.mPropertyHash = nullptr;
  175. }
  176. MOZ_COUNT_DTOR(Assertion);
  177. #ifdef DEBUG_REFS
  178. --gInstanceCount;
  179. fprintf(stdout, "%d - RDF: Assertion\n", gInstanceCount);
  180. #endif
  181. NS_RELEASE(mSource);
  182. if (!mHashEntry)
  183. {
  184. NS_RELEASE(u.as.mProperty);
  185. NS_RELEASE(u.as.mTarget);
  186. }
  187. }
  188. ////////////////////////////////////////////////////////////////////////
  189. // InMemoryDataSource
  190. class InMemoryArcsEnumeratorImpl;
  191. class InMemoryAssertionEnumeratorImpl;
  192. class InMemoryResourceEnumeratorImpl;
  193. class InMemoryDataSource : public nsIRDFDataSource,
  194. public nsIRDFInMemoryDataSource,
  195. public nsIRDFPropagatableDataSource,
  196. public nsIRDFPurgeableDataSource,
  197. public rdfIDataSource
  198. {
  199. protected:
  200. // These hash tables are keyed on pointers to nsIRDFResource
  201. // objects (the nsIRDFService ensures that there is only ever one
  202. // nsIRDFResource object per unique URI). The value of an entry is
  203. // an Assertion struct, which is a linked list of (subject
  204. // predicate object) triples.
  205. PLDHashTable mForwardArcs;
  206. PLDHashTable mReverseArcs;
  207. nsCOMArray<nsIRDFObserver> mObservers;
  208. uint32_t mNumObservers;
  209. // VisitFoo needs to block writes, [Un]Assert only allowed
  210. // during mReadCount == 0
  211. uint32_t mReadCount;
  212. friend class InMemoryArcsEnumeratorImpl;
  213. friend class InMemoryAssertionEnumeratorImpl;
  214. friend class InMemoryResourceEnumeratorImpl; // b/c it needs to enumerate mForwardArcs
  215. // Thread-safe writer implementation methods.
  216. nsresult
  217. LockedAssert(nsIRDFResource* source,
  218. nsIRDFResource* property,
  219. nsIRDFNode* target,
  220. bool tv);
  221. nsresult
  222. LockedUnassert(nsIRDFResource* source,
  223. nsIRDFResource* property,
  224. nsIRDFNode* target);
  225. explicit InMemoryDataSource(nsISupports* aOuter);
  226. virtual ~InMemoryDataSource();
  227. friend nsresult
  228. NS_NewRDFInMemoryDataSource(nsISupports* aOuter, const nsIID& aIID, void** aResult);
  229. public:
  230. NS_DECL_CYCLE_COLLECTING_AGGREGATED
  231. NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(InMemoryDataSource)
  232. // nsIRDFDataSource methods
  233. NS_DECL_NSIRDFDATASOURCE
  234. // nsIRDFInMemoryDataSource methods
  235. NS_DECL_NSIRDFINMEMORYDATASOURCE
  236. // nsIRDFPropagatableDataSource methods
  237. NS_DECL_NSIRDFPROPAGATABLEDATASOURCE
  238. // nsIRDFPurgeableDataSource methods
  239. NS_DECL_NSIRDFPURGEABLEDATASOURCE
  240. // rdfIDataSource methods
  241. NS_DECL_RDFIDATASOURCE
  242. protected:
  243. struct SweepInfo {
  244. Assertion* mUnassertList;
  245. PLDHashTable* mReverseArcs;
  246. };
  247. static void
  248. SweepForwardArcsEntries(PLDHashTable* aTable, SweepInfo* aArg);
  249. public:
  250. // Implementation methods
  251. Assertion*
  252. GetForwardArcs(nsIRDFResource* u) {
  253. PLDHashEntryHdr* hdr = mForwardArcs.Search(u);
  254. return hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  255. }
  256. Assertion*
  257. GetReverseArcs(nsIRDFNode* v) {
  258. PLDHashEntryHdr* hdr = mReverseArcs.Search(v);
  259. return hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  260. }
  261. void
  262. SetForwardArcs(nsIRDFResource* u, Assertion* as) {
  263. if (as) {
  264. auto entry =
  265. static_cast<Entry*>(mForwardArcs.Add(u, mozilla::fallible));
  266. if (entry) {
  267. entry->mNode = u;
  268. entry->mAssertions = as;
  269. }
  270. }
  271. else {
  272. mForwardArcs.Remove(u);
  273. }
  274. }
  275. void
  276. SetReverseArcs(nsIRDFNode* v, Assertion* as) {
  277. if (as) {
  278. auto entry =
  279. static_cast<Entry*>(mReverseArcs.Add(v, mozilla::fallible));
  280. if (entry) {
  281. entry->mNode = v;
  282. entry->mAssertions = as;
  283. }
  284. }
  285. else {
  286. mReverseArcs.Remove(v);
  287. }
  288. }
  289. void
  290. LogOperation(const char* aOperation,
  291. nsIRDFResource* asource,
  292. nsIRDFResource* aProperty,
  293. nsIRDFNode* aTarget,
  294. bool aTruthValue = true);
  295. bool mPropagateChanges;
  296. private:
  297. static mozilla::LazyLogModule gLog;
  298. };
  299. mozilla::LazyLogModule InMemoryDataSource::gLog("InMemoryDataSource");
  300. //----------------------------------------------------------------------
  301. //
  302. // InMemoryAssertionEnumeratorImpl
  303. //
  304. /**
  305. * InMemoryAssertionEnumeratorImpl
  306. */
  307. class InMemoryAssertionEnumeratorImpl : public nsISimpleEnumerator
  308. {
  309. private:
  310. InMemoryDataSource* mDataSource;
  311. nsIRDFResource* mSource;
  312. nsIRDFResource* mProperty;
  313. nsIRDFNode* mTarget;
  314. nsIRDFNode* mValue;
  315. bool mTruthValue;
  316. Assertion* mNextAssertion;
  317. virtual ~InMemoryAssertionEnumeratorImpl();
  318. public:
  319. InMemoryAssertionEnumeratorImpl(InMemoryDataSource* aDataSource,
  320. nsIRDFResource* aSource,
  321. nsIRDFResource* aProperty,
  322. nsIRDFNode* aTarget,
  323. bool aTruthValue);
  324. // nsISupports interface
  325. NS_DECL_ISUPPORTS
  326. // nsISimpleEnumerator interface
  327. NS_DECL_NSISIMPLEENUMERATOR
  328. };
  329. ////////////////////////////////////////////////////////////////////////
  330. InMemoryAssertionEnumeratorImpl::InMemoryAssertionEnumeratorImpl(
  331. InMemoryDataSource* aDataSource,
  332. nsIRDFResource* aSource,
  333. nsIRDFResource* aProperty,
  334. nsIRDFNode* aTarget,
  335. bool aTruthValue)
  336. : mDataSource(aDataSource),
  337. mSource(aSource),
  338. mProperty(aProperty),
  339. mTarget(aTarget),
  340. mValue(nullptr),
  341. mTruthValue(aTruthValue),
  342. mNextAssertion(nullptr)
  343. {
  344. NS_ADDREF(mDataSource);
  345. NS_IF_ADDREF(mSource);
  346. NS_ADDREF(mProperty);
  347. NS_IF_ADDREF(mTarget);
  348. if (mSource) {
  349. mNextAssertion = mDataSource->GetForwardArcs(mSource);
  350. if (mNextAssertion && mNextAssertion->mHashEntry) {
  351. // its our magical HASH_ENTRY forward hash for assertions
  352. PLDHashEntryHdr* hdr =
  353. mNextAssertion->u.hash.mPropertyHash->Search(aProperty);
  354. mNextAssertion =
  355. hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  356. }
  357. }
  358. else {
  359. mNextAssertion = mDataSource->GetReverseArcs(mTarget);
  360. }
  361. // Add an owning reference from the enumerator
  362. if (mNextAssertion)
  363. mNextAssertion->AddRef();
  364. }
  365. InMemoryAssertionEnumeratorImpl::~InMemoryAssertionEnumeratorImpl()
  366. {
  367. #ifdef DEBUG_REFS
  368. --gInstanceCount;
  369. fprintf(stdout, "%d - RDF: InMemoryAssertionEnumeratorImpl\n", gInstanceCount);
  370. #endif
  371. if (mNextAssertion)
  372. mNextAssertion->Release();
  373. NS_IF_RELEASE(mDataSource);
  374. NS_IF_RELEASE(mSource);
  375. NS_IF_RELEASE(mProperty);
  376. NS_IF_RELEASE(mTarget);
  377. NS_IF_RELEASE(mValue);
  378. }
  379. NS_IMPL_ADDREF(InMemoryAssertionEnumeratorImpl)
  380. NS_IMPL_RELEASE(InMemoryAssertionEnumeratorImpl)
  381. NS_IMPL_QUERY_INTERFACE(InMemoryAssertionEnumeratorImpl, nsISimpleEnumerator)
  382. NS_IMETHODIMP
  383. InMemoryAssertionEnumeratorImpl::HasMoreElements(bool* aResult)
  384. {
  385. if (mValue) {
  386. *aResult = true;
  387. return NS_OK;
  388. }
  389. while (mNextAssertion) {
  390. bool foundIt = false;
  391. if ((mProperty == mNextAssertion->u.as.mProperty) &&
  392. (mTruthValue == mNextAssertion->u.as.mTruthValue)) {
  393. if (mSource) {
  394. mValue = mNextAssertion->u.as.mTarget;
  395. NS_ADDREF(mValue);
  396. }
  397. else {
  398. mValue = mNextAssertion->mSource;
  399. NS_ADDREF(mValue);
  400. }
  401. foundIt = true;
  402. }
  403. // Remember the last assertion we were holding on to
  404. Assertion* as = mNextAssertion;
  405. // iterate
  406. mNextAssertion = (mSource) ? mNextAssertion->mNext : mNextAssertion->u.as.mInvNext;
  407. // grab an owning reference from the enumerator to the next assertion
  408. if (mNextAssertion)
  409. mNextAssertion->AddRef();
  410. // ...and release the reference from the enumerator to the old one.
  411. as->Release();
  412. if (foundIt) {
  413. *aResult = true;
  414. return NS_OK;
  415. }
  416. }
  417. *aResult = false;
  418. return NS_OK;
  419. }
  420. NS_IMETHODIMP
  421. InMemoryAssertionEnumeratorImpl::GetNext(nsISupports** aResult)
  422. {
  423. nsresult rv;
  424. bool hasMore;
  425. rv = HasMoreElements(&hasMore);
  426. if (NS_FAILED(rv)) return rv;
  427. if (! hasMore)
  428. return NS_ERROR_UNEXPECTED;
  429. // Don't AddRef: we "transfer" ownership to the caller
  430. *aResult = mValue;
  431. mValue = nullptr;
  432. return NS_OK;
  433. }
  434. ////////////////////////////////////////////////////////////////////////
  435. //
  436. /**
  437. * This class is a little bit bizarre in that it implements both the
  438. * <tt>nsIRDFArcsOutCursor</tt> and <tt>nsIRDFArcsInCursor</tt> interfaces.
  439. * Because the structure of the in-memory graph is pretty flexible, it's
  440. * fairly easy to parameterize this class. The only funky thing to watch
  441. * out for is the multiple inheritance clashes.
  442. */
  443. class InMemoryArcsEnumeratorImpl : public nsISimpleEnumerator
  444. {
  445. private:
  446. InMemoryDataSource* mDataSource;
  447. nsIRDFResource* mSource;
  448. nsIRDFNode* mTarget;
  449. AutoTArray<nsCOMPtr<nsIRDFResource>, 8> mAlreadyReturned;
  450. nsIRDFResource* mCurrent;
  451. Assertion* mAssertion;
  452. nsCOMArray<nsIRDFNode>* mHashArcs;
  453. virtual ~InMemoryArcsEnumeratorImpl();
  454. public:
  455. InMemoryArcsEnumeratorImpl(InMemoryDataSource* aDataSource,
  456. nsIRDFResource* aSource,
  457. nsIRDFNode* aTarget);
  458. // nsISupports interface
  459. NS_DECL_ISUPPORTS
  460. // nsISimpleEnumerator interface
  461. NS_DECL_NSISIMPLEENUMERATOR
  462. };
  463. InMemoryArcsEnumeratorImpl::InMemoryArcsEnumeratorImpl(InMemoryDataSource* aDataSource,
  464. nsIRDFResource* aSource,
  465. nsIRDFNode* aTarget)
  466. : mDataSource(aDataSource),
  467. mSource(aSource),
  468. mTarget(aTarget),
  469. mCurrent(nullptr),
  470. mHashArcs(nullptr)
  471. {
  472. NS_ADDREF(mDataSource);
  473. NS_IF_ADDREF(mSource);
  474. NS_IF_ADDREF(mTarget);
  475. if (mSource) {
  476. // cast okay because it's a closed system
  477. mAssertion = mDataSource->GetForwardArcs(mSource);
  478. if (mAssertion && mAssertion->mHashEntry) {
  479. // its our magical HASH_ENTRY forward hash for assertions
  480. mHashArcs = new nsCOMArray<nsIRDFNode>();
  481. for (auto i = mAssertion->u.hash.mPropertyHash->Iter();
  482. !i.Done();
  483. i.Next()) {
  484. auto entry = static_cast<Entry*>(i.Get());
  485. mHashArcs->AppendElement(entry->mNode);
  486. }
  487. mAssertion = nullptr;
  488. }
  489. }
  490. else {
  491. mAssertion = mDataSource->GetReverseArcs(mTarget);
  492. }
  493. }
  494. InMemoryArcsEnumeratorImpl::~InMemoryArcsEnumeratorImpl()
  495. {
  496. #ifdef DEBUG_REFS
  497. --gInstanceCount;
  498. fprintf(stdout, "%d - RDF: InMemoryArcsEnumeratorImpl\n", gInstanceCount);
  499. #endif
  500. NS_RELEASE(mDataSource);
  501. NS_IF_RELEASE(mSource);
  502. NS_IF_RELEASE(mTarget);
  503. NS_IF_RELEASE(mCurrent);
  504. delete mHashArcs;
  505. }
  506. NS_IMPL_ADDREF(InMemoryArcsEnumeratorImpl)
  507. NS_IMPL_RELEASE(InMemoryArcsEnumeratorImpl)
  508. NS_IMPL_QUERY_INTERFACE(InMemoryArcsEnumeratorImpl, nsISimpleEnumerator)
  509. NS_IMETHODIMP
  510. InMemoryArcsEnumeratorImpl::HasMoreElements(bool* aResult)
  511. {
  512. NS_PRECONDITION(aResult != nullptr, "null ptr");
  513. if (! aResult)
  514. return NS_ERROR_NULL_POINTER;
  515. if (mCurrent) {
  516. *aResult = true;
  517. return NS_OK;
  518. }
  519. if (mHashArcs) {
  520. if (!mHashArcs->IsEmpty()) {
  521. const uint32_t last = mHashArcs->Length() - 1;
  522. nsCOMPtr<nsIRDFResource> tmp(do_QueryInterface(mHashArcs->ObjectAt(last)));
  523. tmp.forget(&mCurrent);
  524. mHashArcs->RemoveElementAt(last);
  525. *aResult = true;
  526. return NS_OK;
  527. }
  528. }
  529. else
  530. while (mAssertion) {
  531. nsIRDFResource* next = mAssertion->u.as.mProperty;
  532. // "next" is the property arc we are tentatively going to return
  533. // in a subsequent GetNext() call. It is important to do two
  534. // things, however, before that can happen:
  535. // 1) Make sure it's not an arc we've already returned.
  536. // 2) Make sure that |mAssertion| is not left pointing to
  537. // another assertion that has the same property as this one.
  538. // The first is a practical concern; the second a defense against
  539. // an obscure crash and other erratic behavior. To ensure the
  540. // second condition, skip down the chain until we find the next
  541. // assertion with a property that doesn't match the current one.
  542. // (All these assertions would be skipped via mAlreadyReturned
  543. // checks anyways; this is even a bit faster.)
  544. do {
  545. mAssertion = (mSource ? mAssertion->mNext :
  546. mAssertion->u.as.mInvNext);
  547. }
  548. while (mAssertion && (next == mAssertion->u.as.mProperty));
  549. bool alreadyReturned = false;
  550. for (int32_t i = mAlreadyReturned.Length() - 1; i >= 0; --i) {
  551. if (mAlreadyReturned[i] == next) {
  552. alreadyReturned = true;
  553. break;
  554. }
  555. }
  556. if (! alreadyReturned) {
  557. mCurrent = next;
  558. NS_ADDREF(mCurrent);
  559. *aResult = true;
  560. return NS_OK;
  561. }
  562. }
  563. *aResult = false;
  564. return NS_OK;
  565. }
  566. NS_IMETHODIMP
  567. InMemoryArcsEnumeratorImpl::GetNext(nsISupports** aResult)
  568. {
  569. nsresult rv;
  570. bool hasMore;
  571. rv = HasMoreElements(&hasMore);
  572. if (NS_FAILED(rv)) return rv;
  573. if (! hasMore)
  574. return NS_ERROR_UNEXPECTED;
  575. // Add this to the set of things we've already returned so that we
  576. // can ensure uniqueness
  577. mAlreadyReturned.AppendElement(mCurrent);
  578. // Don't AddRef: we "transfer" ownership to the caller
  579. *aResult = mCurrent;
  580. mCurrent = nullptr;
  581. return NS_OK;
  582. }
  583. ////////////////////////////////////////////////////////////////////////
  584. // InMemoryDataSource
  585. nsresult
  586. NS_NewRDFInMemoryDataSource(nsISupports* aOuter, const nsIID& aIID, void** aResult)
  587. {
  588. NS_PRECONDITION(aResult != nullptr, "null ptr");
  589. if (! aResult)
  590. return NS_ERROR_NULL_POINTER;
  591. *aResult = nullptr;
  592. if (aOuter && !aIID.Equals(NS_GET_IID(nsISupports))) {
  593. NS_ERROR("aggregation requires nsISupports");
  594. return NS_ERROR_ILLEGAL_VALUE;
  595. }
  596. InMemoryDataSource* datasource = new InMemoryDataSource(aOuter);
  597. NS_ADDREF(datasource);
  598. datasource->fAggregated.AddRef();
  599. nsresult rv = datasource->AggregatedQueryInterface(aIID, aResult); // This'll AddRef()
  600. datasource->fAggregated.Release();
  601. NS_RELEASE(datasource);
  602. return rv;
  603. }
  604. InMemoryDataSource::InMemoryDataSource(nsISupports* aOuter)
  605. : mForwardArcs(PLDHashTable::StubOps(), sizeof(Entry))
  606. , mReverseArcs(PLDHashTable::StubOps(), sizeof(Entry))
  607. , mNumObservers(0)
  608. , mReadCount(0)
  609. {
  610. NS_INIT_AGGREGATED(aOuter);
  611. mPropagateChanges = true;
  612. MOZ_COUNT_CTOR(InMemoryDataSource);
  613. }
  614. InMemoryDataSource::~InMemoryDataSource()
  615. {
  616. #ifdef DEBUG_REFS
  617. --gInstanceCount;
  618. fprintf(stdout, "%d - RDF: InMemoryDataSource\n", gInstanceCount);
  619. #endif
  620. if (mForwardArcs.EntryCount() > 0) {
  621. // This'll release all of the Assertion objects that are
  622. // associated with this data source. We only need to do this
  623. // for the forward arcs, because the reverse arcs table
  624. // indexes the exact same set of resources.
  625. for (auto iter = mForwardArcs.Iter(); !iter.Done(); iter.Next()) {
  626. auto entry = static_cast<Entry*>(iter.Get());
  627. Assertion* as = entry->mAssertions;
  628. while (as) {
  629. Assertion* doomed = as;
  630. as = as->mNext;
  631. // Unlink, and release the datasource's reference.
  632. doomed->mNext = doomed->u.as.mInvNext = nullptr;
  633. doomed->Release();
  634. }
  635. }
  636. }
  637. MOZ_LOG(gLog, LogLevel::Debug,
  638. ("InMemoryDataSource(%p): destroyed.", this));
  639. MOZ_COUNT_DTOR(InMemoryDataSource);
  640. }
  641. ////////////////////////////////////////////////////////////////////////
  642. NS_IMPL_CYCLE_COLLECTION_CLASS(InMemoryDataSource)
  643. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(InMemoryDataSource)
  644. NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservers)
  645. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  646. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(InMemoryDataSource)
  647. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservers)
  648. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  649. NS_IMPL_CYCLE_COLLECTING_AGGREGATED(InMemoryDataSource)
  650. NS_INTERFACE_MAP_BEGIN_AGGREGATED(InMemoryDataSource)
  651. NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION_AGGREGATED(InMemoryDataSource)
  652. NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
  653. NS_INTERFACE_MAP_ENTRY(nsIRDFInMemoryDataSource)
  654. NS_INTERFACE_MAP_ENTRY(nsIRDFPropagatableDataSource)
  655. NS_INTERFACE_MAP_ENTRY(nsIRDFPurgeableDataSource)
  656. NS_INTERFACE_MAP_ENTRY(rdfIDataSource)
  657. NS_INTERFACE_MAP_END
  658. ////////////////////////////////////////////////////////////////////////
  659. void
  660. InMemoryDataSource::LogOperation(const char* aOperation,
  661. nsIRDFResource* aSource,
  662. nsIRDFResource* aProperty,
  663. nsIRDFNode* aTarget,
  664. bool aTruthValue)
  665. {
  666. if (! MOZ_LOG_TEST(gLog, LogLevel::Debug))
  667. return;
  668. nsXPIDLCString uri;
  669. aSource->GetValue(getter_Copies(uri));
  670. PR_LogPrint
  671. ("InMemoryDataSource(%p): %s", this, aOperation);
  672. PR_LogPrint
  673. (" [(%p)%s]--", aSource, (const char*) uri);
  674. aProperty->GetValue(getter_Copies(uri));
  675. char tv = (aTruthValue ? '-' : '!');
  676. PR_LogPrint
  677. (" --%c[(%p)%s]--", tv, aProperty, (const char*) uri);
  678. nsCOMPtr<nsIRDFResource> resource;
  679. nsCOMPtr<nsIRDFLiteral> literal;
  680. if ((resource = do_QueryInterface(aTarget)) != nullptr) {
  681. resource->GetValue(getter_Copies(uri));
  682. PR_LogPrint
  683. (" -->[(%p)%s]", aTarget, (const char*) uri);
  684. }
  685. else if ((literal = do_QueryInterface(aTarget)) != nullptr) {
  686. nsXPIDLString value;
  687. literal->GetValue(getter_Copies(value));
  688. nsAutoString valueStr(value);
  689. char* valueCStr = ToNewCString(valueStr);
  690. PR_LogPrint
  691. (" -->(\"%s\")\n", valueCStr);
  692. free(valueCStr);
  693. }
  694. else {
  695. PR_LogPrint
  696. (" -->(unknown-type)\n");
  697. }
  698. }
  699. NS_IMETHODIMP
  700. InMemoryDataSource::GetURI(char* *uri)
  701. {
  702. NS_PRECONDITION(uri != nullptr, "null ptr");
  703. if (! uri)
  704. return NS_ERROR_NULL_POINTER;
  705. *uri = nullptr;
  706. return NS_OK;
  707. }
  708. NS_IMETHODIMP
  709. InMemoryDataSource::GetSource(nsIRDFResource* property,
  710. nsIRDFNode* target,
  711. bool tv,
  712. nsIRDFResource** source)
  713. {
  714. NS_PRECONDITION(source != nullptr, "null ptr");
  715. if (! source)
  716. return NS_ERROR_NULL_POINTER;
  717. NS_PRECONDITION(property != nullptr, "null ptr");
  718. if (! property)
  719. return NS_ERROR_NULL_POINTER;
  720. NS_PRECONDITION(target != nullptr, "null ptr");
  721. if (! target)
  722. return NS_ERROR_NULL_POINTER;
  723. for (Assertion* as = GetReverseArcs(target); as; as = as->u.as.mInvNext) {
  724. if ((property == as->u.as.mProperty) && (tv == as->u.as.mTruthValue)) {
  725. *source = as->mSource;
  726. NS_ADDREF(*source);
  727. return NS_OK;
  728. }
  729. }
  730. *source = nullptr;
  731. return NS_RDF_NO_VALUE;
  732. }
  733. NS_IMETHODIMP
  734. InMemoryDataSource::GetTarget(nsIRDFResource* source,
  735. nsIRDFResource* property,
  736. bool tv,
  737. nsIRDFNode** target)
  738. {
  739. NS_PRECONDITION(source != nullptr, "null ptr");
  740. if (! source)
  741. return NS_ERROR_NULL_POINTER;
  742. NS_PRECONDITION(property != nullptr, "null ptr");
  743. if (! property)
  744. return NS_ERROR_NULL_POINTER;
  745. NS_PRECONDITION(target != nullptr, "null ptr");
  746. if (! target)
  747. return NS_ERROR_NULL_POINTER;
  748. Assertion *as = GetForwardArcs(source);
  749. if (as && as->mHashEntry) {
  750. PLDHashEntryHdr* hdr = as->u.hash.mPropertyHash->Search(property);
  751. Assertion* val = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  752. while (val) {
  753. if (tv == val->u.as.mTruthValue) {
  754. *target = val->u.as.mTarget;
  755. NS_IF_ADDREF(*target);
  756. return NS_OK;
  757. }
  758. val = val->mNext;
  759. }
  760. }
  761. else
  762. for (; as != nullptr; as = as->mNext) {
  763. if ((property == as->u.as.mProperty) && (tv == (as->u.as.mTruthValue))) {
  764. *target = as->u.as.mTarget;
  765. NS_ADDREF(*target);
  766. return NS_OK;
  767. }
  768. }
  769. // If we get here, then there was no target with for the specified
  770. // property & truth value.
  771. *target = nullptr;
  772. return NS_RDF_NO_VALUE;
  773. }
  774. NS_IMETHODIMP
  775. InMemoryDataSource::HasAssertion(nsIRDFResource* source,
  776. nsIRDFResource* property,
  777. nsIRDFNode* target,
  778. bool tv,
  779. bool* hasAssertion)
  780. {
  781. if (! source)
  782. return NS_ERROR_NULL_POINTER;
  783. if (! property)
  784. return NS_ERROR_NULL_POINTER;
  785. if (! target)
  786. return NS_ERROR_NULL_POINTER;
  787. Assertion *as = GetForwardArcs(source);
  788. if (as && as->mHashEntry) {
  789. PLDHashEntryHdr* hdr = as->u.hash.mPropertyHash->Search(property);
  790. Assertion* val = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  791. while (val) {
  792. if ((val->u.as.mTarget == target) && (tv == (val->u.as.mTruthValue))) {
  793. *hasAssertion = true;
  794. return NS_OK;
  795. }
  796. val = val->mNext;
  797. }
  798. }
  799. else
  800. for (; as != nullptr; as = as->mNext) {
  801. // check target first as its most unique
  802. if (target != as->u.as.mTarget)
  803. continue;
  804. if (property != as->u.as.mProperty)
  805. continue;
  806. if (tv != (as->u.as.mTruthValue))
  807. continue;
  808. // found it!
  809. *hasAssertion = true;
  810. return NS_OK;
  811. }
  812. // If we get here, we couldn't find the assertion
  813. *hasAssertion = false;
  814. return NS_OK;
  815. }
  816. NS_IMETHODIMP
  817. InMemoryDataSource::GetSources(nsIRDFResource* aProperty,
  818. nsIRDFNode* aTarget,
  819. bool aTruthValue,
  820. nsISimpleEnumerator** aResult)
  821. {
  822. NS_PRECONDITION(aProperty != nullptr, "null ptr");
  823. if (! aProperty)
  824. return NS_ERROR_NULL_POINTER;
  825. NS_PRECONDITION(aTarget != nullptr, "null ptr");
  826. if (! aTarget)
  827. return NS_ERROR_NULL_POINTER;
  828. NS_PRECONDITION(aResult != nullptr, "null ptr");
  829. if (! aResult)
  830. return NS_ERROR_NULL_POINTER;
  831. InMemoryAssertionEnumeratorImpl* result =
  832. new InMemoryAssertionEnumeratorImpl(this, nullptr, aProperty,
  833. aTarget, aTruthValue);
  834. if (! result)
  835. return NS_ERROR_OUT_OF_MEMORY;
  836. NS_ADDREF(result);
  837. *aResult = result;
  838. return NS_OK;
  839. }
  840. NS_IMETHODIMP
  841. InMemoryDataSource::GetTargets(nsIRDFResource* aSource,
  842. nsIRDFResource* aProperty,
  843. bool aTruthValue,
  844. nsISimpleEnumerator** aResult)
  845. {
  846. NS_PRECONDITION(aSource != nullptr, "null ptr");
  847. if (! aSource)
  848. return NS_ERROR_NULL_POINTER;
  849. NS_PRECONDITION(aProperty != nullptr, "null ptr");
  850. if (! aProperty)
  851. return NS_ERROR_NULL_POINTER;
  852. NS_PRECONDITION(aResult != nullptr, "null ptr");
  853. if (! aResult)
  854. return NS_ERROR_NULL_POINTER;
  855. InMemoryAssertionEnumeratorImpl* result =
  856. new InMemoryAssertionEnumeratorImpl(this, aSource, aProperty,
  857. nullptr, aTruthValue);
  858. if (! result)
  859. return NS_ERROR_OUT_OF_MEMORY;
  860. NS_ADDREF(result);
  861. *aResult = result;
  862. return NS_OK;
  863. }
  864. nsresult
  865. InMemoryDataSource::LockedAssert(nsIRDFResource* aSource,
  866. nsIRDFResource* aProperty,
  867. nsIRDFNode* aTarget,
  868. bool aTruthValue)
  869. {
  870. LogOperation("ASSERT", aSource, aProperty, aTarget, aTruthValue);
  871. Assertion* next = GetForwardArcs(aSource);
  872. Assertion* prev = next;
  873. Assertion* as = nullptr;
  874. bool haveHash = (next) ? next->mHashEntry : false;
  875. if (haveHash) {
  876. PLDHashEntryHdr* hdr = next->u.hash.mPropertyHash->Search(aProperty);
  877. Assertion* val = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  878. while (val) {
  879. if (val->u.as.mTarget == aTarget) {
  880. // Wow, we already had the assertion. Make sure that the
  881. // truth values are correct and bail.
  882. val->u.as.mTruthValue = aTruthValue;
  883. return NS_OK;
  884. }
  885. val = val->mNext;
  886. }
  887. }
  888. else
  889. {
  890. while (next) {
  891. // check target first as its most unique
  892. if (aTarget == next->u.as.mTarget) {
  893. if (aProperty == next->u.as.mProperty) {
  894. // Wow, we already had the assertion. Make sure that the
  895. // truth values are correct and bail.
  896. next->u.as.mTruthValue = aTruthValue;
  897. return NS_OK;
  898. }
  899. }
  900. prev = next;
  901. next = next->mNext;
  902. }
  903. }
  904. as = new Assertion(aSource, aProperty, aTarget, aTruthValue);
  905. if (! as)
  906. return NS_ERROR_OUT_OF_MEMORY;
  907. // Add the datasource's owning reference.
  908. as->AddRef();
  909. if (haveHash)
  910. {
  911. PLDHashEntryHdr* hdr = next->u.hash.mPropertyHash->Search(aProperty);
  912. Assertion *asRef =
  913. hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  914. if (asRef)
  915. {
  916. as->mNext = asRef->mNext;
  917. asRef->mNext = as;
  918. }
  919. else
  920. {
  921. hdr = next->u.hash.mPropertyHash->Add(aProperty, mozilla::fallible);
  922. if (hdr)
  923. {
  924. Entry* entry = static_cast<Entry*>(hdr);
  925. entry->mNode = aProperty;
  926. entry->mAssertions = as;
  927. }
  928. }
  929. }
  930. else
  931. {
  932. // Link it in to the "forward arcs" table
  933. if (!prev) {
  934. SetForwardArcs(aSource, as);
  935. } else {
  936. prev->mNext = as;
  937. }
  938. }
  939. // Link it in to the "reverse arcs" table
  940. next = GetReverseArcs(aTarget);
  941. as->u.as.mInvNext = next;
  942. next = as;
  943. SetReverseArcs(aTarget, next);
  944. return NS_OK;
  945. }
  946. NS_IMETHODIMP
  947. InMemoryDataSource::Assert(nsIRDFResource* aSource,
  948. nsIRDFResource* aProperty,
  949. nsIRDFNode* aTarget,
  950. bool aTruthValue)
  951. {
  952. NS_PRECONDITION(aSource != nullptr, "null ptr");
  953. if (! aSource)
  954. return NS_ERROR_NULL_POINTER;
  955. NS_PRECONDITION(aProperty != nullptr, "null ptr");
  956. if (! aProperty)
  957. return NS_ERROR_NULL_POINTER;
  958. NS_PRECONDITION(aTarget != nullptr, "null ptr");
  959. if (! aTarget)
  960. return NS_ERROR_NULL_POINTER;
  961. if (mReadCount) {
  962. NS_WARNING("Writing to InMemoryDataSource during read\n");
  963. return NS_RDF_ASSERTION_REJECTED;
  964. }
  965. nsresult rv;
  966. rv = LockedAssert(aSource, aProperty, aTarget, aTruthValue);
  967. if (NS_FAILED(rv)) return rv;
  968. // notify observers
  969. for (int32_t i = (int32_t)mNumObservers - 1; mPropagateChanges && i >= 0; --i) {
  970. nsIRDFObserver* obs = mObservers[i];
  971. // XXX this should never happen, but it does, and we can't figure out why.
  972. NS_ASSERTION(obs, "observer array corrupted!");
  973. if (! obs)
  974. continue;
  975. obs->OnAssert(this, aSource, aProperty, aTarget);
  976. // XXX ignore return value?
  977. }
  978. return NS_RDF_ASSERTION_ACCEPTED;
  979. }
  980. nsresult
  981. InMemoryDataSource::LockedUnassert(nsIRDFResource* aSource,
  982. nsIRDFResource* aProperty,
  983. nsIRDFNode* aTarget)
  984. {
  985. LogOperation("UNASSERT", aSource, aProperty, aTarget);
  986. Assertion* next = GetForwardArcs(aSource);
  987. Assertion* prev = next;
  988. Assertion* root = next;
  989. Assertion* as = nullptr;
  990. bool haveHash = (next) ? next->mHashEntry : false;
  991. if (haveHash) {
  992. PLDHashEntryHdr* hdr = next->u.hash.mPropertyHash->Search(aProperty);
  993. prev = next = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  994. bool first = true;
  995. while (next) {
  996. if (aTarget == next->u.as.mTarget) {
  997. break;
  998. }
  999. first = false;
  1000. prev = next;
  1001. next = next->mNext;
  1002. }
  1003. // We don't even have the assertion, so just bail.
  1004. if (!next)
  1005. return NS_OK;
  1006. as = next;
  1007. if (first) {
  1008. root->u.hash.mPropertyHash->RawRemove(hdr);
  1009. if (next && next->mNext) {
  1010. PLDHashEntryHdr* hdr =
  1011. root->u.hash.mPropertyHash->Add(aProperty,
  1012. mozilla::fallible);
  1013. if (hdr) {
  1014. Entry* entry = static_cast<Entry*>(hdr);
  1015. entry->mNode = aProperty;
  1016. entry->mAssertions = next->mNext;
  1017. }
  1018. }
  1019. else {
  1020. // If this second-level hash empties out, clean it up.
  1021. if (!root->u.hash.mPropertyHash->EntryCount()) {
  1022. root->Release();
  1023. SetForwardArcs(aSource, nullptr);
  1024. }
  1025. }
  1026. }
  1027. else {
  1028. prev->mNext = next->mNext;
  1029. }
  1030. }
  1031. else
  1032. {
  1033. while (next) {
  1034. // check target first as its most unique
  1035. if (aTarget == next->u.as.mTarget) {
  1036. if (aProperty == next->u.as.mProperty) {
  1037. if (prev == next) {
  1038. SetForwardArcs(aSource, next->mNext);
  1039. } else {
  1040. prev->mNext = next->mNext;
  1041. }
  1042. as = next;
  1043. break;
  1044. }
  1045. }
  1046. prev = next;
  1047. next = next->mNext;
  1048. }
  1049. }
  1050. // We don't even have the assertion, so just bail.
  1051. if (!as)
  1052. return NS_OK;
  1053. #ifdef DEBUG
  1054. bool foundReverseArc = false;
  1055. #endif
  1056. next = prev = GetReverseArcs(aTarget);
  1057. while (next) {
  1058. if (next == as) {
  1059. if (prev == next) {
  1060. SetReverseArcs(aTarget, next->u.as.mInvNext);
  1061. } else {
  1062. prev->u.as.mInvNext = next->u.as.mInvNext;
  1063. }
  1064. #ifdef DEBUG
  1065. foundReverseArc = true;
  1066. #endif
  1067. break;
  1068. }
  1069. prev = next;
  1070. next = next->u.as.mInvNext;
  1071. }
  1072. #ifdef DEBUG
  1073. NS_ASSERTION(foundReverseArc, "in-memory db corrupted: unable to find reverse arc");
  1074. #endif
  1075. // Unlink, and release the datasource's reference
  1076. as->mNext = as->u.as.mInvNext = nullptr;
  1077. as->Release();
  1078. return NS_OK;
  1079. }
  1080. NS_IMETHODIMP
  1081. InMemoryDataSource::Unassert(nsIRDFResource* aSource,
  1082. nsIRDFResource* aProperty,
  1083. nsIRDFNode* aTarget)
  1084. {
  1085. NS_PRECONDITION(aSource != nullptr, "null ptr");
  1086. if (! aSource)
  1087. return NS_ERROR_NULL_POINTER;
  1088. NS_PRECONDITION(aProperty != nullptr, "null ptr");
  1089. if (! aProperty)
  1090. return NS_ERROR_NULL_POINTER;
  1091. NS_PRECONDITION(aTarget != nullptr, "null ptr");
  1092. if (! aTarget)
  1093. return NS_ERROR_NULL_POINTER;
  1094. if (mReadCount) {
  1095. NS_WARNING("Writing to InMemoryDataSource during read\n");
  1096. return NS_RDF_ASSERTION_REJECTED;
  1097. }
  1098. nsresult rv;
  1099. rv = LockedUnassert(aSource, aProperty, aTarget);
  1100. if (NS_FAILED(rv)) return rv;
  1101. // Notify the world
  1102. for (int32_t i = int32_t(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
  1103. nsIRDFObserver* obs = mObservers[i];
  1104. // XXX this should never happen, but it does, and we can't figure out why.
  1105. NS_ASSERTION(obs, "observer array corrupted!");
  1106. if (! obs)
  1107. continue;
  1108. obs->OnUnassert(this, aSource, aProperty, aTarget);
  1109. // XXX ignore return value?
  1110. }
  1111. return NS_RDF_ASSERTION_ACCEPTED;
  1112. }
  1113. NS_IMETHODIMP
  1114. InMemoryDataSource::Change(nsIRDFResource* aSource,
  1115. nsIRDFResource* aProperty,
  1116. nsIRDFNode* aOldTarget,
  1117. nsIRDFNode* aNewTarget)
  1118. {
  1119. NS_PRECONDITION(aSource != nullptr, "null ptr");
  1120. if (! aSource)
  1121. return NS_ERROR_NULL_POINTER;
  1122. NS_PRECONDITION(aProperty != nullptr, "null ptr");
  1123. if (! aProperty)
  1124. return NS_ERROR_NULL_POINTER;
  1125. NS_PRECONDITION(aOldTarget != nullptr, "null ptr");
  1126. if (! aOldTarget)
  1127. return NS_ERROR_NULL_POINTER;
  1128. NS_PRECONDITION(aNewTarget != nullptr, "null ptr");
  1129. if (! aNewTarget)
  1130. return NS_ERROR_NULL_POINTER;
  1131. if (mReadCount) {
  1132. NS_WARNING("Writing to InMemoryDataSource during read\n");
  1133. return NS_RDF_ASSERTION_REJECTED;
  1134. }
  1135. nsresult rv;
  1136. // XXX We can implement LockedChange() if we decide that this
  1137. // is a performance bottleneck.
  1138. rv = LockedUnassert(aSource, aProperty, aOldTarget);
  1139. if (NS_FAILED(rv)) return rv;
  1140. rv = LockedAssert(aSource, aProperty, aNewTarget, true);
  1141. if (NS_FAILED(rv)) return rv;
  1142. // Notify the world
  1143. for (int32_t i = int32_t(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
  1144. nsIRDFObserver* obs = mObservers[i];
  1145. // XXX this should never happen, but it does, and we can't figure out why.
  1146. NS_ASSERTION(obs, "observer array corrupted!");
  1147. if (! obs)
  1148. continue;
  1149. obs->OnChange(this, aSource, aProperty, aOldTarget, aNewTarget);
  1150. // XXX ignore return value?
  1151. }
  1152. return NS_RDF_ASSERTION_ACCEPTED;
  1153. }
  1154. NS_IMETHODIMP
  1155. InMemoryDataSource::Move(nsIRDFResource* aOldSource,
  1156. nsIRDFResource* aNewSource,
  1157. nsIRDFResource* aProperty,
  1158. nsIRDFNode* aTarget)
  1159. {
  1160. NS_PRECONDITION(aOldSource != nullptr, "null ptr");
  1161. if (! aOldSource)
  1162. return NS_ERROR_NULL_POINTER;
  1163. NS_PRECONDITION(aNewSource != nullptr, "null ptr");
  1164. if (! aNewSource)
  1165. return NS_ERROR_NULL_POINTER;
  1166. NS_PRECONDITION(aProperty != nullptr, "null ptr");
  1167. if (! aProperty)
  1168. return NS_ERROR_NULL_POINTER;
  1169. NS_PRECONDITION(aTarget != nullptr, "null ptr");
  1170. if (! aTarget)
  1171. return NS_ERROR_NULL_POINTER;
  1172. if (mReadCount) {
  1173. NS_WARNING("Writing to InMemoryDataSource during read\n");
  1174. return NS_RDF_ASSERTION_REJECTED;
  1175. }
  1176. nsresult rv;
  1177. // XXX We can implement LockedMove() if we decide that this
  1178. // is a performance bottleneck.
  1179. rv = LockedUnassert(aOldSource, aProperty, aTarget);
  1180. if (NS_FAILED(rv)) return rv;
  1181. rv = LockedAssert(aNewSource, aProperty, aTarget, true);
  1182. if (NS_FAILED(rv)) return rv;
  1183. // Notify the world
  1184. for (int32_t i = int32_t(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
  1185. nsIRDFObserver* obs = mObservers[i];
  1186. // XXX this should never happen, but it does, and we can't figure out why.
  1187. NS_ASSERTION(obs, "observer array corrupted!");
  1188. if (! obs)
  1189. continue;
  1190. obs->OnMove(this, aOldSource, aNewSource, aProperty, aTarget);
  1191. // XXX ignore return value?
  1192. }
  1193. return NS_RDF_ASSERTION_ACCEPTED;
  1194. }
  1195. NS_IMETHODIMP
  1196. InMemoryDataSource::AddObserver(nsIRDFObserver* aObserver)
  1197. {
  1198. NS_PRECONDITION(aObserver != nullptr, "null ptr");
  1199. if (! aObserver)
  1200. return NS_ERROR_NULL_POINTER;
  1201. mObservers.AppendObject(aObserver);
  1202. mNumObservers = mObservers.Count();
  1203. return NS_OK;
  1204. }
  1205. NS_IMETHODIMP
  1206. InMemoryDataSource::RemoveObserver(nsIRDFObserver* aObserver)
  1207. {
  1208. NS_PRECONDITION(aObserver != nullptr, "null ptr");
  1209. if (! aObserver)
  1210. return NS_ERROR_NULL_POINTER;
  1211. mObservers.RemoveObject(aObserver);
  1212. // note: use Count() instead of just decrementing
  1213. // in case aObserver wasn't in list, for example
  1214. mNumObservers = mObservers.Count();
  1215. return NS_OK;
  1216. }
  1217. NS_IMETHODIMP
  1218. InMemoryDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
  1219. {
  1220. Assertion* ass = GetReverseArcs(aNode);
  1221. while (ass) {
  1222. nsIRDFResource* elbow = ass->u.as.mProperty;
  1223. if (elbow == aArc) {
  1224. *result = true;
  1225. return NS_OK;
  1226. }
  1227. ass = ass->u.as.mInvNext;
  1228. }
  1229. *result = false;
  1230. return NS_OK;
  1231. }
  1232. NS_IMETHODIMP
  1233. InMemoryDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
  1234. {
  1235. Assertion* ass = GetForwardArcs(aSource);
  1236. if (ass && ass->mHashEntry) {
  1237. PLDHashEntryHdr* hdr = ass->u.hash.mPropertyHash->Search(aArc);
  1238. Assertion* val = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  1239. if (val) {
  1240. *result = true;
  1241. return NS_OK;
  1242. }
  1243. ass = ass->mNext;
  1244. }
  1245. while (ass) {
  1246. nsIRDFResource* elbow = ass->u.as.mProperty;
  1247. if (elbow == aArc) {
  1248. *result = true;
  1249. return NS_OK;
  1250. }
  1251. ass = ass->mNext;
  1252. }
  1253. *result = false;
  1254. return NS_OK;
  1255. }
  1256. NS_IMETHODIMP
  1257. InMemoryDataSource::ArcLabelsIn(nsIRDFNode* aTarget, nsISimpleEnumerator** aResult)
  1258. {
  1259. NS_PRECONDITION(aTarget != nullptr, "null ptr");
  1260. if (! aTarget)
  1261. return NS_ERROR_NULL_POINTER;
  1262. InMemoryArcsEnumeratorImpl* result =
  1263. new InMemoryArcsEnumeratorImpl(this, nullptr, aTarget);
  1264. if (! result)
  1265. return NS_ERROR_OUT_OF_MEMORY;
  1266. NS_ADDREF(result);
  1267. *aResult = result;
  1268. return NS_OK;
  1269. }
  1270. NS_IMETHODIMP
  1271. InMemoryDataSource::ArcLabelsOut(nsIRDFResource* aSource, nsISimpleEnumerator** aResult)
  1272. {
  1273. NS_PRECONDITION(aSource != nullptr, "null ptr");
  1274. if (! aSource)
  1275. return NS_ERROR_NULL_POINTER;
  1276. InMemoryArcsEnumeratorImpl* result =
  1277. new InMemoryArcsEnumeratorImpl(this, aSource, nullptr);
  1278. if (! result)
  1279. return NS_ERROR_OUT_OF_MEMORY;
  1280. NS_ADDREF(result);
  1281. *aResult = result;
  1282. return NS_OK;
  1283. }
  1284. NS_IMETHODIMP
  1285. InMemoryDataSource::GetAllResources(nsISimpleEnumerator** aResult)
  1286. {
  1287. nsCOMArray<nsIRDFNode> nodes;
  1288. nodes.SetCapacity(mForwardArcs.EntryCount());
  1289. // Get all of our entries into an nsCOMArray
  1290. for (auto iter = mForwardArcs.Iter(); !iter.Done(); iter.Next()) {
  1291. auto entry = static_cast<Entry*>(iter.Get());
  1292. nodes.AppendObject(entry->mNode);
  1293. }
  1294. return NS_NewArrayEnumerator(aResult, nodes);
  1295. }
  1296. NS_IMETHODIMP
  1297. InMemoryDataSource::GetAllCmds(nsIRDFResource* source,
  1298. nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
  1299. {
  1300. return(NS_NewEmptyEnumerator(commands));
  1301. }
  1302. NS_IMETHODIMP
  1303. InMemoryDataSource::IsCommandEnabled(nsISupports* aSources,
  1304. nsIRDFResource* aCommand,
  1305. nsISupports* aArguments,
  1306. bool* aResult)
  1307. {
  1308. return NS_ERROR_NOT_IMPLEMENTED;
  1309. }
  1310. NS_IMETHODIMP
  1311. InMemoryDataSource::DoCommand(nsISupports* aSources,
  1312. nsIRDFResource* aCommand,
  1313. nsISupports* aArguments)
  1314. {
  1315. return NS_ERROR_NOT_IMPLEMENTED;
  1316. }
  1317. NS_IMETHODIMP
  1318. InMemoryDataSource::BeginUpdateBatch()
  1319. {
  1320. for (int32_t i = int32_t(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
  1321. nsIRDFObserver* obs = mObservers[i];
  1322. obs->OnBeginUpdateBatch(this);
  1323. }
  1324. return NS_OK;
  1325. }
  1326. NS_IMETHODIMP
  1327. InMemoryDataSource::EndUpdateBatch()
  1328. {
  1329. for (int32_t i = int32_t(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
  1330. nsIRDFObserver* obs = mObservers[i];
  1331. obs->OnEndUpdateBatch(this);
  1332. }
  1333. return NS_OK;
  1334. }
  1335. ////////////////////////////////////////////////////////////////////////
  1336. // nsIRDFInMemoryDataSource methods
  1337. NS_IMETHODIMP
  1338. InMemoryDataSource::EnsureFastContainment(nsIRDFResource* aSource)
  1339. {
  1340. Assertion *as = GetForwardArcs(aSource);
  1341. bool haveHash = (as) ? as->mHashEntry : false;
  1342. // if its already a hash, then nothing to do
  1343. if (haveHash) return(NS_OK);
  1344. // convert aSource in forward hash into a hash
  1345. Assertion *hashAssertion = new Assertion(aSource);
  1346. NS_ASSERTION(hashAssertion, "unable to create Assertion");
  1347. if (!hashAssertion) return(NS_ERROR_OUT_OF_MEMORY);
  1348. // Add the datasource's owning reference.
  1349. hashAssertion->AddRef();
  1350. Assertion *first = GetForwardArcs(aSource);
  1351. SetForwardArcs(aSource, hashAssertion);
  1352. // mutate references of existing forward assertions into this hash
  1353. PLDHashTable *table = hashAssertion->u.hash.mPropertyHash;
  1354. Assertion *nextRef;
  1355. while(first) {
  1356. nextRef = first->mNext;
  1357. nsIRDFResource *prop = first->u.as.mProperty;
  1358. PLDHashEntryHdr* hdr = table->Search(prop);
  1359. Assertion* val = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  1360. if (val) {
  1361. first->mNext = val->mNext;
  1362. val->mNext = first;
  1363. }
  1364. else {
  1365. PLDHashEntryHdr* hdr = table->Add(prop, mozilla::fallible);
  1366. if (hdr) {
  1367. Entry* entry = static_cast<Entry*>(hdr);
  1368. entry->mNode = prop;
  1369. entry->mAssertions = first;
  1370. first->mNext = nullptr;
  1371. }
  1372. }
  1373. first = nextRef;
  1374. }
  1375. return(NS_OK);
  1376. }
  1377. ////////////////////////////////////////////////////////////////////////
  1378. // nsIRDFPropagatableDataSource methods
  1379. NS_IMETHODIMP
  1380. InMemoryDataSource::GetPropagateChanges(bool* aPropagateChanges)
  1381. {
  1382. *aPropagateChanges = mPropagateChanges;
  1383. return NS_OK;
  1384. }
  1385. NS_IMETHODIMP
  1386. InMemoryDataSource::SetPropagateChanges(bool aPropagateChanges)
  1387. {
  1388. mPropagateChanges = aPropagateChanges;
  1389. return NS_OK;
  1390. }
  1391. ////////////////////////////////////////////////////////////////////////
  1392. // nsIRDFPurgeableDataSource methods
  1393. NS_IMETHODIMP
  1394. InMemoryDataSource::Mark(nsIRDFResource* aSource,
  1395. nsIRDFResource* aProperty,
  1396. nsIRDFNode* aTarget,
  1397. bool aTruthValue,
  1398. bool* aDidMark)
  1399. {
  1400. NS_PRECONDITION(aSource != nullptr, "null ptr");
  1401. if (! aSource)
  1402. return NS_ERROR_NULL_POINTER;
  1403. NS_PRECONDITION(aProperty != nullptr, "null ptr");
  1404. if (! aProperty)
  1405. return NS_ERROR_NULL_POINTER;
  1406. NS_PRECONDITION(aTarget != nullptr, "null ptr");
  1407. if (! aTarget)
  1408. return NS_ERROR_NULL_POINTER;
  1409. Assertion *as = GetForwardArcs(aSource);
  1410. if (as && as->mHashEntry) {
  1411. PLDHashEntryHdr* hdr = as->u.hash.mPropertyHash->Search(aProperty);
  1412. Assertion* val = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
  1413. while (val) {
  1414. if ((val->u.as.mTarget == aTarget) &&
  1415. (aTruthValue == (val->u.as.mTruthValue))) {
  1416. // found it! so mark it.
  1417. as->Mark();
  1418. *aDidMark = true;
  1419. LogOperation("MARK", aSource, aProperty, aTarget, aTruthValue);
  1420. return NS_OK;
  1421. }
  1422. val = val->mNext;
  1423. }
  1424. }
  1425. else for (; as != nullptr; as = as->mNext) {
  1426. // check target first as its most unique
  1427. if (aTarget != as->u.as.mTarget)
  1428. continue;
  1429. if (aProperty != as->u.as.mProperty)
  1430. continue;
  1431. if (aTruthValue != (as->u.as.mTruthValue))
  1432. continue;
  1433. // found it! so mark it.
  1434. as->Mark();
  1435. *aDidMark = true;
  1436. LogOperation("MARK", aSource, aProperty, aTarget, aTruthValue);
  1437. return NS_OK;
  1438. }
  1439. // If we get here, we couldn't find the assertion
  1440. *aDidMark = false;
  1441. return NS_OK;
  1442. }
  1443. NS_IMETHODIMP
  1444. InMemoryDataSource::Sweep()
  1445. {
  1446. SweepInfo info = { nullptr, &mReverseArcs };
  1447. // Remove all the assertions, but don't notify anyone.
  1448. SweepForwardArcsEntries(&mForwardArcs, &info);
  1449. // Now do the notification.
  1450. Assertion* as = info.mUnassertList;
  1451. while (as) {
  1452. LogOperation("SWEEP", as->mSource, as->u.as.mProperty, as->u.as.mTarget, as->u.as.mTruthValue);
  1453. if (!(as->mHashEntry))
  1454. {
  1455. for (int32_t i = int32_t(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
  1456. nsIRDFObserver* obs = mObservers[i];
  1457. // XXXbz other loops over mObservers null-check |obs| here!
  1458. obs->OnUnassert(this, as->mSource, as->u.as.mProperty, as->u.as.mTarget);
  1459. // XXX ignore return value?
  1460. }
  1461. }
  1462. Assertion* doomed = as;
  1463. as = as->mNext;
  1464. // Unlink, and release the datasource's reference
  1465. doomed->mNext = doomed->u.as.mInvNext = nullptr;
  1466. doomed->Release();
  1467. }
  1468. return NS_OK;
  1469. }
  1470. void
  1471. InMemoryDataSource::SweepForwardArcsEntries(PLDHashTable* aTable,
  1472. SweepInfo* aInfo)
  1473. {
  1474. for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
  1475. auto entry = static_cast<Entry*>(iter.Get());
  1476. Assertion* as = entry->mAssertions;
  1477. if (as && (as->mHashEntry)) {
  1478. // Stuff in sub-hashes must be swept recursively (max depth: 1)
  1479. SweepForwardArcsEntries(as->u.hash.mPropertyHash, aInfo);
  1480. // If the sub-hash is now empty, clean it up.
  1481. if (!as->u.hash.mPropertyHash->EntryCount()) {
  1482. as->Release();
  1483. iter.Remove();
  1484. }
  1485. continue;
  1486. }
  1487. Assertion* prev = nullptr;
  1488. while (as) {
  1489. if (as->IsMarked()) {
  1490. prev = as;
  1491. as->Unmark();
  1492. as = as->mNext;
  1493. }
  1494. else {
  1495. // remove from the list of assertions in the datasource
  1496. Assertion* next = as->mNext;
  1497. if (prev) {
  1498. prev->mNext = next;
  1499. }
  1500. else {
  1501. // it's the first one. update the hashtable entry.
  1502. entry->mAssertions = next;
  1503. }
  1504. // remove from the reverse arcs
  1505. PLDHashEntryHdr* hdr =
  1506. aInfo->mReverseArcs->Search(as->u.as.mTarget);
  1507. NS_ASSERTION(hdr, "no assertion in reverse arcs");
  1508. Entry* rentry = static_cast<Entry*>(hdr);
  1509. Assertion* ras = rentry->mAssertions;
  1510. Assertion* rprev = nullptr;
  1511. while (ras) {
  1512. if (ras == as) {
  1513. if (rprev) {
  1514. rprev->u.as.mInvNext = ras->u.as.mInvNext;
  1515. }
  1516. else {
  1517. // it's the first one. update the hashtable entry.
  1518. rentry->mAssertions = ras->u.as.mInvNext;
  1519. }
  1520. as->u.as.mInvNext = nullptr; // for my sanity.
  1521. break;
  1522. }
  1523. rprev = ras;
  1524. ras = ras->u.as.mInvNext;
  1525. }
  1526. // Wow, it was the _only_ one. Unhash it.
  1527. if (! rentry->mAssertions) {
  1528. aInfo->mReverseArcs->RawRemove(hdr);
  1529. }
  1530. // add to the list of assertions to unassert
  1531. as->mNext = aInfo->mUnassertList;
  1532. aInfo->mUnassertList = as;
  1533. // Advance to the next assertion
  1534. as = next;
  1535. }
  1536. }
  1537. // if no more assertions exist for this resource, then unhash it.
  1538. if (! entry->mAssertions) {
  1539. iter.Remove();
  1540. }
  1541. }
  1542. }
  1543. ////////////////////////////////////////////////////////////////////////
  1544. // rdfIDataSource methods
  1545. NS_IMETHODIMP
  1546. InMemoryDataSource::VisitAllSubjects(rdfITripleVisitor *aVisitor)
  1547. {
  1548. // Lock datasource against writes
  1549. ++mReadCount;
  1550. // Enumerate all of our entries.
  1551. nsresult rv = NS_OK;
  1552. for (auto iter = mForwardArcs.Iter(); !iter.Done(); iter.Next()) {
  1553. auto entry = static_cast<Entry*>(iter.Get());
  1554. nsresult rv2;
  1555. nsCOMPtr<nsIRDFNode> subject = do_QueryInterface(entry->mNode, &rv2);
  1556. if (NS_FAILED(rv2)) {
  1557. NS_WARNING("QI to nsIRDFNode failed");
  1558. continue;
  1559. }
  1560. rv = aVisitor->Visit(subject, nullptr, nullptr, true);
  1561. if (NS_FAILED(rv) || rv == NS_RDF_STOP_VISIT) {
  1562. break;
  1563. }
  1564. }
  1565. // Unlock datasource
  1566. --mReadCount;
  1567. return rv;
  1568. }
  1569. NS_IMETHODIMP
  1570. InMemoryDataSource::VisitAllTriples(rdfITripleVisitor *aVisitor)
  1571. {
  1572. // Lock datasource against writes
  1573. ++mReadCount;
  1574. // Enumerate all of our entries.
  1575. nsresult rv = NS_OK;
  1576. for (auto iter = mForwardArcs.Iter(); !iter.Done(); iter.Next()) {
  1577. auto entry = static_cast<Entry*>(iter.Get());
  1578. nsresult rv2;
  1579. nsCOMPtr<nsIRDFNode> subject = do_QueryInterface(entry->mNode, &rv2);
  1580. if (NS_FAILED(rv2)) {
  1581. NS_WARNING("QI to nsIRDFNode failed");
  1582. } else if (entry->mAssertions->mHashEntry) {
  1583. for (auto iter = entry->mAssertions->u.hash.mPropertyHash->Iter();
  1584. !iter.Done();
  1585. iter.Next()) {
  1586. auto entry = static_cast<Entry*>(iter.Get());
  1587. Assertion* assertion = entry->mAssertions;
  1588. while (assertion) {
  1589. NS_ASSERTION(!assertion->mHashEntry, "shouldn't have to hashes");
  1590. rv = aVisitor->Visit(subject, assertion->u.as.mProperty,
  1591. assertion->u.as.mTarget,
  1592. assertion->u.as.mTruthValue);
  1593. if (NS_FAILED(rv)) {
  1594. goto end;
  1595. }
  1596. if (rv == NS_RDF_STOP_VISIT) {
  1597. goto inner_end;
  1598. }
  1599. assertion = assertion->mNext;
  1600. }
  1601. }
  1602. } else {
  1603. Assertion* assertion = entry->mAssertions;
  1604. while (assertion) {
  1605. NS_ASSERTION(!assertion->mHashEntry, "shouldn't have to hashes");
  1606. rv = aVisitor->Visit(subject, assertion->u.as.mProperty,
  1607. assertion->u.as.mTarget,
  1608. assertion->u.as.mTruthValue);
  1609. if (NS_FAILED(rv) || rv == NS_RDF_STOP_VISIT) {
  1610. goto end;
  1611. }
  1612. assertion = assertion->mNext;
  1613. }
  1614. }
  1615. inner_end:
  1616. (void) 0;
  1617. }
  1618. end:
  1619. // Unlock datasource
  1620. --mReadCount;
  1621. return rv;
  1622. }
  1623. ////////////////////////////////////////////////////////////////////////