| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| namespace Apache.Ignite.Core.Tests.Cache |
| { |
| using System; |
| using System.Collections.Generic; |
| using System.IO; |
| using System.Linq; |
| using System.Threading; |
| using Apache.Ignite.Core.Cache; |
| using Apache.Ignite.Core.Cache.Affinity.Rendezvous; |
| using Apache.Ignite.Core.Cache.Configuration; |
| using Apache.Ignite.Core.Configuration; |
| using NUnit.Framework; |
| |
| /// <summary> |
| /// Tests partition preload API. |
| /// </summary> |
| [Category(TestUtils.CategoryIntensive)] |
| public class PartitionPreloadTest |
| { |
| /** Temp dir for PDS. */ |
| private static readonly string TempDir = PathUtils.GetTempDirectoryName(); |
| |
| /** */ |
| private const string MemoryRegionName = "mem-region"; |
| |
| /** */ |
| private const string PersistenceRegionName = "pds-region"; |
| |
| /** */ |
| private const int GridCount = 3; |
| |
| /** */ |
| private const string MemCacheName = "mem-cache"; |
| |
| /** */ |
| private const string PersistenceCacheName = "pds-cache"; |
| |
| /** */ |
| private const int EntriesCount = 1000; |
| |
| /** */ |
| private static readonly TimeSpan CheckpointFrequency = TimeSpan.FromSeconds(1); |
| |
| /** */ |
| private const string ExpectedErrorMessage = "Operation only applicable to caches with enabled persistence"; |
| |
| /// <summary> |
| /// Tests that preloading partition on client locally returns <code>false</code>. |
| /// </summary> |
| [Test] |
| public void TestLocalPreloadPartitionClient() |
| { |
| var cache = GetClient.GetCache<int, int>(MemCacheName); |
| |
| Assert.IsFalse(cache.LocalPreloadPartition(0)); |
| } |
| |
| /// <summary> |
| /// Preload partitions synchronously. |
| /// </summary> |
| [Test] |
| public void TestPreloadPartition() |
| { |
| PerformPreloadTest(GetGrid(0), GetClient, PreloadMode.Sync); |
| } |
| |
| /// <summary> |
| /// Tests that incorrect usage of API throws exceptions. |
| /// </summary> |
| [Test] |
| public void TestPreloadPartitionInMemoryFail() |
| { |
| var cache = GetClient.GetCache<int, int>(MemCacheName); |
| |
| var ex = Assert.Throws<CacheException>(() => cache.PreloadPartition(0)); |
| |
| Assert.True(ex.Message.Contains(ExpectedErrorMessage), ex.Message); |
| |
| var task = cache.PreloadPartitionAsync(0); |
| |
| ex = Assert.Throws<CacheException>(() => task.WaitResult()); |
| |
| Assert.True(ex.Message.Contains(ExpectedErrorMessage), ex.Message); |
| } |
| |
| /// <summary> |
| /// Preload partitions asynchronously. |
| /// </summary> |
| [Test] |
| public void TestPreloadPartitionAsync() |
| { |
| PerformPreloadTest(GetGrid(0), GetClient, PreloadMode.Async); |
| } |
| |
| /// <summary> |
| /// Preload partitions locally. |
| /// </summary> |
| [Test] |
| public void TestLocalPreloadPartition() |
| { |
| PerformPreloadTest(GetGrid(0), GetClient, PreloadMode.Local); |
| } |
| |
| /// <summary> |
| /// Test set up. |
| /// </summary> |
| [SetUp] |
| public void SetUp() |
| { |
| StartGrids(); |
| } |
| |
| /// <summary> |
| /// Test tear down. |
| /// </summary> |
| [TearDown] |
| public void TearDown() |
| { |
| Ignition.StopAll(true); |
| |
| Directory.Delete(TempDir, true); |
| } |
| |
| /// <summary> |
| /// Starts test grids. |
| /// </summary> |
| private static void StartGrids() |
| { |
| var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) |
| { |
| DataStorageConfiguration = new DataStorageConfiguration |
| { |
| WalMode = WalMode.Fsync, |
| WalSegmentSize = 16 * 1 << 20, // 16 MB. |
| PageSize = 1 << 10, // 1 KB. |
| MetricsEnabled = true, |
| CheckpointFrequency = CheckpointFrequency, |
| DefaultDataRegionConfiguration = new DataRegionConfiguration |
| { |
| Name = PersistenceRegionName, |
| PersistenceEnabled = true, |
| MetricsEnabled = true, |
| MaxSize = 50 * 1 << 20 // 50 MB. |
| }, |
| DataRegionConfigurations = new[] |
| { |
| new DataRegionConfiguration |
| { |
| Name = MemoryRegionName, |
| MetricsEnabled = true, |
| PersistenceEnabled = false, |
| MaxSize = 10 * 1 << 20 // 10 MB. |
| } |
| }, |
| }, |
| WorkDirectory = TempDir, |
| CacheConfiguration = new List<CacheConfiguration> |
| { |
| new CacheConfiguration(MemCacheName) |
| { |
| WriteSynchronizationMode = CacheWriteSynchronizationMode.FullSync, |
| AtomicityMode = CacheAtomicityMode.Transactional, |
| AffinityFunction = new RendezvousAffinityFunction |
| { |
| ExcludeNeighbors = false, |
| Partitions = 32 |
| }, |
| Backups = 1, |
| DataRegionName = MemoryRegionName, |
| }, |
| new CacheConfiguration(PersistenceCacheName) |
| { |
| WriteSynchronizationMode = CacheWriteSynchronizationMode.FullSync, |
| AtomicityMode = CacheAtomicityMode.Transactional, |
| AffinityFunction = new RendezvousAffinityFunction |
| { |
| ExcludeNeighbors = false, |
| Partitions = 32 |
| }, |
| Backups = 1, |
| DataRegionName = PersistenceRegionName |
| } |
| } |
| }; |
| |
| for (int i = 0; i < GridCount; i++) |
| { |
| cfg.IgniteInstanceName = "grid-" + i; |
| cfg.ConsistentId = "grid-" + i; |
| |
| Ignition.Start(cfg); |
| } |
| |
| cfg.IgniteInstanceName = "client"; |
| cfg.ClientMode = true; |
| |
| var client = Ignition.Start(cfg); |
| |
| client.GetCluster().SetActive(true); |
| } |
| |
| private IIgnite GetGrid(int i) |
| { |
| return Ignition.GetIgnite("grid-" + i); |
| } |
| |
| private IIgnite GetClient |
| { |
| get { return Ignition.GetIgnite("client"); } |
| } |
| |
| /// <summary> |
| /// Perform test operations. |
| /// </summary> |
| /// <param name="testNode">Owner of preloaded partition.</param> |
| /// <param name="execNode">Node on which operation will be executed.</param> |
| /// <param name="preloadMode">Preload mode <see cref="PreloadMode"/></param> |
| private void PerformPreloadTest(IIgnite testNode, IIgnite execNode, PreloadMode preloadMode) |
| { |
| int key = TestUtils.GetPrimaryKey(testNode, PersistenceCacheName); |
| var affinity = execNode.GetAffinity(PersistenceCacheName); |
| int preloadPart = affinity.GetPartition(key); |
| |
| using (var streamer = execNode.GetDataStreamer<int, int>(PersistenceCacheName)) |
| { |
| int cnt = EntriesCount; |
| int k = 0; |
| |
| while (cnt > 0) |
| { |
| if (affinity.GetPartition(k) == preloadPart) |
| { |
| streamer.Add(k, k); |
| |
| cnt--; |
| } |
| |
| k++; |
| } |
| } |
| |
| // Wait for checkpoint (wait for doubled CheckpointFrequency interval). |
| Thread.Sleep(CheckpointFrequency.Add(CheckpointFrequency)); |
| |
| switch (preloadMode) |
| { |
| case PreloadMode.Sync: |
| execNode.GetCache<int, int>(PersistenceCacheName).PreloadPartition(preloadPart); |
| |
| break; |
| case PreloadMode.Async: |
| var task = execNode.GetCache<int, int>(PersistenceCacheName).PreloadPartitionAsync(preloadPart); |
| |
| task.WaitResult(); |
| |
| break; |
| case PreloadMode.Local: |
| // In local mode we should load partition from testNode. |
| bool res = testNode.GetCache<int, int>(PersistenceCacheName).LocalPreloadPartition(preloadPart); |
| |
| Assert.IsTrue(res); |
| |
| break; |
| } |
| |
| |
| long pagesRead = testNode.GetDataRegionMetrics(PersistenceRegionName).PagesRead; |
| |
| var entries = testNode.GetCache<int, int>(PersistenceCacheName).GetLocalEntries().ToList(); |
| |
| Assert.AreEqual(entries.Count, EntriesCount); |
| Assert.AreEqual(pagesRead, testNode.GetDataRegionMetrics(PersistenceRegionName).PagesRead); |
| } |
| |
| /** */ |
| enum PreloadMode |
| { |
| /** Preload synchronously. */ |
| Sync, |
| /** Preload asynchronously. */ |
| Async, |
| /** Preload locally. */ |
| Local |
| } |
| } |
| } |