Return-Path: X-Original-To: apmail-incubator-chukwa-user-archive@www.apache.org Delivered-To: apmail-incubator-chukwa-user-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D0ABAC40F for ; Tue, 10 Jul 2012 08:37:09 +0000 (UTC) Received: (qmail 86284 invoked by uid 500); 10 Jul 2012 08:37:09 -0000 Delivered-To: apmail-incubator-chukwa-user-archive@incubator.apache.org Received: (qmail 86250 invoked by uid 500); 10 Jul 2012 08:37:08 -0000 Mailing-List: contact chukwa-user-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: chukwa-user@incubator.apache.org Delivered-To: mailing list chukwa-user@incubator.apache.org Received: (qmail 86223 invoked by uid 99); 10 Jul 2012 08:37:07 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 10 Jul 2012 08:37:07 +0000 X-ASF-Spam-Status: No, hits=1.5 required=5.0 tests=FSL_RCVD_USER,HTML_MESSAGE,RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of afathalla@gmail.com designates 209.85.215.175 as permitted sender) Received: from [209.85.215.175] (HELO mail-ey0-f175.google.com) (209.85.215.175) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 10 Jul 2012 08:37:01 +0000 Received: by eaal1 with SMTP id l1so4322985eaa.6 for ; Tue, 10 Jul 2012 01:36:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=6AbxySsmewxD00v4IcyEZ9dMjR76OLucIZtsL9Y2Rr8=; b=WsfKigMSEgveDLn1yLmmZUL9IfZxQPRHNsHD4ebkxrFTraoA9vEDw1yT9hrR0sH0LC 2wxStGplqfjISIfE6YzzjjsaSz+uzwvOx2ndHPqj7lRYkeN5RkbUCFaAsqJP2X/R3VfM 7o6YOStJGj/gu+ek2I3Doj0Dz2L3eJPe0d3YKckB0Ho5eo8geV9jnUX3VoRY4XCxd7F0 m12Gz/HlW3+VeQ8twInBxSJK/qyNKa6Sx17xfC8T8gyLh8k44OtWhq7xETmQk/CneP6r 8nVhPjLET6cbyvwIHuRBaI9YThEfDHg+Hltp7WY4FJ+0sN+7rejRuZJbMmo2KUzW1ZvF nDBQ== MIME-Version: 1.0 Received: by 10.14.27.201 with SMTP id e49mr10306392eea.230.1341909400841; Tue, 10 Jul 2012 01:36:40 -0700 (PDT) Received: by 10.14.37.138 with HTTP; Tue, 10 Jul 2012 01:36:40 -0700 (PDT) In-Reply-To: References: Date: Tue, 10 Jul 2012 11:36:40 +0300 Message-ID: Subject: Re: Change the FileTailingAdaptor tailFile(),let it apply to the log4j rotated log files From: Ahmed Fathalla To: chukwa-user@incubator.apache.org Content-Type: multipart/alternative; boundary=bcaec539687c28705604c475a141 --bcaec539687c28705604c475a141 Content-Type: text/plain; charset=ISO-8859-1 Ivy, Thanks alot for your contributions! However, a better way to submit patches to Chukwa is: 1-Open a JIRA issue on https://issues.apache.org/jira/browse/CHUKWA I think you will need to register on JIRA first in order to create issues 2- Generate a .patch file using eclipse or command line tools, the .patch file will be a single file with all the changes you have done. 3- Using the "Submit Patch" option on the JIRA issue upload the file. Your changes will be reviewed by a committer and committed if everything i okay. Thank you again for your interest in Chukwa and we really appreciate your proactive approach in contributing back to the project! On Tue, Jul 10, 2012 at 10:04 AM, IvyTang wrote: > Our team has used chukwa *CharFileTailingAdaptorUTF8* to collect the > log4j rotated log files for several months.It does help us to collect the > logs from everywhere to our hadoop center. > During the work , we met several problems . And i have raised them in this > mail list , but i still haven't got a good solution. > So we read the source code , and did some changes > > Our log files are generated by the log4j ,and the log4j appender is > org.apache.log4j.DailyRollingFileAppender. > If you use log4j to generate the rotated log ,may this mail will help you. > > These two problems are the causes why we have to modify the source code. > > 1. The mismatching checkpoint size and file size. > > I raised this problem in May 14 ,"the check point offset is bigger > than the log file size". And Ariel Rabkin and Eric have answered my > question , thanks for your replies. > > When chukwa starts, it will read the the check point file , let the > size be the filereadoffset. The size in the checkpoint indicates how many > bytes the adaptor has send . > > If the log source is stream or a file won't rotate , this size is > right ,it indeed is the filereadoffset.But the file is rorated , the > checkpoint size is often bigger than the file size ,and this will cause > chukwa resend all the log file. > > So we add a "log.info("chunk seqID:"+c.getSeqID());" in > ChukwaHttpSender:send. > > *for (Chunk c : toSend) { > DataOutputBuffer b = new > DataOutputBuffer(c.getSerializedSizeEstimate()); > try { > c.write(b); > } catch (IOException err) { > log.error("serialization threw IOException", err); > } > serializedEvents.add(b); > // store a CLE for this chunk which we will use to ack this chunk to > the > // caller of send() > // (e.g. the agent will use the list of CLE's for checkpointing) > log.info("chunk seqID:"+c.getSeqID()); > commitResults.add(new CommitListEntry(c.getInitiator(), > c.getSeqID(), > c.getSeqID() - c.getData().length)); > }* > * > **The seqid is the offset of the send chunks in this log file.** > * So when we need to restart the chukwa, we just need to stop the > chukwa , change the size in checkpoint to the last chunk seqid in log and > start chukwa. > We also can directly apply the seqID to checkpoint size ,but we > don't know if this will cause other problems. > * > > *2.* *The method tailFile in FileTailingAdaptor is the core code of > collecting the log. The code use the fileReadOffset , file length to detect > the rotated file. > *RandomAccessFile newReader = new RandomAccessFile(toWatch, "r");* > * len = reader.length();* > * long newLength = newReader.length();* > * if (newLength < len && fileReadOffset >= len) {* > * if (reader != null) {* > * reader.close();* > * }* > * * > * reader = newReader;* > * fileReadOffset = 0L;* > * log.debug("Adaptor|"+ adaptorID + "| File size mismatched, > rotating: "* > * + toWatch.getAbsolutePath());* > * } else {* > * try {* > * if (newReader != null) {* > * newReader.close();* > * }* > * newReader =null;* > * } catch (Throwable e) {* > * // do nothing.* > * }* > * }* > * > * > * *This arithmetic does work in most cases. But there is a case ,that > when chukwa starts , the log file is 0 and it will be 0 untill it has been > rotated. After it has been rotated ,becase its size is 0 ,this log will be > removed. A new file has generated , and its size isn't 0. > But the len is still 0 ,newLength is > 0.So this contition if > (newLength < len && fileReadOffset >= len) will never be archived. The new > log file will never be detected. > > So we changed the implemention of this method, we use timestamp to > detect the new log file.The lastSlurpTime is the timestamp of the last > slurp ,it is been declared and assigned in LWFTAdaptor . > try { > len = reader.length(); > if(lastSlurpTime == 0){ > lastSlurpTime = System.currentTimeMillis(); > } > if (offsetOfFirstByte > fileReadOffset) { > // If the file rotated, the recorded offsetOfFirstByte > is greater than > // file size,reset the first byte position to > beginning of the file. > fileReadOffset = 0; > offsetOfFirstByte = 0L; > log.warn("offsetOfFirstByte>fileReadOffset, resetting > offset to 0"); > } > if (len == fileReadOffset) { > File fixedNameFile = new > File(toWatch.getAbsolutePath()); > long fixedNameLastModified = > fixedNameFile.lastModified(); > if (fixedNameLastModified > lastSlurpTime) { > // If len == fileReadOffset,the file stops rolling > log or the file has rotated. > // But fixedNameLastModified > lastSlurpTime , > this means after the last slurping,the file has been written . > // so the file has been rotated. > boolean hasLeftData = true; > while(hasLeftData){// read the possiblly generated > log > hasLeftData = slurp(len, reader); > } > RandomAccessFile newReader = new > RandomAccessFile(toWatch, "r"); > if (reader != null) { > reader.close(); > } > reader = newReader; > fileReadOffset = 0L; > len = reader.length(); > log.debug("Adaptor|" + adaptorID + "| File size > mismatched, rotating: " + > toWatch.getAbsolutePath()); > } > hasMoreData = slurp(len, reader); > } else if (len < fileReadOffset) { > // file has rotated and no detection > if (reader != null) { > reader.close(); > } > reader = null; > fileReadOffset = 0L; > offsetOfFirstByte = 0L; > hasMoreData = true; > log.warn("Adaptor|" + adaptorID + "| file: " + > toWatch.getPath() > + ", has rotated and no detection - reset > counters to 0L"); > } else { > hasMoreData = slurp(len, reader); > } > > > We hope these two changes will help the adaptor collect the rotated file > more well. > > If these is anything wrong ,please let me know, > > Thanks! > > > > -- > Best regards, > > Ivy Tang > > > > -- Ahmed Fathalla --bcaec539687c28705604c475a141 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Ivy,

Thanks alot for your contributions= ! =A0

However, a better way to submit patches to C= hukwa is:

1-Open a JIRA issue on


I think you wi= ll need to register on JIRA first in order to create issues

2- Generate a .patch file using eclipse or command line tools, t= he .patch file will be a single file with all the changes you have done.


3- Using the "Submit Patch"= option on the JIRA issue upload the file. Your changes will be reviewed by= a committer and committed if everything i okay.

Thank you again for your interest in Chukwa and we real= ly appreciate your proactive approach in contributing back to the project!<= /div>

On Tue, Jul 10, 2012 at 10:04 AM, = IvyTang <ivytang0812@gmail.com> wrote:
Our team has used chukwa CharFileTailingA= daptorUTF8 to collect the log4j rotated log files for several months.It= does help us to collect the logs from everywhere to our hadoop center.
During the work , we met several problems . And i have raised them in this = mail list , but i still haven't got a good solution.
So we=A0 read the source code , and did some changes

Our log files a= re generated by the log4j ,and the log4j appender is org.apache.log4j.Daily= RollingFileAppender.
If you use log4j to generate the rotated log ,may t= his mail will help you.

These two problems are the causes why we have to modify the source code= .

1. The mismatching checkpoint size and file size.

=A0=A0=A0= =A0 I raised this problem in May 14 ,"the check point offset is bigger= than the log file size". And Ariel Rabkin=A0 and Eric have answered m= y question , thanks for your replies.

=A0=A0=A0=A0 When chukwa starts, it will read the the check point file = , let the size be the filereadoffset. The size in the checkpoint indicates = how many bytes the adaptor has send .

=A0=A0=A0=A0 If the log source= is stream or a file won't rotate , this size is right ,it indeed is th= e filereadoffset.But the file is rorated , the checkpoint size is often big= ger than the file size ,and this will cause chukwa resend all the log file.=

=A0=A0=A0=A0 So we add a "log.info("chunk seqID:"+c.getSeqID());" in ChukwaH= ttpSender:send.

=A0=A0=A0=A0 for (Chunk c : toSend) {
=A0=A0= =A0=A0=A0 DataOutputBuffer b =3D new DataOutputBuffer(c.getSerializedSizeEs= timate());
=A0=A0=A0=A0=A0 try {
=A0=A0=A0=A0=A0=A0=A0 c.write(b);
=A0=A0=A0=A0= =A0 } catch (IOException err) {
=A0=A0=A0=A0=A0=A0=A0 log.error("se= rialization threw IOException", err);
=A0=A0=A0=A0=A0 }
=A0=A0= =A0=A0=A0 serializedEvents.add(b);
=A0=A0=A0=A0=A0 // store a CLE for th= is chunk which we will use to ack this chunk to the
=A0=A0=A0=A0=A0 // caller of send()
=A0=A0=A0=A0=A0 // (e.g. the agent w= ill use the list of CLE's for checkpointing)
=A0=A0=A0=A0=A0 log.info("chunk seqID:"= ;+c.getSeqID());
=A0=A0=A0=A0=A0 commitResults.add(new CommitListEntry(c= .getInitiator(), c.getSeqID(),
=A0=A0=A0=A0=A0=A0=A0=A0 c.getSeqID() - c.getData().length));
=A0=A0=A0 = }

=A0=A0=A0=A0
=A0=A0=A0
The seqid is the offset of th= e send chunks in this log file.
=A0=A0=A0
So when we need to = restart the chukwa, we just need to stop the chukwa , change the size in checkpoint to the last chunk seqid in log and start=20 chukwa. =A0=A0
=A0 =A0 =A0 We also can directly apply the seqID to checkpoint s= ize ,but we=20 don't know if this will cause other problems.


2. The method tailFile in FileTailingAdaptor is the core cod= e of collecting the log. The code use the=A0fileReadOffset , file length to= detect the rotated file.
=A0 =A0 =A0 =A0=A0RandomAccessFile newRead= er =3D new RandomAccessFile(toWatch, "r");
=A0 =A0 =A0 =A0 len =3D reader.length();
=A0 =A0 =A0 = =A0 long newLength =3D newReader.length();
=A0 =A0 =A0 =A0= if (newLength < len && fileReadOffset >=3D len) {
<= div>=A0 =A0 =A0 =A0 =A0 if (reader !=3D null) {
=A0 =A0 =A0 =A0 =A0 =A0 reader.close();
=A0 =A0 = =A0 =A0 =A0 }
=A0 =A0 =A0 =A0 =A0=A0
=A0 = =A0 =A0 =A0 =A0 reader =3D newReader;
=A0 =A0 =A0 =A0 =A0 = fileReadOffset =3D 0L;
=A0 =A0 =A0 =A0 =A0 log.debug("= ;Adaptor|"+ adaptorID + "| File size mismatched, rotating: "=
=A0 =A0 =A0 =A0 =A0 =A0 =A0 + toWatch.getAbsolutePath());
=
=A0 =A0 =A0 =A0 } else {
=A0 =A0 =A0 =A0 =A0 try {=
=A0 =A0 =A0 =A0 =A0 =A0 if (newReader !=3D null) {
=A0 =A0 =A0 =A0 =A0 =A0 =A0 newReader.close();
=A0 =A0 =A0 =A0 =A0 =A0 }
=A0 =A0 =A0 =A0 =A0 =A0 = newReader =3Dnull;
=A0 =A0 =A0 =A0 =A0 } catch (Throwable = e) {
=A0 =A0 =A0 =A0 =A0 =A0 // do nothing.
= =A0 =A0 =A0 =A0 =A0 }
=A0 =A0 =A0 =A0 }

=A0 =A0 =A0This=A0arithmetic does work in= most cases. But there is a case ,that when chukwa starts , the log file is= 0 and it will be 0 untill it has been rotated. After it has been rotated ,= becase its size is 0 ,this log will be removed. A new file has generated , = and its size isn't 0.
=A0 =A0 =A0 But the len is still 0 ,newLength is > 0.So this contit= ion=A0=A0if (newLength < len && fileReadOffset >=3D len) =A0w= ill never be archived. The new log file will never be detected.
<= br>
=A0 =A0 =A0 =A0So we changed the implemention of this method, we use timest= amp to detect the new log file.The lastSlurpTime is the timestamp of the la= st slurp ,it is been declared and assigned in LWFTAdaptor . =A0=A0
=A0= =A0=A0=A0=A0=A0 try {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 len =3D reader.length();
= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 if(lastSlurpTime =3D=3D 0){=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 lastSlurpTime = =3D System.currentTimeMillis();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 }
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 if (offsetOfFirst= Byte > fileReadOffset) {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // If the file ro= tated, the recorded offsetOfFirstByte is greater than
=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // file size,reset the first byte p= osition to beginning of the file.
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 fileReadOffset =3D 0;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 offsetOfFirstByte= =3D 0L;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 log.w= arn("offsetOfFirstByte>fileReadOffset, resetting offset to 0")= ;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 if (len =3D=3D fileReadOffset) {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 File fixedNameFil= e =3D new File(toWatch.getAbsolutePath());
=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 long fixedNameLastModified =3D fixedNameFile= .lastModified();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 if (fixedNameLastModified > lastSlurpTime) {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // If= len =3D=3D fileReadOffset,the file stops rolling log or the file has rotat= ed.
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 // But fixedNameLastModified > lastSlurpTime , this means after the = last slurping,the file has been written .
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // so= the file has been rotated.
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0 boolean hasLeftData =3D true;
=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 while(hasLeftData= ){// read the possiblly generated log
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 hasLeftData =3D slurp(len,= reader);
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }
= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Rando= mAccessFile newReader =3D new RandomAccessFile(toWatch, "r");
= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 if (r= eader !=3D null) {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 reader.close();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }
= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 reade= r =3D newReader;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 fileReadOffset =3D 0L;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 len =3D reader.length();
=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 log.debug(&quo= t;Adaptor|" + adaptorID + "| File size mismatched, rotating: &quo= t; + toWatch.getAbsolutePath());=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }
=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 hasMoreData =3D slurp(len,= reader);
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 } else if (len &= lt; fileReadOffset) {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 // file has rotated and no detection
=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 if (reader !=3D null) {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 reade= r.close();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 reader =3D null= ;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 fileReadOffs= et =3D 0L;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 off= setOfFirstByte =3D 0L;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 hasMoreData =3D true;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 log.warn("Ad= aptor|" + adaptorID + "| file: " + toWatch.getPath()
=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 + ", has rotated and no detection - reset counters to 0L");=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 } else {=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 hasMoreData =3D s= lurp(len, reader);
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }

We hope these two changes will help the adaptor collect the rotated f= ile more well.

If these is anything wrong ,please let me know,

Thanks!
=A0=A0=A0


--
Best regards,

Ivy Tang






--
Ahmed Fathal= la
--bcaec539687c28705604c475a141--