Skip to content

Commit 079dfdf

Browse files
committed
Bug 37315344 - [37264961->14.1.2.0.1] CQC constructor with fCacheValues of false should configure lite mapListener (main.net->net-v14.1.2)
Validated with shelf build in Jenkins Coh-NET-14.1.2.0, #3 [git-p4: depot-paths = "//dev/release.net/coherence-net-v14.1.2.0/": change = 113010]
1 parent babc2fc commit 079dfdf

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;
@@ -117,6 +117,112 @@ public void TestEvents()
117117
Assert.AreEqual(SOME_DATA, listener.GetActualTotal());
118118
}
119119

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

266372

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

269498
/**

0 commit comments

Comments
 (0)