~ubuntu-branches/ubuntu/trusty/ehcache/trusty

« back to all changes in this revision

Viewing changes to src/main/java/net/sf/ehcache/management/sampled/CacheManagerSamplerImpl.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg
  • Date: 2013-05-06 14:53:07 UTC
  • mfrom: (1.1.7) (2.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20130506145307-v5bhw5yu70re00l3
Tags: 2.6.7-1
* Team upload.
* New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 *  Copyright Terracotta, Inc.
 
3
 *
 
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
 
5
 *  you may not use this file except in compliance with the License.
 
6
 *  You may obtain a copy of the License at
 
7
 *
 
8
 *      http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 *  Unless required by applicable law or agreed to in writing, software
 
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
 
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 *  See the License for the specific language governing permissions and
 
14
 *  limitations under the License.
 
15
 */
 
16
package net.sf.ehcache.management.sampled;
 
17
 
 
18
import net.sf.ehcache.Cache;
 
19
import net.sf.ehcache.CacheException;
 
20
import net.sf.ehcache.CacheManager;
 
21
import net.sf.ehcache.Ehcache;
 
22
import net.sf.ehcache.config.CacheWriterConfiguration;
 
23
import net.sf.ehcache.statistics.LiveCacheStatistics;
 
24
import net.sf.ehcache.statistics.sampled.SampledCacheStatistics;
 
25
import net.sf.ehcache.writer.writebehind.WriteBehindManager;
 
26
 
 
27
import java.util.HashMap;
 
28
import java.util.Map;
 
29
 
 
30
/**
 
31
 * An implementation of {@link CacheManagerSampler}
 
32
 *
 
33
 * @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
 
34
 * @author <a href="mailto:byoukste@terracottatech.com">byoukste</a>
 
35
 */
 
36
public class CacheManagerSamplerImpl implements CacheManagerSampler {
 
37
 
 
38
    private final CacheManager cacheManager;
 
39
 
 
40
    /**
 
41
     * Constructor taking the backing {@link CacheManager}
 
42
     *
 
43
     * @param cacheManager to wrap
 
44
     */
 
45
    public CacheManagerSamplerImpl(CacheManager cacheManager) {
 
46
        this.cacheManager = cacheManager;
 
47
    }
 
48
 
 
49
    /**
 
50
     * {@inheritDoc}
 
51
     */
 
52
    public void clearAll() {
 
53
        cacheManager.clearAll();
 
54
    }
 
55
 
 
56
    /**
 
57
     * {@inheritDoc}
 
58
     */
 
59
    public String[] getCacheNames() throws IllegalStateException {
 
60
        return cacheManager.getCacheNames();
 
61
    }
 
62
 
 
63
    /**
 
64
     * {@inheritDoc}
 
65
     */
 
66
    public String getStatus() {
 
67
        return cacheManager.getStatus().toString();
 
68
    }
 
69
 
 
70
    /**
 
71
     * {@inheritDoc}
 
72
     */
 
73
    public void shutdown() {
 
74
        // no-op
 
75
    }
 
76
 
 
77
    /**
 
78
     * {@inheritDoc}
 
79
     */
 
80
    public Map<String, long[]> getCacheMetrics() {
 
81
        Map<String, long[]> result = new HashMap<String, long[]>();
 
82
        for (String cacheName : getCacheNames()) {
 
83
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
84
            if (cache != null) {
 
85
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
86
                result.put(cacheName, new long[] {stats.getCacheHitMostRecentSample(),
 
87
                    stats.getCacheMissNotFoundMostRecentSample()
 
88
                    + stats.getCacheMissExpiredMostRecentSample(),
 
89
                    stats.getCacheElementPutMostRecentSample()});
 
90
            }
 
91
        }
 
92
        return result;
 
93
    }
 
94
 
 
95
    /**
 
96
     * {@inheritDoc}
 
97
     */
 
98
    public long getCacheHitRate() {
 
99
        long result = 0;
 
100
        for (String cacheName : getCacheNames()) {
 
101
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
102
            if (cache != null) {
 
103
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
104
                result += stats.getCacheHitMostRecentSample();
 
105
            }
 
106
        }
 
107
        return result;
 
108
    }
 
109
 
 
110
    /**
 
111
     * {@inheritDoc}
 
112
     */
 
113
    public long getCacheInMemoryHitRate() {
 
114
        long result = 0;
 
115
        for (String cacheName : getCacheNames()) {
 
116
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
117
            if (cache != null) {
 
118
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
119
                result += stats.getCacheHitInMemoryMostRecentSample();
 
120
            }
 
121
        }
 
122
        return result;
 
123
    }
 
124
 
 
125
    /**
 
126
     * {@inheritDoc}
 
127
     */
 
128
    public long getCacheOffHeapHitRate() {
 
129
        long result = 0;
 
130
        for (String cacheName : getCacheNames()) {
 
131
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
132
            if (cache != null) {
 
133
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
134
                result += stats.getCacheHitOffHeapMostRecentSample();
 
135
            }
 
136
        }
 
137
        return result;
 
138
    }
 
139
 
 
140
    /**
 
141
     * {@inheritDoc}
 
142
     */
 
143
    public long getCacheOnDiskHitRate() {
 
144
        long result = 0;
 
145
        for (String cacheName : getCacheNames()) {
 
146
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
147
            if (cache != null) {
 
148
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
149
                result += stats.getCacheHitOnDiskMostRecentSample();
 
150
            }
 
151
        }
 
152
        return result;
 
153
    }
 
154
 
 
155
    /**
 
156
     * {@inheritDoc}
 
157
     */
 
158
    public long getCacheMissRate() {
 
159
        long result = 0;
 
160
        for (String cacheName : getCacheNames()) {
 
161
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
162
            if (cache != null) {
 
163
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
164
                result += (stats.getCacheMissNotFoundMostRecentSample()
 
165
                           + stats.getCacheMissExpiredMostRecentSample());
 
166
            }
 
167
        }
 
168
        return result;
 
169
    }
 
170
 
 
171
    /**
 
172
     * {@inheritDoc}
 
173
     */
 
174
    public long getCacheInMemoryMissRate() {
 
175
        long result = 0;
 
176
        for (String cacheName : getCacheNames()) {
 
177
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
178
            if (cache != null) {
 
179
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
180
                result += stats.getCacheMissInMemoryMostRecentSample();
 
181
            }
 
182
        }
 
183
        return result;
 
184
    }
 
185
 
 
186
    /**
 
187
     * {@inheritDoc}
 
188
     */
 
189
    public long getCacheOffHeapMissRate() {
 
190
        long result = 0;
 
191
        for (String cacheName : getCacheNames()) {
 
192
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
193
            if (cache != null) {
 
194
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
195
                result += stats.getCacheMissOffHeapMostRecentSample();
 
196
            }
 
197
        }
 
198
        return result;
 
199
    }
 
200
 
 
201
    /**
 
202
     * {@inheritDoc}
 
203
     */
 
204
    public long getCacheOnDiskMissRate() {
 
205
        long result = 0;
 
206
        for (String cacheName : getCacheNames()) {
 
207
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
208
            if (cache != null) {
 
209
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
210
                result += stats.getCacheMissOnDiskMostRecentSample();
 
211
            }
 
212
        }
 
213
        return result;
 
214
    }
 
215
 
 
216
    /**
 
217
     * {@inheritDoc}
 
218
     */
 
219
    public long getCachePutRate() {
 
220
        long result = 0;
 
221
        for (String cacheName : getCacheNames()) {
 
222
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
223
            if (cache != null) {
 
224
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
225
                result += stats.getCacheElementPutMostRecentSample();
 
226
            }
 
227
        }
 
228
        return result;
 
229
    }
 
230
 
 
231
    /**
 
232
     * {@inheritDoc}
 
233
     */
 
234
    public long getCacheUpdateRate() {
 
235
        long result = 0;
 
236
        for (String cacheName : getCacheNames()) {
 
237
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
238
            if (cache != null) {
 
239
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
240
                result += stats.getCacheElementUpdatedMostRecentSample();
 
241
            }
 
242
        }
 
243
        return result;
 
244
    }
 
245
 
 
246
    /**
 
247
     * {@inheritDoc}
 
248
     */
 
249
    public long getCacheRemoveRate() {
 
250
        long result = 0;
 
251
        for (String cacheName : getCacheNames()) {
 
252
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
253
            if (cache != null) {
 
254
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
255
                result += stats.getCacheElementRemovedMostRecentSample();
 
256
            }
 
257
        }
 
258
        return result;
 
259
    }
 
260
 
 
261
    /**
 
262
     * {@inheritDoc}
 
263
     */
 
264
    public long getCacheEvictionRate() {
 
265
        long result = 0;
 
266
        for (String cacheName : getCacheNames()) {
 
267
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
268
            if (cache != null) {
 
269
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
270
                result += stats.getCacheElementEvictedMostRecentSample();
 
271
            }
 
272
        }
 
273
        return result;
 
274
    }
 
275
 
 
276
    /**
 
277
     * {@inheritDoc}
 
278
     */
 
279
    public long getCacheExpirationRate() {
 
280
        long result = 0;
 
281
        for (String cacheName : getCacheNames()) {
 
282
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
283
            if (cache != null) {
 
284
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
285
                result += stats.getCacheElementExpiredMostRecentSample();
 
286
            }
 
287
        }
 
288
        return result;
 
289
    }
 
290
 
 
291
    /**
 
292
     * {@inheritDoc}
 
293
     */
 
294
    public float getCacheAverageGetTime() {
 
295
        float result = 0;
 
296
        int instances = 0;
 
297
        for (String cacheName : getCacheNames()) {
 
298
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
299
            if (cache != null) {
 
300
                result += cache.getAverageGetTime();
 
301
                instances++;
 
302
            }
 
303
        }
 
304
        return instances > 0 ? result / instances : 0;
 
305
    }
 
306
 
 
307
    /**
 
308
     * {@inheritDoc}
 
309
     */
 
310
    public long getCacheSearchRate() {
 
311
        long result = 0;
 
312
        for (String cacheName : getCacheNames()) {
 
313
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
314
            if (cache != null) {
 
315
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
316
                result += stats.getSearchesPerSecond();
 
317
            }
 
318
        }
 
319
        return result;
 
320
    }
 
321
 
 
322
    /**
 
323
     * {@inheritDoc}
 
324
     */
 
325
    public long getCacheAverageSearchTime() {
 
326
        long result = 0;
 
327
        for (String cacheName : getCacheNames()) {
 
328
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
329
            if (cache != null) {
 
330
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
331
                result += stats.getAverageSearchTime();
 
332
            }
 
333
        }
 
334
        return result;
 
335
    }
 
336
 
 
337
    /**
 
338
     * {@inheritDoc}
 
339
     */
 
340
    public boolean getHasWriteBehindWriter() {
 
341
        for (String cacheName : getCacheNames()) {
 
342
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
343
            if (cache != null) {
 
344
                if (cache.getWriterManager() instanceof WriteBehindManager &&
 
345
                    cache.getRegisteredCacheWriter() != null) {
 
346
                    return true;
 
347
                }
 
348
            }
 
349
        }
 
350
        return false;
 
351
    }
 
352
 
 
353
    /**
 
354
     * {@inheritDoc}
 
355
     */
 
356
    public long getWriterQueueLength() {
 
357
        long result = 0;
 
358
        for (String cacheName : getCacheNames()) {
 
359
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
360
            if (cache != null) {
 
361
                LiveCacheStatistics stats = cache.getLiveCacheStatistics();
 
362
                result += Math.max(stats.getWriterQueueLength(), 0);
 
363
            }
 
364
        }
 
365
        return result;
 
366
    }
 
367
 
 
368
    /**
 
369
     * {@inheritDoc}
 
370
     */
 
371
    public int getWriterMaxQueueSize() {
 
372
        int result = 0;
 
373
        for (String cacheName : getCacheNames()) {
 
374
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
375
            if (cache != null) {
 
376
                CacheWriterConfiguration writerConfig = cache.getCacheConfiguration().getCacheWriterConfiguration();
 
377
                result += (writerConfig.getWriteBehindMaxQueueSize() * writerConfig.getWriteBehindConcurrency());
 
378
            }
 
379
        }
 
380
        return result;
 
381
    }
 
382
 
 
383
    /**
 
384
     * {@inheritDoc}
 
385
     */
 
386
    public long getMaxBytesLocalDisk() {
 
387
        return cacheManager.getConfiguration().getMaxBytesLocalDisk();
 
388
    }
 
389
 
 
390
    /**
 
391
     * {@inheritDoc}
 
392
     */
 
393
    public String getMaxBytesLocalDiskAsString() {
 
394
        return cacheManager.getConfiguration().getMaxBytesLocalDiskAsString();
 
395
    }
 
396
 
 
397
    /**
 
398
     * {@inheritDoc}
 
399
     */
 
400
    public void setMaxBytesLocalDisk(long maxBytes) {
 
401
        try {
 
402
            cacheManager.getConfiguration().setMaxBytesLocalDisk(maxBytes);
 
403
        } catch (RuntimeException e) {
 
404
            throw Utils.newPlainException(e);
 
405
        }
 
406
    }
 
407
 
 
408
    /**
 
409
     * {@inheritDoc}
 
410
     */
 
411
    public void setMaxBytesLocalDiskAsString(String maxBytes) {
 
412
        try {
 
413
            cacheManager.getConfiguration().setMaxBytesLocalDisk(maxBytes);
 
414
        } catch (RuntimeException e) {
 
415
            throw Utils.newPlainException(e);
 
416
        }
 
417
    }
 
418
 
 
419
    /**
 
420
     * {@inheritDoc}
 
421
     */
 
422
    public long getMaxBytesLocalHeap() {
 
423
        return cacheManager.getConfiguration().getMaxBytesLocalHeap();
 
424
    }
 
425
 
 
426
    /**
 
427
     * {@inheritDoc}
 
428
     */
 
429
    public String getMaxBytesLocalHeapAsString() {
 
430
        return cacheManager.getConfiguration().getMaxBytesLocalHeapAsString();
 
431
    }
 
432
 
 
433
    /**
 
434
     * {@inheritDoc}
 
435
     */
 
436
    public void setMaxBytesLocalHeap(long maxBytes) {
 
437
        try {
 
438
            cacheManager.getConfiguration().setMaxBytesLocalHeap(maxBytes);
 
439
        } catch (RuntimeException e) {
 
440
            throw Utils.newPlainException(e);
 
441
        }
 
442
    }
 
443
 
 
444
    /**
 
445
     * {@inheritDoc}
 
446
     */
 
447
    public void setMaxBytesLocalHeapAsString(String maxBytes) {
 
448
        try {
 
449
            cacheManager.getConfiguration().setMaxBytesLocalHeap(maxBytes);
 
450
        } catch (RuntimeException e) {
 
451
            throw Utils.newPlainException(e);
 
452
        }
 
453
    }
 
454
 
 
455
    /**
 
456
     * {@inheritDoc}
 
457
     */
 
458
    public long getMaxBytesLocalOffHeap() {
 
459
        return cacheManager.getConfiguration().getMaxBytesLocalOffHeap();
 
460
    }
 
461
 
 
462
    /**
 
463
     * {@inheritDoc}
 
464
     */
 
465
    public String getMaxBytesLocalOffHeapAsString() {
 
466
        return cacheManager.getConfiguration().getMaxBytesLocalOffHeapAsString();
 
467
    }
 
468
 
 
469
    /**
 
470
     * {@inheritDoc}
 
471
     */
 
472
    public String getName() {
 
473
        return cacheManager.getName();
 
474
    }
 
475
 
 
476
    /**
 
477
     * {@inheritDoc}
 
478
     */
 
479
    public String getClusterUUID() {
 
480
        return cacheManager.getClusterUUID();
 
481
    }
 
482
 
 
483
    /**
 
484
     * {@inheritDoc}
 
485
     */
 
486
    public void clearStatistics() {
 
487
        for (String cacheName : getCacheNames()) {
 
488
            Cache cache = cacheManager.getCache(cacheName);
 
489
            if (cache != null) {
 
490
                cache.clearStatistics();
 
491
            }
 
492
        }
 
493
    }
 
494
 
 
495
    /**
 
496
     * {@inheritDoc}
 
497
     */
 
498
    public void enableStatistics() {
 
499
        for (String cacheName : getCacheNames()) {
 
500
            Cache cache = cacheManager.getCache(cacheName);
 
501
            if (cache != null) {
 
502
                // enables regular statistics also
 
503
                cache.setSampledStatisticsEnabled(true);
 
504
            }
 
505
        }
 
506
    }
 
507
 
 
508
    /**
 
509
     * {@inheritDoc}
 
510
     */
 
511
    public void disableStatistics() {
 
512
        for (String cacheName : getCacheNames()) {
 
513
            Cache cache = cacheManager.getCache(cacheName);
 
514
            if (cache != null) {
 
515
                // disables regular statistics also
 
516
                cache.setStatisticsEnabled(false);
 
517
            }
 
518
        }
 
519
    }
 
520
 
 
521
    /**
 
522
     * {@inheritDoc}
 
523
     */
 
524
    public void setStatisticsEnabled(boolean enabled) {
 
525
        if (enabled) {
 
526
            enableStatistics();
 
527
        } else {
 
528
            disableStatistics();
 
529
        }
 
530
    }
 
531
 
 
532
    /**
 
533
     * {@inheritDoc}
 
534
     */
 
535
    public boolean isStatisticsEnabled() {
 
536
        for (String cacheName : getCacheNames()) {
 
537
            Cache cache = cacheManager.getCache(cacheName);
 
538
            if (cache != null) {
 
539
                if (!cache.isSampledStatisticsEnabled()) {
 
540
                    return false;
 
541
                }
 
542
            }
 
543
        }
 
544
        return true;
 
545
    }
 
546
 
 
547
    /**
 
548
     * {@inheritDoc}
 
549
     */
 
550
    public String generateActiveConfigDeclaration() {
 
551
        return this.cacheManager.getActiveConfigurationText();
 
552
    }
 
553
 
 
554
    /**
 
555
     * {@inheritDoc}
 
556
     */
 
557
    public String generateActiveConfigDeclaration(String cacheName) {
 
558
        return this.cacheManager.getActiveConfigurationText(cacheName);
 
559
    }
 
560
 
 
561
    /**
 
562
     * {@inheritDoc}
 
563
     */
 
564
    public boolean getTransactional() {
 
565
        for (String cacheName : getCacheNames()) {
 
566
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
567
            if (cache != null && cache.getCacheConfiguration().getTransactionalMode().isTransactional()) {
 
568
                return true;
 
569
            }
 
570
        }
 
571
        return false;
 
572
    }
 
573
 
 
574
    /**
 
575
     * {@inheritDoc}
 
576
     */
 
577
    public boolean getSearchable() {
 
578
        for (String cacheName : getCacheNames()) {
 
579
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
580
            if (cache != null && cache.getCacheConfiguration().getSearchable() != null) {
 
581
                return true;
 
582
            }
 
583
        }
 
584
        return false;
 
585
    }
 
586
 
 
587
    /**
 
588
     * {@inheritDoc}
 
589
     */
 
590
    public long getTransactionCommittedCount() {
 
591
        return this.cacheManager.getTransactionController().getTransactionCommittedCount();
 
592
    }
 
593
 
 
594
    /**
 
595
     * {@inheritDoc}
 
596
     */
 
597
    public long getTransactionCommitRate() {
 
598
        long result = 0;
 
599
        for (String cacheName : getCacheNames()) {
 
600
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
601
            if (cache != null) {
 
602
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
603
                result += stats.getCacheXaCommitsMostRecentSample();
 
604
            }
 
605
        }
 
606
        return result;
 
607
    }
 
608
 
 
609
    /**
 
610
     * {@inheritDoc}
 
611
     */
 
612
    public long getTransactionRolledBackCount() {
 
613
        return this.cacheManager.getTransactionController().getTransactionRolledBackCount();
 
614
    }
 
615
 
 
616
    /**
 
617
     * {@inheritDoc}
 
618
     */
 
619
    public long getTransactionRollbackRate() {
 
620
        long result = 0;
 
621
        for (String cacheName : getCacheNames()) {
 
622
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
623
            if (cache != null) {
 
624
                SampledCacheStatistics stats = cache.getSampledCacheStatistics();
 
625
                result += stats.getCacheXaRollbacksMostRecentSample();
 
626
            }
 
627
        }
 
628
        return result;
 
629
    }
 
630
 
 
631
    /**
 
632
     * {@inheritDoc}
 
633
     */
 
634
    public long getTransactionTimedOutCount() {
 
635
        return this.cacheManager.getTransactionController().getTransactionTimedOutCount();
 
636
    }
 
637
 
 
638
    /**
 
639
     * {@inheritDoc}
 
640
     */
 
641
    public boolean isEnabled() throws CacheException {
 
642
        for (String cacheName : getCacheNames()) {
 
643
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
644
            if (cache != null && cache.isDisabled()) {
 
645
                return false;
 
646
            }
 
647
        }
 
648
        return true;
 
649
    }
 
650
 
 
651
    /**
 
652
     * {@inheritDoc}
 
653
     */
 
654
    public void setEnabled(boolean enabled) {
 
655
        for (String cacheName : getCacheNames()) {
 
656
            Ehcache cache = cacheManager.getEhcache(cacheName);
 
657
            if (cache != null) {
 
658
                cache.setDisabled(!enabled);
 
659
            }
 
660
        }
 
661
    }
 
662
}
 
 
b'\\ No newline at end of file'