Prepare dictionary saving in native code.

Bug: 6669677

Change-Id: I0787f66409e2b183c6328fa05805945520e1e93a
main
Keisuke Kuroyanagi 2013-09-17 18:07:16 +09:00
parent 7e51989b3f
commit d0246277fd
11 changed files with 147 additions and 10 deletions

View File

@ -19,6 +19,7 @@ package com.android.inputmethod.latin;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.settings.NativeSuggestOptions; import com.android.inputmethod.latin.settings.NativeSuggestOptions;
@ -47,6 +48,7 @@ public final class BinaryDictionary extends Dictionary {
private long mNativeDict; private long mNativeDict;
private final Locale mLocale; private final Locale mLocale;
private final long mDictSize; private final long mDictSize;
private final String mDictFilePath;
private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH]; private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS]; private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
private final int[] mSpaceIndices = new int[MAX_RESULTS]; private final int[] mSpaceIndices = new int[MAX_RESULTS];
@ -91,6 +93,7 @@ public final class BinaryDictionary extends Dictionary {
super(dictType); super(dictType);
mLocale = locale; mLocale = locale;
mDictSize = length; mDictSize = length;
mDictFilePath = filename;
mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance); mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
loadDictionary(filename, offset, length, isUpdatable); loadDictionary(filename, offset, length, isUpdatable);
} }
@ -101,6 +104,9 @@ public final class BinaryDictionary extends Dictionary {
private static native long openNative(String sourceDir, long dictOffset, long dictSize, private static native long openNative(String sourceDir, long dictOffset, long dictSize,
boolean isUpdatable); boolean isUpdatable);
private static native void flushNative(long dict, String filePath);
private static native boolean needsToRunGCNative(long dict);
private static native void flushWithGCNative(long dict, String filePath);
private static native void closeNative(long dict); private static native void closeNative(long dict);
private static native int getProbabilityNative(long dict, int[] word); private static native int getProbabilityNative(long dict, int[] word);
private static native boolean isValidBigramNative(long dict, int[] word0, int[] word1); private static native boolean isValidBigramNative(long dict, int[] word0, int[] word1);
@ -261,6 +267,24 @@ public final class BinaryDictionary extends Dictionary {
removeBigramWordsNative(mNativeDict, codePoints0, codePoints1); removeBigramWordsNative(mNativeDict, codePoints0, codePoints1);
} }
@UsedForTesting
public void flush() {
if (!isValidDictionary()) return;
flushNative(mNativeDict, mDictFilePath);
}
@UsedForTesting
public void flushWithGC() {
if (!isValidDictionary()) return;
flushWithGCNative(mNativeDict, mDictFilePath);
}
@UsedForTesting
public boolean needsToRunGC() {
if (!isValidDictionary()) return false;
return needsToRunGCNative(mNativeDict);
}
@Override @Override
public boolean shouldAutoCommit(final SuggestedWordInfo candidate) { public boolean shouldAutoCommit(final SuggestedWordInfo candidate) {
// TODO: actually use the confidence rather than use this completely broken heuristic // TODO: actually use the confidence rather than use this completely broken heuristic

View File

@ -46,8 +46,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring s
sourceDirChars[sourceDirUtf8Length] = '\0'; sourceDirChars[sourceDirUtf8Length] = '\0';
DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy = DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy =
DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy( DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy(
sourceDirChars, static_cast<int>(sourceDirUtf8Length), sourceDirChars, static_cast<int>(dictOffset), static_cast<int>(dictSize),
static_cast<int>(dictOffset), static_cast<int>(dictSize),
isUpdatable == JNI_TRUE); isUpdatable == JNI_TRUE);
if (!dictionaryStructureWithBufferPolicy) { if (!dictionaryStructureWithBufferPolicy) {
return 0; return 0;
@ -59,6 +58,35 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring s
return reinterpret_cast<jlong>(dictionary); return reinterpret_cast<jlong>(dictionary);
} }
static void latinime_BinaryDictionary_flush(JNIEnv *env, jclass clazz, jlong dict,
jstring filePath) {
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
if (!dictionary) return;
const jsize filePathUtf8Length = env->GetStringUTFLength(filePath);
char filePathChars[filePathUtf8Length + 1];
env->GetStringUTFRegion(filePath, 0, env->GetStringLength(filePath), filePathChars);
filePathChars[filePathUtf8Length] = '\0';
dictionary->flush(filePathChars);
}
static bool latinime_BinaryDictionary_needsToRunGC(JNIEnv *env, jclass clazz,
jlong dict) {
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
if (!dictionary) return false;
return dictionary->needsToRunGC();
}
static void latinime_BinaryDictionary_flushWithGC(JNIEnv *env, jclass clazz, jlong dict,
jstring filePath) {
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
if (!dictionary) return;
const jsize filePathUtf8Length = env->GetStringUTFLength(filePath);
char filePathChars[filePathUtf8Length + 1];
env->GetStringUTFRegion(filePath, 0, env->GetStringLength(filePath), filePathChars);
filePathChars[filePathUtf8Length] = '\0';
dictionary->flushWithGC(filePathChars);
}
static void latinime_BinaryDictionary_close(JNIEnv *env, jclass clazz, jlong dict) { static void latinime_BinaryDictionary_close(JNIEnv *env, jclass clazz, jlong dict) {
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
if (!dictionary) return; if (!dictionary) return;
@ -252,6 +280,21 @@ static const JNINativeMethod sMethods[] = {
const_cast<char *>("(J)V"), const_cast<char *>("(J)V"),
reinterpret_cast<void *>(latinime_BinaryDictionary_close) reinterpret_cast<void *>(latinime_BinaryDictionary_close)
}, },
{
const_cast<char *>("flushNative"),
const_cast<char *>("(JLjava/lang/String;)V"),
reinterpret_cast<void *>(latinime_BinaryDictionary_flush)
},
{
const_cast<char *>("needsToRunGCNative"),
const_cast<char *>("(J)Z"),
reinterpret_cast<void *>(latinime_BinaryDictionary_needsToRunGC)
},
{
const_cast<char *>("flushWithGCNative"),
const_cast<char *>("(JLjava/lang/String;)V"),
reinterpret_cast<void *>(latinime_BinaryDictionary_flushWithGC)
},
{ {
const_cast<char *>("getSuggestionsNative"), const_cast<char *>("getSuggestionsNative"),
const_cast<char *>("(JJJ[I[I[I[I[III[I[I[I[I[I[I[I)I"), const_cast<char *>("(JJJ[I[I[I[I[III[I[I[I[I[I[I[I)I"),

View File

@ -112,6 +112,18 @@ void Dictionary::removeBigramWords(const int *const word0, const int length0,
mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1); mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1);
} }
void Dictionary::flush(const char *const filePath) {
mDictionaryStructureWithBufferPolicy->flush(filePath);
}
void Dictionary::flushWithGC(const char *const filePath) {
mDictionaryStructureWithBufferPolicy->flushWithGC(filePath);
}
bool Dictionary::needsToRunGC() {
return mDictionaryStructureWithBufferPolicy->needsToRunGC();
}
void Dictionary::logDictionaryInfo(JNIEnv *const env) const { void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
const int BUFFER_SIZE = 16; const int BUFFER_SIZE = 16;
int dictionaryIdCodePointBuffer[BUFFER_SIZE]; int dictionaryIdCodePointBuffer[BUFFER_SIZE];

View File

@ -77,6 +77,12 @@ class Dictionary {
void removeBigramWords(const int *const word0, const int length0, const int *const word1, void removeBigramWords(const int *const word0, const int length0, const int *const word1,
const int length1); const int length1);
void flush(const char *const filePath);
void flushWithGC(const char *const filePath);
bool needsToRunGC();
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const { const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const {
return mDictionaryStructureWithBufferPolicy; return mDictionaryStructureWithBufferPolicy;
} }

View File

@ -74,6 +74,12 @@ class DictionaryStructureWithBufferPolicy {
virtual bool removeBigramWords(const int *const word0, const int length0, virtual bool removeBigramWords(const int *const word0, const int length0,
const int *const word1, const int length1) = 0; const int *const word1, const int length1) = 0;
virtual void flush(const char *const filePath) = 0;
virtual void flushWithGC(const char *const filePath) = 0;
virtual bool needsToRunGC() const = 0;
protected: protected:
DictionaryStructureWithBufferPolicy() {} DictionaryStructureWithBufferPolicy() {}

View File

@ -27,12 +27,12 @@
namespace latinime { namespace latinime {
/* static */ DictionaryStructureWithBufferPolicy *DictionaryStructureWithBufferPolicyFactory /* static */ DictionaryStructureWithBufferPolicy *DictionaryStructureWithBufferPolicyFactory
::newDictionaryStructureWithBufferPolicy(const char *const path, const int pathLength, ::newDictionaryStructureWithBufferPolicy(const char *const path, const int bufOffset,
const int bufOffset, const int size, const bool isUpdatable) { const int size, const bool isUpdatable) {
// Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
// impl classes of DictionaryStructureWithBufferPolicy. // impl classes of DictionaryStructureWithBufferPolicy.
const MmappedBuffer *const mmapedBuffer = MmappedBuffer::openBuffer(path, pathLength, bufOffset, const MmappedBuffer *const mmapedBuffer = MmappedBuffer::openBuffer(path, bufOffset, size,
size, isUpdatable); isUpdatable);
if (!mmapedBuffer) { if (!mmapedBuffer) {
return 0; return 0;
} }

View File

@ -27,8 +27,7 @@ namespace latinime {
class DictionaryStructureWithBufferPolicyFactory { class DictionaryStructureWithBufferPolicyFactory {
public: public:
static DictionaryStructureWithBufferPolicy *newDictionaryStructureWithBufferPolicy( static DictionaryStructureWithBufferPolicy *newDictionaryStructureWithBufferPolicy(
const char *const path, const int pathLength, const int bufOffset, const int size, const char *const path, const int bufOffset, const int size, const bool isUpdatable);
const bool isUpdatable);
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory); DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);

View File

@ -243,4 +243,29 @@ bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const
return writingHelper.removeBigramWords(word0Pos, word1Pos); return writingHelper.removeBigramWords(word0Pos, word1Pos);
} }
void DynamicPatriciaTriePolicy::flush(const char *const filePath) {
if (!mBuffer->isUpdatable()) {
AKLOGI("Warning: flush() is called for non-updatable dictionary.");
return;
}
// TODO: Implement.
}
void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) {
if (!mBuffer->isUpdatable()) {
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
return;
}
// TODO: Implement.
}
bool DynamicPatriciaTriePolicy::needsToRunGC() const {
if (!mBuffer->isUpdatable()) {
AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
return false;
}
// TODO: Implement.
return false;
}
} // namespace latinime } // namespace latinime

View File

@ -85,6 +85,12 @@ class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
bool removeBigramWords(const int *const word0, const int length0, const int *const word1, bool removeBigramWords(const int *const word0, const int length0, const int *const word1,
const int length1); const int length1);
void flush(const char *const filePath);
void flushWithGC(const char *const filePath);
bool needsToRunGC() const;
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTriePolicy); DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTriePolicy);

View File

@ -96,6 +96,22 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
return false; return false;
} }
void flush(const char *const filePath) {
// This method should not be called for non-updatable dictionary.
AKLOGI("Warning: flush() is called for non-updatable dictionary.");
}
void flushWithGC(const char *const filePath) {
// This method should not be called for non-updatable dictionary.
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
}
bool needsToRunGC() const {
// This method should not be called for non-updatable dictionary.
AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
return false;
}
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy); DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);

View File

@ -29,8 +29,8 @@ namespace latinime {
class MmappedBuffer { class MmappedBuffer {
public: public:
static MmappedBuffer* openBuffer(const char *const path, const int pathLength, static MmappedBuffer* openBuffer(const char *const path, const int bufferOffset,
const int bufferOffset, const int bufferSize, const bool isUpdatable) { const int bufferSize, const bool isUpdatable) {
const int openMode = isUpdatable ? O_RDWR : O_RDONLY; const int openMode = isUpdatable ? O_RDWR : O_RDONLY;
const int mmapFd = open(path, openMode); const int mmapFd = open(path, openMode);
if (mmapFd < 0) { if (mmapFd < 0) {