Skip to content

Commit b971035

Browse files
committed
Bug 37315342 - [37264961->14.1.1.0.20] CQC constructor with fCacheValues of false should configure lite mapListener (NET-v 14.1.2->NET-v14.1.1)
Validated running shelf build of Coh-NET-14.1.1.0, #992. [git-p4: depot-paths = "//dev/release.net/coherence-net-v14.1.1.0/": change = 113012]
1 parent 603ce21 commit b971035

File tree

3 files changed

+443
-10
lines changed

3 files changed

+443
-10
lines changed

src/Coherence/Net/Cache/ContinuousQueryCache.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2023, Oracle and/or its affiliates.
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
33
*
44
* Licensed under the Universal Permissive License v 1.0 as shown at
55
* https://oss.oracle.com/licenses/upl.
@@ -134,11 +134,15 @@ public virtual bool IsCacheValues
134134
/// <b>true</b> if this object caches values locally, and false if it
135135
/// relies on the underlying <b>INamedCache</b>.
136136
/// </value>
137+
/// <p>
138+
/// Note that a non-null <see cref="Transformer"/> or a <b>isLite</b> parameter of <b>false</b>
139+
/// passed to <see cref="IObservableCache.AddCacheListener(ICacheListener, IFilter, bool)"/> forces
140+
/// <b>CacheValues</b> to always be <b>true</b>.</p>
137141
public virtual bool CacheValues
138142
{
139143
get
140144
{
141-
return m_cacheValues || IsObserved;
145+
return m_cacheValues || IsObserved || Transformer != null;
142146
}
143147
set
144148
{
@@ -512,6 +516,7 @@ public ContinuousQueryCache(INamedCache cache, IFilter filter, IValueExtractor t
512516
/// <param name="isCacheValues">
513517
/// Pass <b>true</b> to cache both the keys and values of the
514518
/// materialized view locally, or <b>false</b> to only cache the keys.
519+
/// Override of <b>false</b> described in <see cref="CacheValues"/>.
515520
/// </param>
516521
public ContinuousQueryCache(INamedCache cache, IFilter filter, bool isCacheValues)
517522
: this(() => cache, filter, isCacheValues, null, null)
@@ -562,6 +567,7 @@ public ContinuousQueryCache(INamedCache cache, IFilter filter, ICacheListener li
562567
/// <param name="cacheValues">
563568
/// Pass <b>true</b> to cache both the keys and values of the
564569
/// materialized view locally, or <b>false</b> to only cache the keys.
570+
/// Override of <b>false</b> described in <b>CacheValues</b>.
565571
/// </param>
566572
/// <param name="cacheListener">
567573
/// The optional <b>ICacheListener</b> that will receive all events
@@ -571,7 +577,11 @@ public ContinuousQueryCache(INamedCache cache, IFilter filter, ICacheListener li
571577
/// The transformer that should be used to convert values from the
572578
/// underlying cache before storing them locally
573579
/// </param>
574-
public ContinuousQueryCache(Func<INamedCache> supplierCache, IFilter filter, bool cacheValues,
580+
/// <p>
581+
/// Note when parameter <b>cacheValues</b> is <b>false</b>, it is inferred that provided parameter
582+
/// <b>cacheListener</b> is a lite listener as described by <b>isLite</b> parameter of
583+
/// <see cref="IObservableCache.AddCacheListener(ICacheListener, IFilter, bool)"/>.</p>
584+
public ContinuousQueryCache(Func<INamedCache> supplierCache, IFilter filter, bool cacheValues,
575585
ICacheListener cacheListener, IValueExtractor transformer)
576586
{
577587
INamedCache cache = supplierCache();
@@ -601,6 +611,9 @@ public ContinuousQueryCache(Func<INamedCache> supplierCache, IFilter filter, boo
601611
m_state = CacheState.Disconnected;
602612
m_cacheListener = cacheListener;
603613

614+
// initialize IsObserved on whether a standard (non-lite) listener passed in at construction time
615+
m_hasListeners = cacheListener != null && cacheValues;
616+
604617
// by including information about the underlying cache, filter and
605618
// transformer, the resulting cache name is convoluted but extremely
606619
// helpful for tasks such as debugging
@@ -2596,13 +2609,13 @@ protected IObservableCache EnsureInternalCache()
25962609
if (m_cacheLocal == null)
25972610
{
25982611
IObservableCache cacheLocal = m_cacheLocal = InstantiateInternalCache();
2599-
ICacheListener cacheListener = m_cacheListener;
2612+
ICacheListener cacheListener = m_cacheListener;
2613+
bool isLite = !CacheValues;
26002614
if (cacheListener != null)
26012615
{
26022616
// the initial listener has to hear the initial events
26032617
EnsureEventDispatcher();
2604-
cacheLocal.AddCacheListener(InstantiateEventRouter(cacheListener, false));
2605-
m_hasListeners = true;
2618+
cacheLocal.AddCacheListener(InstantiateEventRouter(cacheListener, isLite), (IFilter) null, isLite);
26062619
}
26072620
}
26082621
return m_cacheLocal;

tests/Coherence.Tests/Net/Cache/CQCProxyTests.cs

Lines changed: 231 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
2-
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
33
*
44
* Licensed under the Universal Permissive License v 1.0 as shown at
5-
* http://oss.oracle.com/licenses/upl.
5+
* https://oss.oracle.com/licenses/upl.
66
*/
77
using System;
88
using System.Collections;
@@ -116,6 +116,112 @@ public void TestEvents()
116116
Assert.AreEqual(SOME_DATA, listener.GetActualTotal());
117117
}
118118

119+
/// <summary>
120+
/// TestEvents with CacheValues of false.
121+
/// </summary>
122+
[Test]
123+
public void TestEventsNoValues()
124+
{
125+
// start the ProxyService on just one cluster node
126+
IInvocationService invocationService = RestartProxy(null);
127+
128+
// put data items into inner cache to generate events
129+
INamedCache testCache = GetCache("proxy-stop-test");
130+
testCache.Clear();
131+
IDictionary dict = new Hashtable();
132+
for (int i = 0; i < SOME_DATA; i++)
133+
{
134+
dict.Add("TestKey" + i, i);
135+
}
136+
testCache.InsertAll(dict);
137+
138+
// create listener for CQC
139+
ValidateLiteListener listener = new ValidateLiteListener(SOME_DATA);
140+
141+
// instantiate the CQC, will start the test running.
142+
ContinuousQueryCache queryCache =
143+
new ContinuousQueryCache(() => testCache, AlwaysFilter.Instance,
144+
false, listener, null);
145+
theCQC = queryCache;
146+
Assert.IsFalse(queryCache.CacheValues);
147+
148+
// instantiate a service listener to receive memberLeft event
149+
fMemberLeft = false;
150+
testCache.CacheService.MemberLeft += new MemberEventHandler(OnMemberLeft);
151+
152+
// allow test time to complete
153+
using (ThreadTimeout t = ThreadTimeout.After(30000))
154+
{
155+
while (listener.GetActualTotal() < SOME_DATA)
156+
{
157+
Blocking.Sleep(250);
158+
}
159+
}
160+
161+
// check listener received the correct number of events.
162+
Assert.AreEqual(SOME_DATA, listener.GetActualTotal());
163+
listener.ResetActualTotal();
164+
165+
// restart proxy
166+
RestartProxy(invocationService);
167+
168+
using (ThreadTimeout t = ThreadTimeout.After(30000))
169+
{
170+
while (!fMemberLeft)
171+
{
172+
Blocking.Sleep(250);
173+
}
174+
}
175+
176+
// ping the CQC to make it realize the cache needs restart
177+
theCQC.Contains("junkstuff");
178+
179+
// allow test time to complete.
180+
using (ThreadTimeout t = ThreadTimeout.After(30000))
181+
{
182+
while (listener.GetActualTotal() < SOME_DATA)
183+
{
184+
Blocking.Sleep(250);
185+
}
186+
}
187+
188+
Assert.AreEqual(SOME_DATA, listener.GetActualTotal());
189+
}
190+
191+
/// <summary>
192+
/// TestEvents with CacheValues of false. After standard listener (non-lite) added, CacheValues overriden to true.
193+
/// </summary>
194+
[Test]
195+
public void TestEventsNoValuesToObservable()
196+
{
197+
// start the ProxyService on just one cluster node
198+
IInvocationService invocationService = RestartProxy(null);
199+
200+
// put data items into inner cache to generate events
201+
INamedCache testCache = GetCache("proxy-stop-test");
202+
testCache.Clear();
203+
IDictionary dict = new Hashtable();
204+
for (int i = 0; i < SOME_DATA; i++)
205+
{
206+
dict.Add("TestKey" + i, i);
207+
}
208+
testCache.InsertAll(dict);
209+
210+
// create listener for CQC
211+
ValidateLiteListener listener = new ValidateLiteListener(SOME_DATA);
212+
213+
// instantiate the CQC, will start the test running.
214+
ContinuousQueryCache queryCache = new ContinuousQueryCache(() => testCache, AlwaysFilter.Instance, false, listener, null);
215+
theCQC = queryCache;
216+
Assert.IsFalse(queryCache.CacheValues);
217+
218+
// add standard (non-lite) listener
219+
TestCQCListener listenerStandard = new TestCQCListener(SOME_DATA);
220+
bool isLite = false;
221+
queryCache.AddCacheListener(listenerStandard, AlwaysFilter.Instance, isLite);
222+
Assert.IsTrue(queryCache.CacheValues);
223+
}
224+
119225
/**
120226
* utility method to stop and restart the proxy.
121227
*/
@@ -263,6 +369,129 @@ public void ResetActualTotal()
263369
}
264370

265371

372+
// ----- data members -----------------------------------------------
373+
374+
/**
375+
* Number of insert events actually received
376+
*/
377+
int m_cActualInserts;
378+
379+
/**
380+
* Number of update events actually received
381+
*/
382+
int m_cActualUpdates;
383+
384+
/**
385+
* Number of delete events actually received
386+
*/
387+
int m_cActualDeletes;
388+
389+
/**
390+
* Number of events listener should receive
391+
*/
392+
int m_cCount;
393+
}
394+
#endregion
395+
396+
// ----- inner class: ValidateLiteListener --------------------------------------
397+
398+
/**
399+
* MapListener that continuously receives events from the cache.
400+
*/
401+
#region Helper class
402+
403+
class ValidateLiteListener : ICacheListener
404+
{
405+
406+
public ValidateLiteListener(int count)
407+
{
408+
m_cCount = count;
409+
m_cActualInserts = 0;
410+
m_cActualUpdates = 0;
411+
m_cActualDeletes = 0;
412+
}
413+
414+
public int Count
415+
{
416+
get { return m_cCount; }
417+
set { m_cCount = value; }
418+
}
419+
420+
/**
421+
* Number of insert events listener actually received.
422+
*
423+
* @return number of event received
424+
*/
425+
public int ActualInserts
426+
{
427+
get { return m_cActualInserts; }
428+
set { m_cActualInserts = value; }
429+
}
430+
431+
/**
432+
* Number of update events listener actually received.
433+
*
434+
* @return number of event received
435+
*/
436+
public int ActualUpdates
437+
{
438+
get { return m_cActualUpdates; }
439+
set { m_cActualUpdates = value; }
440+
}
441+
442+
/**
443+
* Number of delete events listener actually received.
444+
*
445+
* @return number of event received
446+
*/
447+
public int ActualDeletes
448+
{
449+
get { return m_cActualDeletes; }
450+
set { m_cActualDeletes = value; }
451+
}
452+
453+
public void EntryUpdated(CacheEventArgs evt)
454+
{
455+
m_cActualUpdates++;
456+
Assert.AreEqual(evt.NewValue, null);
457+
Assert.AreEqual(evt.OldValue, null);
458+
}
459+
460+
public void EntryInserted(CacheEventArgs evt)
461+
{
462+
m_cActualInserts++;
463+
Assert.AreEqual(evt.NewValue, null);
464+
Assert.AreEqual(evt.OldValue, null);
465+
}
466+
467+
public void EntryDeleted(CacheEventArgs evt)
468+
{
469+
m_cActualDeletes++;
470+
Assert.AreEqual(evt.OldValue, null);
471+
}
472+
473+
/**
474+
* Total number of events listener actually received.
475+
*
476+
* @return number of event received
477+
*/
478+
public int GetActualTotal()
479+
{
480+
return m_cActualInserts+m_cActualUpdates+m_cActualDeletes;
481+
}
482+
483+
/**
484+
* Reset the number of events received.
485+
*
486+
*/
487+
public void ResetActualTotal()
488+
{
489+
m_cActualUpdates = 0;
490+
m_cActualInserts = 0;
491+
m_cActualDeletes = 0;
492+
}
493+
494+
266495
// ----- data members -----------------------------------------------
267496

268497
/**

0 commit comments

Comments
 (0)