@@ -56,7 +56,8 @@ static int my_validate_index(const struct cache_time *mtime_reported)
5656	mtime_observed_on_disk .nsec  =  ST_MTIME_NSEC (st );
5757	if  ((mtime_observed_on_disk .sec  !=  mtime_reported -> sec ) || 
5858	    (mtime_observed_on_disk .nsec  !=  mtime_reported -> nsec )) {
59- 		trace_printf_key (& trace_deserialize , "index mtime changed [des %d.%d][obs %d.%d]" ,
59+ 		trace_printf_key (& trace_deserialize ,
60+ 				 "index mtime changed [des %d %d][obs %d %d]" ,
6061			     mtime_reported -> sec , mtime_reported -> nsec ,
6162			     mtime_observed_on_disk .sec , mtime_observed_on_disk .nsec );
6263		return  DESERIALIZE_ERR ;
@@ -545,6 +546,8 @@ static inline int my_strcmp_null(const char *a, const char *b)
545546
546547static  int  wt_deserialize_fd (const  struct  wt_status  * cmd_s , struct  wt_status  * des_s , int  fd )
547548{
549+ 	memset (des_s , 0 , sizeof (* des_s ));
550+ 
548551	/* 
549552	 * Check the path spec on the current command 
550553	 */ 
@@ -668,33 +671,127 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de
668671	return  DESERIALIZE_OK ;
669672}
670673
674+ static  struct  cache_time  deserialize_prev_mtime  =  { 0 , 0  };
675+ 
676+ static  int  try_deserialize_read_from_file_1 (const  struct  wt_status  * cmd_s ,
677+ 					    const  char  * path ,
678+ 					    struct  wt_status  * des_s )
679+ {
680+ 	struct  stat  st ;
681+ 	int  result ;
682+ 	int  fd ;
683+ 
684+ 	/* 
685+ 	 * If we are spinning waiting for the status cache to become 
686+ 	 * valid, skip re-reading it if the mtime has not changed 
687+ 	 * since the last time we read it. 
688+ 	 */ 
689+ 	if  (lstat (path , & st )) {
690+ 		trace_printf_key (& trace_deserialize ,
691+ 				 "could not lstat '%s'" , path );
692+ 		return  DESERIALIZE_ERR ;
693+ 	}
694+ 	if  (st .st_mtime  ==  deserialize_prev_mtime .sec  && 
695+ 	    ST_MTIME_NSEC (st ) ==  deserialize_prev_mtime .nsec ) {
696+ 		trace_printf_key (& trace_deserialize ,
697+ 				 "mtime has not changed '%s'" , path );
698+ 		return  DESERIALIZE_ERR ;
699+ 	}
700+ 
701+ 	fd  =  xopen (path , O_RDONLY );
702+ 	if  (fd  ==  -1 ) {
703+ 		trace_printf_key (& trace_deserialize ,
704+ 				 "could not read '%s'" , path );
705+ 		return  DESERIALIZE_ERR ;
706+ 	}
707+ 
708+ 	deserialize_prev_mtime .sec  =  st .st_mtime ;
709+ 	deserialize_prev_mtime .nsec  =  ST_MTIME_NSEC (st );
710+ 
711+ 	trace_printf_key (& trace_deserialize ,
712+ 			 "reading serialization file (%d %d) '%s'" ,
713+ 			 deserialize_prev_mtime .sec ,
714+ 			 deserialize_prev_mtime .nsec ,
715+ 			 path );
716+ 
717+ 	result  =  wt_deserialize_fd (cmd_s , des_s , fd );
718+ 	close (fd );
719+ 
720+ 	return  result ;
721+ }
722+ 
723+ static  int  try_deserialize_read_from_file (const  struct  wt_status  * cmd_s ,
724+ 					  const  char  * path ,
725+ 					  enum  wt_status_deserialize_wait  dw ,
726+ 					  struct  wt_status  * des_s )
727+ {
728+ 	int  k , limit ;
729+ 	int  result  =  DESERIALIZE_ERR ;
730+ 
731+ 	/* 
732+ 	 * For "fail" or "no", try exactly once to read the status cache. 
733+ 	 * Return an error if the file is stale. 
734+ 	 */ 
735+ 	if  (dw  ==  DESERIALIZE_WAIT__FAIL  ||  dw  ==  DESERIALIZE_WAIT__NO )
736+ 		return  try_deserialize_read_from_file_1 (cmd_s , path , des_s );
737+ 
738+ 	/* 
739+ 	 * Wait for the status cache file to refresh.  Wait duration can 
740+ 	 * be in tenths of a second or unlimited.  Poll every 100ms. 
741+ 	 */ 
742+ 	if  (dw  ==  DESERIALIZE_WAIT__BLOCK ) {
743+ 		/* 
744+ 		 * Convert "unlimited" to 1 day. 
745+ 		 */ 
746+ 		limit  =  10  *  60  *  60  *  24 ;
747+ 	} else  {
748+ 		/* spin for dw tenths of a second */ 
749+ 		limit  =  dw ;
750+ 	}
751+ 	for  (k  =  0 ; k  <  limit ; k ++ ) {
752+ 		result  =  try_deserialize_read_from_file_1 (
753+ 			cmd_s , path , des_s );
754+ 
755+ 		if  (result  ==  DESERIALIZE_OK )
756+ 			break ;
757+ 
758+ 		sleep_millisec (100 );
759+ 	}
760+ 
761+ 	trace_printf_key (& trace_deserialize ,
762+ 			 "wait polled=%d result=%d '%s'" ,
763+ 			 k , result , path );
764+ 	return  result ;
765+ }
766+ 
671767/* 
672-  * Read raw serialized status data from the given file 
768+  * Read raw serialized status data from the given file (or STDIN).  
673769 * 
674770 * Verify that the args specified in the current command 
675771 * are compatible with the deserialized data (such as "-uno"). 
676772 * 
677773 * Copy display-related fields from the current command 
678774 * into the deserialized data (so that the user can request 
679775 * long or short as they please). 
776+  * 
777+  * Print status report using cached data. 
680778 */ 
681779int  wt_status_deserialize (const  struct  wt_status  * cmd_s ,
682- 			  const  char  * path )
780+ 			  const  char  * path ,
781+ 			  enum  wt_status_deserialize_wait  dw )
683782{
684783	struct  wt_status  des_s ;
685784	int  result ;
686785
687786	if  (path  &&  * path  &&  strcmp (path , "0" )) {
688- 		int  fd  =  xopen (path , O_RDONLY );
689- 		if  (fd  ==  -1 ) {
690- 			trace_printf_key (& trace_deserialize , "could not read '%s'" , path );
691- 			return  DESERIALIZE_ERR ;
692- 		}
693- 		trace_printf_key (& trace_deserialize , "reading serialization file '%s'" , path );
694- 		result  =  wt_deserialize_fd (cmd_s , & des_s , fd );
695- 		close (fd );
787+ 		result  =  try_deserialize_read_from_file (cmd_s , path , dw , & des_s );
696788	} else  {
697789		trace_printf_key (& trace_deserialize , "reading stdin" );
790+ 
791+ 		/* 
792+ 		 * Read status cache data from stdin.  Ignore the deserialize-wait 
793+ 		 * term, since we cannot read stdin multiple times. 
794+ 		 */ 
698795		result  =  wt_deserialize_fd (cmd_s , & des_s , 0 );
699796	}
700797
0 commit comments