Permalink
Browse files

NEXUS-5372: Alternative fix

Introduced new format, to replace the old broken
format, while keeping backward compat. In cases when
records are no longer than 255 bytes at least.
  • Loading branch information...
1 parent 48cb872 commit b2c1f7a4272da01e1363f360c3bbfd4b0f8b53eb @cstamas cstamas committed Nov 13, 2012
@@ -47,25 +47,50 @@
public class DefaultTimelinePersistor
{
- @Deprecated
- private static final String V1_DATA_FILE_NAME_DATE_FORMAT = "yyyy-MM-dd.HH-mm-ss";
+ private enum Version
+ {
+ V1, V2, V3;
+ }
- @Deprecated
- private static final Pattern V1_DATA_FILE_NAME_PATTERN =
- Pattern.compile( "^timeline\\.(\\d{4}-\\d{2}-\\d{2}\\.\\d{2}-\\d{2}-\\d{2})\\.dat$" );
+ // == V3
- // ==
+ private static final String V3_DATA_FILE_NAME_PREFIX = "timeline.";
+
+ private static final String V3_DATA_FILE_NAME_SUFFIX = "-v3.dat";
+
+ private static final String V3_DATA_FILE_NAME_DATE_FORMAT = "yyyy-MM-dd.HH-mm-ssZ";
+
+ private static final Pattern V3_DATA_FILE_NAME_PATTERN = Pattern.compile( "^" + V3_DATA_FILE_NAME_PREFIX.replace(
+ ".", "\\." ) + "(\\d{4}-\\d{2}-\\d{2}\\.\\d{2}-\\d{2}-\\d{2}[+-]\\d{4})" + V3_DATA_FILE_NAME_SUFFIX.replace(
+ ".", "\\." ) + "$" );
+
+ // == V2
- private static final String V2_DATA_FILE_NAME_PREFIX = "timeline.";
+ @Deprecated
+ private static final String V2_DATA_FILE_NAME_PREFIX = V3_DATA_FILE_NAME_PREFIX;
+ @Deprecated
private static final String V2_DATA_FILE_NAME_SUFFIX = ".dat";
- private static final String V2_DATA_FILE_NAME_DATE_FORMAT = "yyyy-MM-dd.HH-mm-ssZ";
+ @Deprecated
+ private static final String V2_DATA_FILE_NAME_DATE_FORMAT = V3_DATA_FILE_NAME_DATE_FORMAT;
+ @Deprecated
private static final Pattern V2_DATA_FILE_NAME_PATTERN = Pattern.compile( "^" + V2_DATA_FILE_NAME_PREFIX.replace(
".", "\\." ) + "(\\d{4}-\\d{2}-\\d{2}\\.\\d{2}-\\d{2}-\\d{2}[+-]\\d{4})" + V2_DATA_FILE_NAME_SUFFIX.replace(
".", "\\." ) + "$" );
+ // == V1
+
+ @Deprecated
+ private static final String V1_DATA_FILE_NAME_DATE_FORMAT = "yyyy-MM-dd.HH-mm-ss";
+
+ @Deprecated
+ private static final Pattern V1_DATA_FILE_NAME_PATTERN =
+ Pattern.compile( "^timeline\\.(\\d{4}-\\d{2}-\\d{2}\\.\\d{2}-\\d{2}-\\d{2})\\.dat$" );
+
+ // ==
+
private int rollingIntervalMillis;
private File persistDirectory;
@@ -106,14 +131,12 @@ protected synchronized void persist( final TimelineRecord... records )
OutputStream out = null;
try
{
+ out = new FileOutputStream( getDataFile(), true );
for ( TimelineRecord record : records )
{
- out = new FileOutputStream( getDataFile(), true );
- byte[] bytes = toProto( record ).toByteArray();
- out.write( bytes.length );
- out.write( bytes );
- out.flush();
+ toProto( record ).writeDelimitedTo( out );
}
+ out.flush();
}
finally
{
@@ -163,7 +186,8 @@ protected void readAllSinceDays( final int days, final TimelineCallback callback
{
public boolean accept( File dir, String fname )
{
- return V2_DATA_FILE_NAME_PATTERN.matcher( fname ).matches()
+ return V3_DATA_FILE_NAME_PATTERN.matcher( fname ).matches()
+ || V2_DATA_FILE_NAME_PATTERN.matcher( fname ).matches()
|| V1_DATA_FILE_NAME_PATTERN.matcher( fname ).matches();
}
} );
@@ -240,8 +264,12 @@ else if ( filePtr >= result.size() )
}
else
{
+ final File file = result.get( filePtr );
+ // V1 and V2 uses same format, so for reading telling is it V3 or less is enough
+ final Version version =
+ V3_DATA_FILE_NAME_PATTERN.matcher( file.getName() ).matches() ? Version.V3 : Version.V2;
// jump to next file
- currentIterator = readFile( result.get( filePtr ) );
+ currentIterator = readFile( version, file );
filePtr++;
continue;
}
@@ -255,19 +283,33 @@ else if ( filePtr >= result.size() )
* @param file
* @return
*/
- protected Iterator<TimelineRecord> readFile( File file )
+ protected Iterator<TimelineRecord> readFile( Version version, File file )
{
final ArrayList<TimelineRecord> result = new ArrayList<TimelineRecord>();
InputStream in = null;
try
{
in = new FileInputStream( file );
- while ( in.available() > 0 )
+ if ( Version.V3 == version )
{
- int length = in.read();
- byte[] bytes = new byte[length];
- in.read( bytes, 0, length );
- result.add( fromProto( TimeLineRecordProtos.TimeLineRecord.parseFrom( bytes ) ) );
+ // V3 uses delimited format
+ TimelineRecord rec = fromProto( TimeLineRecordProtos.TimeLineRecord.parseDelimitedFrom( in ) );
+ while ( rec != null )
+ {
+ result.add( rec );
+ rec = fromProto( TimeLineRecordProtos.TimeLineRecord.parseDelimitedFrom( in ) );
+ }
+ }
+ else
+ {
+ // V1 and V2 suffers from NEXUS-5372
+ while ( in.available() > 0 )
+ {
+ int length = in.read();
+ byte[] bytes = new byte[length];
+ in.read( bytes, 0, length );
+ result.add( fromProto( TimeLineRecordProtos.TimeLineRecord.parseFrom( bytes ) ) );
+ }
}
}
catch ( Exception e )
@@ -276,23 +318,18 @@ else if ( filePtr >= result.size() )
}
finally
{
- if ( in != null )
- {
- try
- {
- in.close();
- }
- catch ( IOException e )
- {
- }
- }
+ IOUtil.close( in );
}
return result.iterator();
}
protected TimelineRecord fromProto( TimeLineRecordProtos.TimeLineRecord rec )
{
+ if ( rec == null )
+ {
+ return null;
+ }
final Map<String, String> dataMap = new HashMap<String, String>();
for ( TimeLineRecordProtos.TimeLineRecord.Data data : rec.getDataList() )
{
@@ -305,20 +342,34 @@ protected TimelineRecord fromProto( TimeLineRecordProtos.TimeLineRecord rec )
protected String buildTimestampedFileName()
{
- final SimpleDateFormat dateFormat = new SimpleDateFormat( V2_DATA_FILE_NAME_DATE_FORMAT );
+ final SimpleDateFormat dateFormat = new SimpleDateFormat( V3_DATA_FILE_NAME_DATE_FORMAT );
final StringBuilder fileName = new StringBuilder();
- fileName.append( V2_DATA_FILE_NAME_PREFIX ).append(
+ fileName.append( V3_DATA_FILE_NAME_PREFIX ).append(
dateFormat.format( new Date( System.currentTimeMillis() ) ) ).append(
- V2_DATA_FILE_NAME_SUFFIX );
+ V3_DATA_FILE_NAME_SUFFIX );
return fileName.toString();
}
protected long getTimestampedFileNameTimestamp( final File file )
{
- final Matcher fnMatcher = V2_DATA_FILE_NAME_PATTERN.matcher( file.getName() );
- if ( fnMatcher.matches() )
+ final Matcher v3FnMatcher = V3_DATA_FILE_NAME_PATTERN.matcher( file.getName() );
+ if ( v3FnMatcher.matches() )
+ {
+ final String datePattern = v3FnMatcher.group( 1 );
+ try
+ {
+ return new SimpleDateFormat( V3_DATA_FILE_NAME_DATE_FORMAT ).parse( datePattern ).getTime();
+ }
+ catch ( ParseException e )
+ {
+ // silently go to next try
+ }
+ }
+
+ final Matcher v2FnMatcher = V2_DATA_FILE_NAME_PATTERN.matcher( file.getName() );
+ if ( v2FnMatcher.matches() )
{
- final String datePattern = fnMatcher.group( 1 );
+ final String datePattern = v2FnMatcher.group( 1 );
try
{
return new SimpleDateFormat( V2_DATA_FILE_NAME_DATE_FORMAT ).parse( datePattern ).getTime();
@@ -329,10 +380,10 @@ protected long getTimestampedFileNameTimestamp( final File file )
}
}
- final Matcher oldFnMatcher = V1_DATA_FILE_NAME_PATTERN.matcher( file.getName() );
- if ( oldFnMatcher.matches() )
+ final Matcher v1FnMatcher = V1_DATA_FILE_NAME_PATTERN.matcher( file.getName() );
+ if ( v1FnMatcher.matches() )
{
- final String datePattern = oldFnMatcher.group( 1 );
+ final String datePattern = v1FnMatcher.group( 1 );
try
{
return new SimpleDateFormat( V1_DATA_FILE_NAME_DATE_FORMAT ).parse( datePattern ).getTime();

0 comments on commit b2c1f7a

Please sign in to comment.