| 654 | } |
| 655 | |
| 656 | void TopDUContextDynamicData::store() |
| 657 | { |
| 658 | // qCDebug(LANGUAGE) << "storing" << m_topContext->url().str() << m_topContext->ownIndex() << "import-count:" << m_topContext->importedParentContexts().size(); |
| 659 | |
| 660 | //Check if something has changed. If nothing has changed, don't store to disk. |
| 661 | bool contentDataChanged = hasChanged(); |
| 662 | if (!contentDataChanged) { |
| 663 | return; |
| 664 | } |
| 665 | |
| 666 | ///@todo Save the meta-data into a repository, and only the actual content data into a file. |
| 667 | /// This will make saving+loading more efficient, and will reduce the disk-usage. |
| 668 | /// Then we also won't need to load the data if only the meta-data changed. |
| 669 | if (!m_dataLoaded) |
| 670 | loadData(); |
| 671 | |
| 672 | ///If the data is mapped, and we re-write the file, we must make sure that the data is copied out of the map, |
| 673 | ///even if only metadata is changed. |
| 674 | ///@todo If we split up data and metadata, we don't need to do this |
| 675 | if (m_mappedData) |
| 676 | contentDataChanged = true; |
| 677 | |
| 678 | m_topContext->makeDynamic(); |
| 679 | m_topContextData.clear(); |
| 680 | Q_ASSERT(m_topContext->d_func()->m_ownIndex == m_topContext->ownIndex()); |
| 681 | |
| 682 | uint topContextDataSize = DUChainItemSystem::self().dynamicSize(*m_topContext->d_func()); |
| 683 | m_topContextData.append({QByteArray(DUChainItemSystem::self().dynamicSize(*m_topContext->d_func()), |
| 684 | topContextDataSize), 0u}); |
| 685 | uint actualTopContextDataSize = 0; |
| 686 | |
| 687 | if (contentDataChanged) { |
| 688 | //We don't need these structures any more, since we have loaded all the declarations/contexts, and m_data |
| 689 | //will be reset which these structures pointed into |
| 690 | //Load all lazy declarations/contexts |
| 691 | |
| 692 | const auto oldData = m_data; //Keep the old data alive until everything is stored into a new data structure |
| 693 | |
| 694 | m_data.clear(); |
| 695 | |
| 696 | uint newDataSize = 0; |
| 697 | for (const ArrayWithPosition& array : oldData) { |
| 698 | newDataSize += array.position; |
| 699 | } |
| 700 | |
| 701 | newDataSize = std::max(newDataSize, 10000u); |
| 702 | |
| 703 | //We always put 1 byte to the front, so we don't have zero data-offsets, since those are used for "invalid". |
| 704 | uint currentDataOffset = 1; |
| 705 | m_data.append({QByteArray(newDataSize, 0), currentDataOffset}); |
| 706 | |
| 707 | m_itemRetrievalForbidden = true; |
| 708 | |
| 709 | m_contexts.storeData(currentDataOffset, oldData); |
| 710 | m_declarations.storeData(currentDataOffset, oldData); |
| 711 | m_problems.storeData(currentDataOffset, oldData); |
| 712 | |
| 713 | m_itemRetrievalForbidden = false; |
no test coverage detected