| OLD | NEW |
| 1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
| 6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
| 7 #include "base/path_service.h" | 7 #include "base/path_service.h" |
| 8 #include "base/platform_thread.h" | 8 #include "base/platform_thread.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/thread.h" |
| 10 #include "net/base/io_buffer.h" | 11 #include "net/base/io_buffer.h" |
| 11 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
| 12 #include "net/base/test_completion_callback.h" | 13 #include "net/base/test_completion_callback.h" |
| 13 #include "net/disk_cache/backend_impl.h" | 14 #include "net/disk_cache/backend_impl.h" |
| 14 #include "net/disk_cache/disk_cache_test_base.h" | 15 #include "net/disk_cache/disk_cache_test_base.h" |
| 15 #include "net/disk_cache/disk_cache_test_util.h" | 16 #include "net/disk_cache/disk_cache_test_util.h" |
| 16 #include "net/disk_cache/histogram_macros.h" | 17 #include "net/disk_cache/histogram_macros.h" |
| 17 #include "net/disk_cache/mapped_file.h" | 18 #include "net/disk_cache/mapped_file.h" |
| 19 #include "net/disk_cache/mem_backend_impl.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 21 |
| 20 using base::Time; | 22 using base::Time; |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 24 // Copies a set of cache files from the data folder to the test folder. | 26 // Copies a set of cache files from the data folder to the test folder. |
| 25 bool CopyTestCache(const std::wstring& name) { | 27 bool CopyTestCache(const std::wstring& name) { |
| 26 FilePath path; | 28 FilePath path; |
| 27 PathService::Get(base::DIR_SOURCE_ROOT, &path); | 29 PathService::Get(base::DIR_SOURCE_ROOT, &path); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 TEST_F(DiskCacheBackendTest, NewEvictionKeying) { | 182 TEST_F(DiskCacheBackendTest, NewEvictionKeying) { |
| 181 SetNewEviction(); | 183 SetNewEviction(); |
| 182 BackendKeying(); | 184 BackendKeying(); |
| 183 } | 185 } |
| 184 | 186 |
| 185 TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) { | 187 TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) { |
| 186 SetMemoryOnlyMode(); | 188 SetMemoryOnlyMode(); |
| 187 BackendKeying(); | 189 BackendKeying(); |
| 188 } | 190 } |
| 189 | 191 |
| 192 TEST_F(DiskCacheTest, CreateBackend) { |
| 193 TestCompletionCallback cb; |
| 194 |
| 195 { |
| 196 FilePath path = GetCacheFilePath(); |
| 197 ASSERT_TRUE(DeleteCache(path)); |
| 198 base::Thread cache_thread("CacheThread"); |
| 199 ASSERT_TRUE(cache_thread.StartWithOptions( |
| 200 base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
| 201 |
| 202 // Test the private factory methods. |
| 203 disk_cache::Backend* cache = NULL; |
| 204 int rv = disk_cache::BackendImpl::CreateBackend( |
| 205 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, |
| 206 cache_thread.message_loop_proxy(), &cache, &cb); |
| 207 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 208 ASSERT_TRUE(cache); |
| 209 delete cache; |
| 210 |
| 211 cache = disk_cache::MemBackendImpl::CreateBackend(0); |
| 212 ASSERT_TRUE(cache); |
| 213 delete cache; |
| 214 cache = NULL; |
| 215 |
| 216 // Now test the public API. |
| 217 rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false, |
| 218 cache_thread.message_loop_proxy(), |
| 219 &cache, &cb); |
| 220 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 221 ASSERT_TRUE(cache); |
| 222 delete cache; |
| 223 cache = NULL; |
| 224 |
| 225 rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE, FilePath(), 0, false, |
| 226 NULL, &cache, &cb); |
| 227 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 228 ASSERT_TRUE(cache); |
| 229 delete cache; |
| 230 } |
| 231 |
| 232 MessageLoop::current()->RunAllPending(); |
| 233 } |
| 234 |
| 190 TEST_F(DiskCacheBackendTest, ExternalFiles) { | 235 TEST_F(DiskCacheBackendTest, ExternalFiles) { |
| 191 InitCache(); | 236 InitCache(); |
| 192 // First, lets create a file on the folder. | 237 // First, lets create a file on the folder. |
| 193 FilePath filename = GetCacheFilePath().AppendASCII("f_000001"); | 238 FilePath filename = GetCacheFilePath().AppendASCII("f_000001"); |
| 194 | 239 |
| 195 const int kSize = 50; | 240 const int kSize = 50; |
| 196 scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize); | 241 scoped_refptr<net::IOBuffer> buffer1 = new net::IOBuffer(kSize); |
| 197 CacheTestFillBuffer(buffer1->data(), kSize, false); | 242 CacheTestFillBuffer(buffer1->data(), kSize, false); |
| 198 ASSERT_EQ(kSize, file_util::WriteFile(filename, buffer1->data(), kSize)); | 243 ASSERT_EQ(kSize, file_util::WriteFile(filename, buffer1->data(), kSize)); |
| 199 | 244 |
| 200 // Now let's create a file with the cache. | 245 // Now let's create a file with the cache. |
| 201 disk_cache::Entry* entry; | 246 disk_cache::Entry* entry; |
| 202 ASSERT_EQ(net::OK, CreateEntry("key", &entry)); | 247 ASSERT_EQ(net::OK, CreateEntry("key", &entry)); |
| 203 ASSERT_EQ(0, entry->WriteData(0, 20000, buffer1, 0, NULL, false)); | 248 ASSERT_EQ(0, entry->WriteData(0, 20000, buffer1, 0, NULL, false)); |
| 204 entry->Close(); | 249 entry->Close(); |
| 205 | 250 |
| 206 // And verify that the first file is still there. | 251 // And verify that the first file is still there. |
| 207 scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize); | 252 scoped_refptr<net::IOBuffer> buffer2 = new net::IOBuffer(kSize); |
| 208 ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize)); | 253 ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize)); |
| 209 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); | 254 EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize)); |
| 210 } | 255 } |
| 211 | 256 |
| 212 TEST_F(DiskCacheTest, ShutdownWithPendingIO) { | 257 TEST_F(DiskCacheTest, ShutdownWithPendingIO) { |
| 213 TestCompletionCallback callback; | 258 TestCompletionCallback callback; |
| 214 | 259 |
| 215 { | 260 { |
| 216 FilePath path = GetCacheFilePath(); | 261 FilePath path = GetCacheFilePath(); |
| 217 ASSERT_TRUE(DeleteCache(path)); | 262 ASSERT_TRUE(DeleteCache(path)); |
| 263 base::Thread cache_thread("CacheThread"); |
| 264 ASSERT_TRUE(cache_thread.StartWithOptions( |
| 265 base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
| 218 | 266 |
| 219 disk_cache::Backend* cache = | 267 disk_cache::Backend* cache; |
| 220 disk_cache::CreateCacheBackend(path, false, 0, net::DISK_CACHE); | 268 int rv = disk_cache::BackendImpl::CreateBackend( |
| 269 path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, |
| 270 cache_thread.message_loop_proxy(), &cache, &callback); |
| 271 ASSERT_EQ(net::OK, callback.GetResult(rv)); |
| 221 | 272 |
| 222 disk_cache::Entry* entry; | 273 disk_cache::Entry* entry; |
| 223 ASSERT_TRUE(cache->CreateEntry("some key", &entry)); | 274 rv = cache->CreateEntry("some key", &entry, &callback); |
| 275 ASSERT_EQ(net::OK, callback.GetResult(rv)); |
| 224 | 276 |
| 225 const int kSize = 25000; | 277 const int kSize = 25000; |
| 226 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); | 278 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); |
| 227 CacheTestFillBuffer(buffer->data(), kSize, false); | 279 CacheTestFillBuffer(buffer->data(), kSize, false); |
| 228 | 280 |
| 229 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { | 281 for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) { |
| 230 int rv = entry->WriteData(0, i, buffer, kSize, &callback, false); | 282 int rv = entry->WriteData(0, i, buffer, kSize, &callback, false); |
| 231 if (rv == net::ERR_IO_PENDING) | 283 if (rv == net::ERR_IO_PENDING) |
| 232 break; | 284 break; |
| 233 EXPECT_EQ(kSize, rv); | 285 EXPECT_EQ(kSize, rv); |
| 234 } | 286 } |
| 235 | 287 |
| 236 entry->Close(); | 288 entry->Close(); |
| 237 | 289 |
| 238 // The cache destructor will see one pending operation here. | 290 // The cache destructor will see one pending operation here. |
| 239 delete cache; | 291 delete cache; |
| 240 } | 292 } |
| 241 | 293 |
| 242 MessageLoop::current()->RunAllPending(); | 294 MessageLoop::current()->RunAllPending(); |
| 243 } | 295 } |
| 244 | 296 |
| 245 TEST_F(DiskCacheTest, TruncatedIndex) { | 297 TEST_F(DiskCacheTest, TruncatedIndex) { |
| 246 FilePath path = GetCacheFilePath(); | 298 FilePath path = GetCacheFilePath(); |
| 247 ASSERT_TRUE(DeleteCache(path)); | 299 ASSERT_TRUE(DeleteCache(path)); |
| 248 FilePath index = path.AppendASCII("index"); | 300 FilePath index = path.AppendASCII("index"); |
| 249 ASSERT_EQ(5, file_util::WriteFile(index, "hello", 5)); | 301 ASSERT_EQ(5, file_util::WriteFile(index, "hello", 5)); |
| 250 scoped_ptr<disk_cache::Backend> backend; | 302 |
| 251 backend.reset(disk_cache::BackendImpl::CreateBackend(path, false, 0, | 303 base::Thread cache_thread("CacheThread"); |
| 252 net::DISK_CACHE, | 304 ASSERT_TRUE(cache_thread.StartWithOptions( |
| 253 disk_cache::kNone)); | 305 base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
| 254 ASSERT_TRUE(backend.get() == NULL); | 306 TestCompletionCallback cb; |
| 307 |
| 308 disk_cache::Backend* backend = NULL; |
| 309 int rv = disk_cache::BackendImpl::CreateBackend( |
| 310 path, false, 0, net::DISK_CACHE, disk_cache::kNone, |
| 311 cache_thread.message_loop_proxy(), &backend, &cb); |
| 312 ASSERT_NE(net::OK, cb.GetResult(rv)); |
| 313 |
| 314 ASSERT_TRUE(backend == NULL); |
| 315 delete backend; |
| 255 } | 316 } |
| 256 | 317 |
| 257 void DiskCacheBackendTest::BackendSetSize() { | 318 void DiskCacheBackendTest::BackendSetSize() { |
| 258 SetDirectMode(); | 319 SetDirectMode(); |
| 259 const int cache_size = 0x10000; // 64 kB | 320 const int cache_size = 0x10000; // 64 kB |
| 260 SetMaxSize(cache_size); | 321 SetMaxSize(cache_size); |
| 261 InitCache(); | 322 InitCache(); |
| 262 | 323 |
| 263 std::string first("some key"); | 324 std::string first("some key"); |
| 264 std::string second("something else"); | 325 std::string second("something else"); |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 TEST_F(DiskCacheBackendTest, RecoverRemove) { | 1142 TEST_F(DiskCacheBackendTest, RecoverRemove) { |
| 1082 BackendRecoverRemove(); | 1143 BackendRecoverRemove(); |
| 1083 } | 1144 } |
| 1084 | 1145 |
| 1085 TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) { | 1146 TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) { |
| 1086 SetNewEviction(); | 1147 SetNewEviction(); |
| 1087 BackendRecoverRemove(); | 1148 BackendRecoverRemove(); |
| 1088 } | 1149 } |
| 1089 | 1150 |
| 1090 // Tests dealing with cache files that cannot be recovered. | 1151 // Tests dealing with cache files that cannot be recovered. |
| 1091 TEST_F(DiskCacheTest, Backend_DeleteOld) { | 1152 TEST_F(DiskCacheTest, DeleteOld) { |
| 1092 ASSERT_TRUE(CopyTestCache(L"wrong_version")); | 1153 ASSERT_TRUE(CopyTestCache(L"wrong_version")); |
| 1093 FilePath path = GetCacheFilePath(); | 1154 FilePath path = GetCacheFilePath(); |
| 1094 scoped_ptr<disk_cache::Backend> cache; | 1155 base::Thread cache_thread("CacheThread"); |
| 1095 cache.reset(disk_cache::CreateCacheBackend(path, true, 0, net::DISK_CACHE)); | 1156 ASSERT_TRUE(cache_thread.StartWithOptions( |
| 1157 base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
| 1158 TestCompletionCallback cb; |
| 1159 |
| 1160 disk_cache::Backend* cache; |
| 1161 int rv = disk_cache::BackendImpl::CreateBackend( |
| 1162 path, true, 0, net::DISK_CACHE, disk_cache::kNoRandom, |
| 1163 cache_thread.message_loop_proxy(), &cache, &cb); |
| 1164 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 1096 | 1165 |
| 1097 MessageLoopHelper helper; | 1166 MessageLoopHelper helper; |
| 1098 | 1167 |
| 1099 ASSERT_TRUE(NULL != cache.get()); | 1168 ASSERT_TRUE(NULL != cache); |
| 1100 ASSERT_EQ(0, cache->GetEntryCount()); | 1169 ASSERT_EQ(0, cache->GetEntryCount()); |
| 1101 | 1170 |
| 1102 // Wait for a callback that never comes... about 2 secs :). The message loop | 1171 delete cache; |
| 1103 // has to run to allow destruction of the cleaner thread. | |
| 1104 helper.WaitUntilCacheIoFinished(1); | |
| 1105 } | 1172 } |
| 1106 | 1173 |
| 1107 // We want to be able to deal with messed up entries on disk. | 1174 // We want to be able to deal with messed up entries on disk. |
| 1108 void DiskCacheBackendTest::BackendInvalidEntry2() { | 1175 void DiskCacheBackendTest::BackendInvalidEntry2() { |
| 1109 ASSERT_TRUE(CopyTestCache(L"bad_entry")); | 1176 ASSERT_TRUE(CopyTestCache(L"bad_entry")); |
| 1110 DisableFirstCleanup(); | 1177 DisableFirstCleanup(); |
| 1111 InitCache(); | 1178 InitCache(); |
| 1112 | 1179 |
| 1113 disk_cache::Entry *entry1, *entry2; | 1180 disk_cache::Entry *entry1, *entry2; |
| 1114 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); | 1181 ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1)); |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1436 InitCache(); | 1503 InitCache(); |
| 1437 BackendDisable4(); | 1504 BackendDisable4(); |
| 1438 } | 1505 } |
| 1439 | 1506 |
| 1440 TEST_F(DiskCacheTest, Backend_UsageStats) { | 1507 TEST_F(DiskCacheTest, Backend_UsageStats) { |
| 1441 MessageLoopHelper helper; | 1508 MessageLoopHelper helper; |
| 1442 | 1509 |
| 1443 FilePath path = GetCacheFilePath(); | 1510 FilePath path = GetCacheFilePath(); |
| 1444 ASSERT_TRUE(DeleteCache(path)); | 1511 ASSERT_TRUE(DeleteCache(path)); |
| 1445 scoped_ptr<disk_cache::BackendImpl> cache; | 1512 scoped_ptr<disk_cache::BackendImpl> cache; |
| 1446 cache.reset(new disk_cache::BackendImpl(path)); | 1513 cache.reset(new disk_cache::BackendImpl( |
| 1514 path, base::MessageLoopProxy::CreateForCurrentThread())); |
| 1447 ASSERT_TRUE(NULL != cache.get()); | 1515 ASSERT_TRUE(NULL != cache.get()); |
| 1448 cache->SetUnitTestMode(); | 1516 cache->SetUnitTestMode(); |
| 1449 ASSERT_TRUE(cache->Init()); | 1517 ASSERT_TRUE(cache->Init()); |
| 1450 | 1518 |
| 1451 // Wait for a callback that never comes... about 2 secs :). The message loop | 1519 // Wait for a callback that never comes... about 2 secs :). The message loop |
| 1452 // has to run to allow invocation of the usage timer. | 1520 // has to run to allow invocation of the usage timer. |
| 1453 helper.WaitUntilCacheIoFinished(1); | 1521 helper.WaitUntilCacheIoFinished(1); |
| 1454 } | 1522 } |
| 1455 | 1523 |
| 1456 void DiskCacheBackendTest::BackendDoomAll() { | 1524 void DiskCacheBackendTest::BackendDoomAll() { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1539 InitCache(); | 1607 InitCache(); |
| 1540 BackendDoomAll2(); | 1608 BackendDoomAll2(); |
| 1541 } | 1609 } |
| 1542 | 1610 |
| 1543 // We should be able to create the same entry on multiple simultaneous instances | 1611 // We should be able to create the same entry on multiple simultaneous instances |
| 1544 // of the cache. | 1612 // of the cache. |
| 1545 TEST_F(DiskCacheTest, MultipleInstances) { | 1613 TEST_F(DiskCacheTest, MultipleInstances) { |
| 1546 ScopedTestCache store1; | 1614 ScopedTestCache store1; |
| 1547 ScopedTestCache store2("cache_test2"); | 1615 ScopedTestCache store2("cache_test2"); |
| 1548 ScopedTestCache store3("cache_test3"); | 1616 ScopedTestCache store3("cache_test3"); |
| 1617 base::Thread cache_thread("CacheThread"); |
| 1618 ASSERT_TRUE(cache_thread.StartWithOptions( |
| 1619 base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
| 1620 TestCompletionCallback cb; |
| 1549 | 1621 |
| 1550 const int kNumberOfCaches = 2; | 1622 const int kNumberOfCaches = 2; |
| 1551 scoped_ptr<disk_cache::Backend> cache[kNumberOfCaches]; | 1623 disk_cache::Backend* cache[kNumberOfCaches]; |
| 1552 | 1624 |
| 1553 cache[0].reset(disk_cache::CreateCacheBackend(store1.path(), false, 0, | 1625 int rv = disk_cache::BackendImpl::CreateBackend( |
| 1554 net::DISK_CACHE)); | 1626 store1.path(), false, 0, net::DISK_CACHE, disk_cache::kNone, |
| 1555 cache[1].reset(disk_cache::CreateCacheBackend(store2.path(), false, 0, | 1627 cache_thread.message_loop_proxy(), &cache[0], &cb); |
| 1556 net::MEDIA_CACHE)); | 1628 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 1629 rv = disk_cache::BackendImpl::CreateBackend( |
| 1630 store2.path(), false, 0, net::MEDIA_CACHE, disk_cache::kNone, |
| 1631 cache_thread.message_loop_proxy(), &cache[1], &cb); |
| 1632 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 1557 | 1633 |
| 1558 ASSERT_TRUE(cache[0].get() != NULL && cache[1].get() != NULL); | 1634 ASSERT_TRUE(cache[0] != NULL && cache[1] != NULL); |
| 1559 | 1635 |
| 1560 std::string key("the first key"); | 1636 std::string key("the first key"); |
| 1561 disk_cache::Entry* entry; | 1637 disk_cache::Entry* entry; |
| 1562 for (int i = 0; i < kNumberOfCaches; i++) { | 1638 for (int i = 0; i < kNumberOfCaches; i++) { |
| 1563 ASSERT_TRUE(cache[i]->CreateEntry(key, &entry)); | 1639 rv = cache[i]->CreateEntry(key, &entry, &cb); |
| 1640 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 1564 entry->Close(); | 1641 entry->Close(); |
| 1565 } | 1642 } |
| 1643 delete cache[0]; |
| 1644 delete cache[1]; |
| 1566 } | 1645 } |
| 1567 | 1646 |
| 1568 // Test the six regions of the curve that determines the max cache size. | 1647 // Test the six regions of the curve that determines the max cache size. |
| 1569 TEST_F(DiskCacheTest, AutomaticMaxSize) { | 1648 TEST_F(DiskCacheTest, AutomaticMaxSize) { |
| 1570 const int kDefaultSize = 80 * 1024 * 1024; | 1649 const int kDefaultSize = 80 * 1024 * 1024; |
| 1571 int64 large_size = kDefaultSize; | 1650 int64 large_size = kDefaultSize; |
| 1572 int64 largest_size = kint32max; | 1651 int64 largest_size = kint32max; |
| 1573 | 1652 |
| 1574 // Region 1: expected = available * 0.8 | 1653 // Region 1: expected = available * 0.8 |
| 1575 EXPECT_EQ((kDefaultSize - 1) * 8 / 10, | 1654 EXPECT_EQ((kDefaultSize - 1) * 8 / 10, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1618 // another. | 1697 // another. |
| 1619 TEST_F(DiskCacheBackendTest, Histograms) { | 1698 TEST_F(DiskCacheBackendTest, Histograms) { |
| 1620 SetDirectMode(); | 1699 SetDirectMode(); |
| 1621 InitCache(); | 1700 InitCache(); |
| 1622 disk_cache::BackendImpl* backend_ = cache_impl_; // Needed be the macro. | 1701 disk_cache::BackendImpl* backend_ = cache_impl_; // Needed be the macro. |
| 1623 | 1702 |
| 1624 for (int i = 1; i < 3; i++) { | 1703 for (int i = 1; i < 3; i++) { |
| 1625 CACHE_UMA(HOURS, "FillupTime", i, 28); | 1704 CACHE_UMA(HOURS, "FillupTime", i, 28); |
| 1626 } | 1705 } |
| 1627 } | 1706 } |
| OLD | NEW |