|
19 | 19 |
|
20 | 20 | package org.elasticsearch.index.store; |
21 | 21 |
|
| 22 | +import org.apache.lucene.codecs.Codec; |
22 | 23 | import org.apache.lucene.codecs.CodecUtil; |
23 | 24 | import org.apache.lucene.index.CorruptIndexException; |
24 | 25 | import org.apache.lucene.index.IndexCommit; |
|
28 | 29 | import org.apache.lucene.index.IndexNotFoundException; |
29 | 30 | import org.apache.lucene.index.IndexWriter; |
30 | 31 | import org.apache.lucene.index.SegmentCommitInfo; |
| 32 | +import org.apache.lucene.index.SegmentInfo; |
31 | 33 | import org.apache.lucene.index.SegmentInfos; |
32 | 34 | import org.apache.lucene.store.AlreadyClosedException; |
33 | 35 | import org.apache.lucene.store.BufferedChecksum; |
|
49 | 51 | import org.elasticsearch.ExceptionsHelper; |
50 | 52 | import org.elasticsearch.common.Strings; |
51 | 53 | import org.elasticsearch.common.bytes.BytesReference; |
| 54 | +import org.elasticsearch.common.collect.ImmutableOpenMap; |
52 | 55 | import org.elasticsearch.common.collect.Tuple; |
53 | 56 | import org.elasticsearch.common.inject.Inject; |
54 | 57 | import org.elasticsearch.common.io.Streams; |
|
85 | 88 | import java.nio.file.Path; |
86 | 89 | import java.sql.Time; |
87 | 90 | import java.util.ArrayList; |
| 91 | +import java.util.Arrays; |
88 | 92 | import java.util.Collections; |
89 | 93 | import java.util.Comparator; |
90 | 94 | import java.util.HashMap; |
@@ -158,7 +162,7 @@ public Store(ShardId shardId, IndexSettings indexSettings, DirectoryService dire |
158 | 162 | this.shardLock = shardLock; |
159 | 163 | this.onClose = onClose; |
160 | 164 | final TimeValue refreshInterval = indexSettings.getValue(INDEX_STORE_STATS_REFRESH_INTERVAL_SETTING); |
161 | | - this.statsCache = new StoreStatsCache(refreshInterval, directory, directoryService); |
| 165 | + this.statsCache = new StoreStatsCache(refreshInterval, directoryService, this); |
162 | 166 | logger.debug("store stats are refreshed with refresh_interval [{}]", refreshInterval); |
163 | 167 |
|
164 | 168 | assert onClose != null; |
@@ -1546,35 +1550,113 @@ public void handle(ShardLock Lock) { |
1546 | 1550 | } |
1547 | 1551 |
|
1548 | 1552 | private static class StoreStatsCache extends SingleObjectCache<StoreStats> { |
1549 | | - private final Directory directory; |
| 1553 | + private final Store store; |
1550 | 1554 | private final DirectoryService directoryService; |
1551 | 1555 |
|
1552 | | - public StoreStatsCache(TimeValue refreshInterval, Directory directory, DirectoryService directoryService) throws IOException { |
1553 | | - super(refreshInterval, new StoreStats(estimateSize(directory), directoryService.throttleTimeInNanos())); |
1554 | | - this.directory = directory; |
| 1556 | + public StoreStatsCache(TimeValue refreshInterval, DirectoryService directoryService, Store store) throws IOException { |
| 1557 | + super(refreshInterval, estimateSize(store, directoryService.throttleTimeInNanos())); |
| 1558 | + this.store = store; |
1555 | 1559 | this.directoryService = directoryService; |
1556 | 1560 | } |
1557 | 1561 |
|
1558 | 1562 | @Override |
1559 | 1563 | protected StoreStats refresh() { |
1560 | 1564 | try { |
1561 | | - return new StoreStats(estimateSize(directory), directoryService.throttleTimeInNanos()); |
| 1565 | + return estimateSize(store, directoryService.throttleTimeInNanos()); |
1562 | 1566 | } catch (IOException ex) { |
1563 | 1567 | throw new ElasticsearchException("failed to refresh store stats", ex); |
1564 | 1568 | } |
1565 | 1569 | } |
1566 | 1570 |
|
1567 | | - private static long estimateSize(Directory directory) throws IOException { |
| 1571 | + private static StoreStats estimateSize(Store store, final long throttleTimeInNanos) throws IOException { |
1568 | 1572 | long estimatedSize = 0; |
1569 | | - String[] files = directory.listAll(); |
| 1573 | + Directory storeDirectory = store.directory(); |
| 1574 | + String[] files = new String[0]; |
| 1575 | + try { |
| 1576 | + files = storeDirectory.listAll(); |
| 1577 | + } catch (IOException e) { |
| 1578 | + store.logger.warn("Couldn't list Store Directory [{}]", e, storeDirectory); |
| 1579 | + } |
| 1580 | + |
| 1581 | + boolean segmentsFileExists = false; |
1570 | 1582 | for (String file : files) { |
1571 | 1583 | try { |
1572 | | - estimatedSize += directory.fileLength(file); |
| 1584 | + estimatedSize += storeDirectory.fileLength(file); |
| 1585 | + if (file.startsWith(IndexFileNames.SEGMENTS)) { |
| 1586 | + segmentsFileExists = true; |
| 1587 | + } |
1573 | 1588 | } catch (NoSuchFileException | FileNotFoundException e) { |
1574 | 1589 | // ignore, the file is not there no more |
1575 | 1590 | } |
1576 | 1591 | } |
1577 | | - return estimatedSize; |
| 1592 | + |
| 1593 | + StoreStats basicStoreStats = new StoreStats(estimatedSize, ImmutableOpenMap.of(), throttleTimeInNanos); |
| 1594 | + if (!segmentsFileExists) { |
| 1595 | + return basicStoreStats; |
| 1596 | + } |
| 1597 | + |
| 1598 | + ImmutableOpenMap.Builder<String, Long> map = ImmutableOpenMap.builder(); |
| 1599 | + SegmentInfos segmentInfos = null; |
| 1600 | + try { |
| 1601 | + segmentInfos = store.readLastCommittedSegmentsInfo(); |
| 1602 | + } catch (IOException e) { |
| 1603 | + store.logger.warn("Unable to retrieve segment infos", e); |
| 1604 | + return basicStoreStats; |
| 1605 | + } |
| 1606 | + |
| 1607 | + for (SegmentCommitInfo segmentCommitInfo : segmentInfos) { |
| 1608 | + Directory directory = null; |
| 1609 | + boolean useCompoundFile = segmentCommitInfo.info.getUseCompoundFile(); |
| 1610 | + if (useCompoundFile) { |
| 1611 | + try { |
| 1612 | + directory = segmentCommitInfo.info.getCodec().compoundFormat() |
| 1613 | + .getCompoundReader(segmentCommitInfo.info.dir, segmentCommitInfo.info, IOContext.READ); |
| 1614 | + } catch (IOException e) { |
| 1615 | + store.logger.warn("Error when opening compound reader for Directory [{}] and SegmentCommitInfo [{}]", e, |
| 1616 | + segmentCommitInfo.info.dir, segmentCommitInfo); |
| 1617 | + } |
| 1618 | + } else { |
| 1619 | + directory = segmentCommitInfo.info.dir; |
| 1620 | + } |
| 1621 | + |
| 1622 | + // Couldn't open compound reader, skip |
| 1623 | + if (directory == null) { |
| 1624 | + continue; |
| 1625 | + } |
| 1626 | + |
| 1627 | + files = new String[0]; |
| 1628 | + try { |
| 1629 | + files = directory.listAll(); |
| 1630 | + } catch (IOException e) { |
| 1631 | + store.logger.warn("Couldn't list Directory [{}]", e, directory); |
| 1632 | + } |
| 1633 | + |
| 1634 | + for (String file : files) { |
| 1635 | + String extension = IndexFileNames.getExtension(file); |
| 1636 | + if (extension == null) { |
| 1637 | + continue; |
| 1638 | + } |
| 1639 | + |
| 1640 | + try { |
| 1641 | + long length = directory.fileLength(file); |
| 1642 | + map.put(extension, length); |
| 1643 | + } catch (NoSuchFileException | FileNotFoundException e) { |
| 1644 | + store.logger.trace("Tried to query fileLength but file is gone, Directory [{}], file [{}]", e, directory, file); |
| 1645 | + } catch (IOException e) { |
| 1646 | + store.logger.warn("Error when trying to query fileLength in Directory [{}] and file [{}]", e, directory, file); |
| 1647 | + } |
| 1648 | + } |
| 1649 | + |
| 1650 | + if (useCompoundFile && directory != null) { |
| 1651 | + try { |
| 1652 | + directory.close(); |
| 1653 | + } catch (IOException e) { |
| 1654 | + store.logger.warn("Error when closing compound reader on Directory [{}]", e, directory); |
| 1655 | + } |
| 1656 | + } |
| 1657 | + } |
| 1658 | + |
| 1659 | + return new StoreStats(estimatedSize, map.build(), throttleTimeInNanos); |
1578 | 1660 | } |
1579 | 1661 | } |
1580 | 1662 |
|
|
0 commit comments