1/* 2 * Copyright (C) 2013 The Android Open Source Project 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 17#include "dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h" 18 19#include "dictionary/interface/dictionary_header_structure_policy.h" 20#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h" 21#include "dictionary/structure/pt_common/pt_node_params.h" 22#include "dictionary/structure/pt_common/pt_node_writer.h" 23 24namespace latinime { 25 26bool DynamicPtGcEventListeners 27 ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted 28 ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) { 29 // PtNode is useless when the PtNode is not a terminal and doesn't have any not useless 30 // children. 31 bool isUselessPtNode = !ptNodeParams->isTerminal(); 32 if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) { 33 bool needsToKeepPtNode = true; 34 if (!mPtNodeWriter->updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC( 35 ptNodeParams, &needsToKeepPtNode)) { 36 AKLOGE("Cannot update PtNode probability or get needs to keep PtNode after GC."); 37 return false; 38 } 39 if (!needsToKeepPtNode) { 40 isUselessPtNode = true; 41 } 42 } 43 if (mChildrenValue > 0) { 44 isUselessPtNode = false; 45 } else if (ptNodeParams->isTerminal()) { 46 // Remove children as all children are useless. 47 if (!mPtNodeWriter->updateChildrenPosition(ptNodeParams, 48 NOT_A_DICT_POS /* newChildrenPosition */)) { 49 return false; 50 } 51 } 52 if (isUselessPtNode) { 53 // Current PtNode is no longer needed. Mark it as deleted. 54 if (!mPtNodeWriter->markPtNodeAsDeleted(ptNodeParams)) { 55 return false; 56 } 57 } else { 58 mValueStack.back() += 1; 59 if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) { 60 mValidUnigramCount += 1; 61 } 62 } 63 return true; 64} 65 66bool DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability 67 ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) { 68 if (!ptNodeParams->isDeleted()) { 69 int bigramEntryCount = 0; 70 if (!mPtNodeWriter->updateAllBigramEntriesAndDeleteUselessEntries(ptNodeParams, 71 &bigramEntryCount)) { 72 return false; 73 } 74 mValidBigramEntryCount += bigramEntryCount; 75 } 76 return true; 77} 78 79// Writes dummy PtNode array size when the head of PtNode array is read. 80bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer 81 ::onDescend(const int ptNodeArrayPos) { 82 mValidPtNodeCount = 0; 83 int writingPos = mBufferToWrite->getTailPosition(); 84 mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.insert( 85 PtNodeWriter::PtNodeArrayPositionRelocationMap::value_type(ptNodeArrayPos, writingPos)); 86 // Writes dummy PtNode array size because arrays can have a forward link or needles PtNodes. 87 // This field will be updated later in onReadingPtNodeArrayTail() with actual PtNode count. 88 mPtNodeArraySizeFieldPos = writingPos; 89 return DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition( 90 mBufferToWrite, 0 /* arraySize */, &writingPos); 91} 92 93// Write PtNode array terminal and actual PtNode array size. 94bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer 95 ::onReadingPtNodeArrayTail() { 96 int writingPos = mBufferToWrite->getTailPosition(); 97 // Write PtNode array terminal. 98 if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition( 99 mBufferToWrite, NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) { 100 return false; 101 } 102 // Write actual PtNode array size. 103 if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition( 104 mBufferToWrite, mValidPtNodeCount, &mPtNodeArraySizeFieldPos)) { 105 return false; 106 } 107 return true; 108} 109 110// Write valid PtNode to buffer and memorize mapping from the old position to the new position. 111bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer 112 ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) { 113 if (ptNodeParams->isDeleted()) { 114 // Current PtNode is not written in new buffer because it has been deleted. 115 mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert( 116 PtNodeWriter::PtNodePositionRelocationMap::value_type( 117 ptNodeParams->getHeadPos(), NOT_A_DICT_POS)); 118 return true; 119 } 120 int writingPos = mBufferToWrite->getTailPosition(); 121 mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert( 122 PtNodeWriter::PtNodePositionRelocationMap::value_type( 123 ptNodeParams->getHeadPos(), writingPos)); 124 mValidPtNodeCount++; 125 // Writes current PtNode. 126 return mPtNodeWriter->writePtNodeAndAdvancePosition(ptNodeParams, &writingPos); 127} 128 129bool DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields 130 ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) { 131 // Updates parent position. 132 int bigramCount = 0; 133 if (!mPtNodeWriter->updateAllPositionFields(ptNodeParams, mDictPositionRelocationMap, 134 &bigramCount)) { 135 return false; 136 } 137 mBigramCount += bigramCount; 138 if (ptNodeParams->isTerminal()) { 139 mUnigramCount++; 140 } 141 return true; 142} 143 144} // namespace latinime 145