mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-23 07:27:22 +01:00
part two: add threadID and support multiple threads
Looks like it's enough to just use a mutex so threads block until it's their turn to send logs to java.
This commit is contained in:
parent
cfa9b73833
commit
6560394478
6 changed files with 66 additions and 49 deletions
|
@ -51,6 +51,7 @@ public class DlgDelegate {
|
||||||
DWNLD_LOC_DICT,
|
DWNLD_LOC_DICT,
|
||||||
NEW_GAME_DFLT_NAME,
|
NEW_GAME_DFLT_NAME,
|
||||||
SEND_EMAIL,
|
SEND_EMAIL,
|
||||||
|
WRITE_LOG_DB,
|
||||||
CLEAR_LOG_DB,
|
CLEAR_LOG_DB,
|
||||||
|
|
||||||
// BoardDelegate
|
// BoardDelegate
|
||||||
|
|
|
@ -1385,6 +1385,25 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
Utils.emailAuthor( m_activity );
|
Utils.emailAuthor( m_activity );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WRITE_LOG_DB:
|
||||||
|
final File logLoc = Log.dumpStored();
|
||||||
|
post( new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String dumpMsg;
|
||||||
|
if ( null == logLoc ) {
|
||||||
|
dumpMsg = LocUtils.getString( m_activity,
|
||||||
|
R.string.logstore_notdumped );
|
||||||
|
} else {
|
||||||
|
dumpMsg = LocUtils
|
||||||
|
.getString( m_activity, R.string.logstore_dumped_fmt,
|
||||||
|
logLoc.getPath() );
|
||||||
|
}
|
||||||
|
makeOkOnlyBuilder( dumpMsg ).show();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
break;
|
||||||
|
|
||||||
case CLEAR_LOG_DB:
|
case CLEAR_LOG_DB:
|
||||||
int nDumped = Log.clearStored();
|
int nDumped = Log.clearStored();
|
||||||
Utils.showToast( m_activity, R.string.logstore_cleared_fmt, nDumped );
|
Utils.showToast( m_activity, R.string.logstore_cleared_fmt, nDumped );
|
||||||
|
@ -1687,13 +1706,8 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
.show();
|
.show();
|
||||||
break;
|
break;
|
||||||
case R.id.games_menu_dumpLogStorage:
|
case R.id.games_menu_dumpLogStorage:
|
||||||
File logLoc = Log.dumpStored();
|
Perms23.tryGetPerms( this, Perm.STORAGE, null,
|
||||||
if ( null != logLoc ) {
|
Action.WRITE_LOG_DB );
|
||||||
String dumpMsg = LocUtils
|
|
||||||
.getString( m_activity, R.string.logstore_dumped_fmt,
|
|
||||||
logLoc.getPath() );
|
|
||||||
makeOkOnlyBuilder( dumpMsg ).show();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1907,6 +1921,7 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
} else {
|
} else {
|
||||||
dropSels = true; // will select the new game instead
|
dropSels = true; // will select the new game instead
|
||||||
post( new Runnable() {
|
post( new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Activity self = m_activity;
|
Activity self = m_activity;
|
||||||
byte[] stream =
|
byte[] stream =
|
||||||
|
|
|
@ -42,9 +42,11 @@ public class Log {
|
||||||
private static final boolean LOGGING_ENABLED
|
private static final boolean LOGGING_ENABLED
|
||||||
= BuildConfig.DEBUG || !BuildConfig.IS_TAGGED_BUILD;
|
= BuildConfig.DEBUG || !BuildConfig.IS_TAGGED_BUILD;
|
||||||
private static final boolean ERROR_LOGGING_ENABLED = true;
|
private static final boolean ERROR_LOGGING_ENABLED = true;
|
||||||
private static final String LOGS_DB_NAME = "logs_db";
|
private static final String LOGS_DB_NAME = "xwlogs_db";
|
||||||
private static final String LOGS_TABLE_NAME = "logs";
|
private static final String LOGS_TABLE_NAME = "logs";
|
||||||
private static final String COL_ENTRY = "entry";
|
private static final String COL_ENTRY = "entry";
|
||||||
|
private static final String COL_THREAD = "tid";
|
||||||
|
private static final String COL_PID = "pid";
|
||||||
private static final String COL_ROWID = "rowid";
|
private static final String COL_ROWID = "rowid";
|
||||||
private static final String COL_TAG = "tag";
|
private static final String COL_TAG = "tag";
|
||||||
private static final String COL_LEVEL = "level";
|
private static final String COL_LEVEL = "level";
|
||||||
|
@ -188,10 +190,10 @@ public class Log {
|
||||||
return s_dbHelper;
|
return s_dbHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from jni
|
// Called from jni. Keep name and signature in sync with what's in
|
||||||
|
// passToJava() in andutils.c
|
||||||
public static void store( String tag, String msg )
|
public static void store( String tag, String msg )
|
||||||
{
|
{
|
||||||
llog( "store(%s) called from jni", msg );
|
|
||||||
store( LOG_LEVEL.DEBUG, tag, msg );
|
store( LOG_LEVEL.DEBUG, tag, msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +222,8 @@ public class Log {
|
||||||
String query = "CREATE TABLE " + LOGS_TABLE_NAME + "("
|
String query = "CREATE TABLE " + LOGS_TABLE_NAME + "("
|
||||||
+ COL_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT"
|
+ COL_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT"
|
||||||
+ "," + COL_ENTRY + " TEXT"
|
+ "," + COL_ENTRY + " TEXT"
|
||||||
|
+ "," + COL_THREAD + " INTEGER"
|
||||||
|
+ "," + COL_PID + " INTEGER"
|
||||||
+ "," + COL_TAG + " TEXT"
|
+ "," + COL_TAG + " TEXT"
|
||||||
+ "," + COL_LEVEL + " INTEGER(2)"
|
+ "," + COL_LEVEL + " INTEGER(2)"
|
||||||
+ ");";
|
+ ");";
|
||||||
|
@ -238,8 +242,11 @@ public class Log {
|
||||||
|
|
||||||
void store( LOG_LEVEL level, String tag, String msg )
|
void store( LOG_LEVEL level, String tag, String msg )
|
||||||
{
|
{
|
||||||
|
long tid = Thread.currentThread().getId();
|
||||||
|
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put( COL_ENTRY, msg );
|
values.put( COL_ENTRY, msg );
|
||||||
|
values.put( COL_THREAD, tid );
|
||||||
values.put( COL_TAG, tag );
|
values.put( COL_TAG, tag );
|
||||||
values.put( COL_LEVEL, level.ordinal() );
|
values.put( COL_LEVEL, level.ordinal() );
|
||||||
long res = getWritableDatabase().insert( LOGS_TABLE_NAME, null, values );
|
long res = getWritableDatabase().insert( LOGS_TABLE_NAME, null, values );
|
||||||
|
@ -247,14 +254,15 @@ public class Log {
|
||||||
|
|
||||||
File dumpToFile()
|
File dumpToFile()
|
||||||
{
|
{
|
||||||
File storage = Environment.getExternalStorageDirectory();
|
File dir = Environment.getExternalStorageDirectory();
|
||||||
File db = new File( storage, LOGS_DB_NAME );
|
dir = new File( dir, Environment.DIRECTORY_DOWNLOADS );
|
||||||
|
File db = new File( dir, LOGS_DB_NAME + ".txt" );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
OutputStream os = new FileOutputStream( db );
|
OutputStream os = new FileOutputStream( db );
|
||||||
OutputStreamWriter osw = new OutputStreamWriter(os);
|
OutputStreamWriter osw = new OutputStreamWriter(os);
|
||||||
|
|
||||||
String[] columns = { COL_ENTRY, COL_TAG };
|
String[] columns = { COL_ENTRY, COL_TAG, COL_THREAD };
|
||||||
String selection = null;
|
String selection = null;
|
||||||
String orderBy = COL_ROWID;
|
String orderBy = COL_ROWID;
|
||||||
Cursor cursor = getReadableDatabase().query( LOGS_TABLE_NAME, columns,
|
Cursor cursor = getReadableDatabase().query( LOGS_TABLE_NAME, columns,
|
||||||
|
@ -263,17 +271,22 @@ public class Log {
|
||||||
llog( "dumpToFile(): got %d results", cursor.getCount() );
|
llog( "dumpToFile(): got %d results", cursor.getCount() );
|
||||||
int indx0 = cursor.getColumnIndex( columns[0] );
|
int indx0 = cursor.getColumnIndex( columns[0] );
|
||||||
int indx1 = cursor.getColumnIndex( columns[1] );
|
int indx1 = cursor.getColumnIndex( columns[1] );
|
||||||
|
int indx2 = cursor.getColumnIndex( columns[2] );
|
||||||
while ( cursor.moveToNext() ) {
|
while ( cursor.moveToNext() ) {
|
||||||
String data = cursor.getString(indx0);
|
String data = cursor.getString(indx0);
|
||||||
String tag = cursor.getString(indx1);
|
String tag = cursor.getString(indx1);
|
||||||
osw.write( tag );
|
long tid = cursor.getLong(indx2);
|
||||||
osw.write( ":" );
|
StringBuilder builder = new StringBuilder()
|
||||||
osw.write(data);
|
.append(tid).append(":")
|
||||||
osw.write( "\n" );
|
.append(tag).append(":")
|
||||||
|
.append(data).append("\n")
|
||||||
|
;
|
||||||
|
osw.write( builder.toString() );
|
||||||
}
|
}
|
||||||
osw.close();
|
osw.close();
|
||||||
} catch ( IOException ioe ) {
|
} catch ( IOException ioe ) {
|
||||||
llog( "dumpToFile(): ioe: %s", ioe );
|
llog( "dumpToFile(): ioe: %s", ioe );
|
||||||
|
db = null;
|
||||||
}
|
}
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2530,6 +2530,8 @@
|
||||||
<string name="gamel_menu_logstore_dump">Write stored logs to file</string>
|
<string name="gamel_menu_logstore_dump">Write stored logs to file</string>
|
||||||
<!-- Debug-build-only status message shown after logs successfully written to file -->
|
<!-- Debug-build-only status message shown after logs successfully written to file -->
|
||||||
<string name="logstore_dumped_fmt">Logs written to file %1$s</string>
|
<string name="logstore_dumped_fmt">Logs written to file %1$s</string>
|
||||||
|
<!-- Debug-build-only status message shown when unable to write logs -->
|
||||||
|
<string name="logstore_notdumped">Unable to write logs</string>
|
||||||
<!-- Debug-build-only status message shown after logs successfully cleared -->
|
<!-- Debug-build-only status message shown after logs successfully cleared -->
|
||||||
<string name="logstore_cleared_fmt">%1$d log entries deleted</string>
|
<string name="logstore_cleared_fmt">%1$d log entries deleted</string>
|
||||||
<!-- Debug-build-only question asked to confirm deletion of saved logs -->
|
<!-- Debug-build-only question asked to confirm deletion of saved logs -->
|
||||||
|
|
|
@ -768,43 +768,25 @@ deleteLocalRefs( JNIEnv* env, ... )
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static int g_log_count = 0;
|
|
||||||
static pthread_mutex_t g_log_count_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
/* A bunch of threads are generating log statements. */
|
/* A bunch of threads are generating log statements. */
|
||||||
static void
|
static void
|
||||||
passToJava( const char* tag, const char* msg )
|
passToJava( const char* tag, const char* msg )
|
||||||
{
|
{
|
||||||
if ( 1 ) {
|
JNIEnv* env = waitEnvFromGlobals();
|
||||||
pthread_mutex_lock( &g_log_count_lock );
|
if ( !!env ) {
|
||||||
int lockCount = ++g_log_count;
|
jstring jtag = (*env)->NewStringUTF( env, tag );
|
||||||
RAW_LOG( "lockCount: %d", lockCount );
|
jstring jbuf = (*env)->NewStringUTF( env, msg );
|
||||||
pthread_mutex_unlock( &g_log_count_lock );
|
jclass clazz = (*env)->FindClass( env, PKG_PATH("Log") );
|
||||||
|
XP_ASSERT( !!clazz );
|
||||||
|
jmethodID mid = (*env)->GetStaticMethodID( env, clazz, "store",
|
||||||
|
"(Ljava/lang/String;Ljava/lang/String;)V" );
|
||||||
|
(*env)->CallStaticVoidMethod( env, clazz, mid, jtag, jbuf );
|
||||||
|
deleteLocalRefs( env, clazz, jtag, jbuf, DELETE_NO_REF );
|
||||||
|
|
||||||
/* Now pass into Log.java for possible writing to DB */
|
releaseEnvFromGlobals( env );
|
||||||
if ( 1 == lockCount ) {
|
} else {
|
||||||
JNIEnv* env = waitEnvFromGlobals();
|
RAW_LOG( "env is NULL; dropping" );
|
||||||
if ( !!env ) {
|
|
||||||
jstring jtag = (*env)->NewStringUTF( env, tag );
|
|
||||||
jstring jbuf = (*env)->NewStringUTF( env, msg );
|
|
||||||
jclass clazz = (*env)->FindClass( env, PKG_PATH("Log") );
|
|
||||||
XP_ASSERT( !!clazz );
|
|
||||||
jmethodID mid = (*env)->GetStaticMethodID( env, clazz, "store",
|
|
||||||
"(Ljava/lang/String;Ljava/lang/String;)V" );
|
|
||||||
(*env)->CallStaticVoidMethod( env, clazz, mid, jtag, jbuf );
|
|
||||||
deleteLocalRefs( env, clazz, jtag, jbuf, DELETE_NO_REF );
|
|
||||||
|
|
||||||
releaseEnvFromGlobals( env );
|
|
||||||
} else {
|
|
||||||
RAW_LOG( "env is NULL; dropping" );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
RAW_LOG( "recursing! Skipping msg %s", msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock( &g_log_count_lock );
|
|
||||||
--g_log_count;
|
|
||||||
pthread_mutex_unlock( &g_log_count_lock );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,11 @@ JNIEnv* waitEnvFromGlobals();
|
||||||
void releaseEnvFromGlobals( JNIEnv* env );
|
void releaseEnvFromGlobals( JNIEnv* env );
|
||||||
|
|
||||||
void raw_log( const char* func, const char* fmt, ... );
|
void raw_log( const char* func, const char* fmt, ... );
|
||||||
#define RAW_LOG(...) raw_log( __func__, __VA_ARGS__ )
|
#ifdef DEBUG
|
||||||
|
# define RAW_LOG(...) raw_log( __func__, __VA_ARGS__ )
|
||||||
|
#else
|
||||||
|
# define RAW_LOG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
# define DELETE_NO_REF ((jobject)-1) /* terminates above varargs list */
|
# define DELETE_NO_REF ((jobject)-1) /* terminates above varargs list */
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue