Procházet zdrojové kódy

Patched problem with too many files: invoke GC followed by waiting for files to close

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6984 8c9fc860-2736-0410-a75d-ab315db34111
felixf před 8 roky
rodič
revize
6bc1225108
2 změnil soubory, kde provedl 46 přidání a 13 odebrání
  1. 45 12
      source/Generic.Unix.UnixFiles.Mod
  2. 1 1
      source/StdIOShell.Mod

+ 45 - 12
source/Generic.Unix.UnixFiles.Mod

@@ -20,7 +20,7 @@ CONST
 	Trace = {};
 VAR
 	tempno: INTEGER;
-	openfiles: INTEGER;
+	openfiles: LONGINT;
 	
 	searchPath: ARRAY 1024 OF CHAR;
 	cwd: ARRAY 256 OF CHAR;
@@ -243,7 +243,7 @@ TYPE
 
 				PROCEDURE Old0*( name: ARRAY OF CHAR ): Files.File;
 				VAR f: File;  stat: Unix.Status;  fd, r, errno, pos: LONGINT;
-					oflags: SET;  nextdir, path: Filename; 
+					oflags: SET;  nextdir, path: Filename;  fo: LONGINT;
 				BEGIN  {EXCLUSIVE}
 					IF name = "" THEN  RETURN NIL  END;
 					
@@ -265,8 +265,13 @@ TYPE
 							fd := Unix.open( ADDRESSOF( path ), oflags, {} );  errno := Unix.errno();
 							IF ((fd < 0) & (errno IN {Unix.ENFILE, Unix.EMFILE})) (* OR (fd >= FileTabSize)*)  THEN
 								(*IF fd > 0 THEN  r := Unix.p( fd )  END;*)
-								(*!GC ;*)
-								fd := Unix.open( ADDRESSOF( path ), oflags, {} );  errno := Unix.errno();
+								REPEAT
+									TRACE(errno, openfiles);
+									fo := openfiles;
+									Kernel.GC;
+									WaitClose(fo);
+									fd := Unix.open( ADDRESSOF( path ), oflags, {} );  errno := Unix.errno();
+								UNTIL (fd >= 0) OR ~ (errno IN  {Unix.ENFILE, Unix.EMFILE})
 							END;
 
 							IF fd >= 0 THEN
@@ -292,7 +297,7 @@ TYPE
 									END;
 									f.key := NoKey;  f.fs := SELF;
 									(*fileTab[fd].f := f;  (* cache file *)*)
-									INC( openfiles );  
+									IncOpenFiles();
 									collection.AddOld(f);
 									(*RegisterFinalizer( f, Cleanup );*)
 									EXIT
@@ -515,7 +520,7 @@ TYPE
 
 				PROCEDURE CreateUnixFile;
 				VAR 
-					stat: Unix.Status;  done: BOOLEAN;  r: LONGINT;
+					stat: Unix.Status;  done: BOOLEAN;  errno,fo: LONGINT;
 				BEGIN
 					IF state = Create THEN  
 						GetTempName( registerName, workName );  tempFile := TRUE
@@ -526,16 +531,26 @@ TYPE
 							RETURN;
 						END;
 					END;
-					r := Unix.unlink( ADDRESSOF( workName ) );
+					errno := Unix.unlink( ADDRESSOF( workName ) );
 					(*unlink first to avoid stale NFS handles and to avoid reuse of inodes*)
 					
 					(*IF (FileTabSize - openfiles) < ResFiles THEN  Kernel.GC  END;*)
 						
 					fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr );
-					done := fd >= 0;  r := Unix.errno();
-					IF (~done & (r IN {Unix.ENFILE, Unix.EMFILE})) THEN
+					done := fd >= 0;  errno := Unix.errno();
+					IF (~done & (errno IN {Unix.ENFILE, Unix.EMFILE})) THEN
+						REPEAT
+							TRACE(errno, openfiles);
+							fo := openfiles;
+							Kernel.GC;
+							WaitClose(fo);
+							fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr);  errno := Unix.errno();
+						UNTIL (fd >= 0) OR ~ (errno IN  {Unix.ENFILE, Unix.EMFILE});
+						(*
+						TRACE(r, openfiles);
 						Kernel.GC; (*! + wait ? *)
 						fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr );
+						*)
 						done := fd >= 0
 					END;
 					IF done THEN
@@ -543,11 +558,11 @@ TYPE
 							r := Unix.close( fd );  
 							Halt( SELF, FALSE, "UnixFiles.File.Create: too many files open" )
 						ELSE*)
-							r := Unix.fstat( fd, stat );  
+							errno := Unix.fstat( fd, stat );  
 							dev := stat.dev;  ino := stat.ino;  mtime := stat.mtime.sec;
 							state := Open;  fpos := 0;
 							(*fileTab[fd].f := SELF;*)
-							INC( openfiles );  
+							IncOpenFiles();
 							
 							collection.AddNew(SELF);
 
@@ -813,7 +828,8 @@ TYPE
 							fd := NoDesc;
 						END;
 					END;
-					DEC( openfiles );  state := Closed;
+					DecOpenFiles();
+					state := Closed;
 				END Finalize;
 				
 				PROCEDURE Close;
@@ -1150,6 +1166,23 @@ TYPE
 		collection.Finalize;
 		unixFS.Finalize;
 	END Finalization;
+	
+	PROCEDURE DecOpenFiles;
+	BEGIN{EXCLUSIVE}
+		DEC(openfiles);
+	END DecOpenFiles;
+
+	PROCEDURE IncOpenFiles;
+	BEGIN{EXCLUSIVE}
+		INC(openfiles);
+	END IncOpenFiles;
+	
+	
+	PROCEDURE WaitClose(no: LONGINT);
+	BEGIN{EXCLUSIVE}
+		AWAIT(openfiles < no);
+	END WaitClose;
+	
 
 BEGIN
 	Initialize;

+ 1 - 1
source/StdIOShell.Mod

@@ -45,7 +45,7 @@ SystemTools.DoCommands
 		Unix.StdIO.Mod Generic.Unix.Traps.Mod Locks.Mod Unix.Clock.Mod Disks.Mod Files.Mod Dates.Mod Strings.Mod 
 		UTF8Strings.Mod FileTrapWriter.Mod Caches.Mod DiskVolumes.Mod OldDiskVolumes.Mod RAMVolumes.Mod 
 		DiskFS.Mod OldDiskFS.Mod OberonFS.Mod FATVolumes.Mod FATFiles.Mod ISO9660Volumes.Mod 
-		ISO9660Files.Mod Generic.Unix.UnixFiles.Mod RelativeFileSystem.Mod BitSets.Mod StringPool.Mod DIagnostics.Mod 
+		ISO9660Files.Mod Generic.Unix.UnixFiles.Mod RelativeFileSystem.Mod BitSets.Mod StringPool.Mod Diagnostics.Mod 
 		ObjectFile.Mod GenericLinker.Mod GenericLoader.Mod Unix.BootConsole.Mod 
 		Pipes.Mod Shell.Mod StdIOShell.Mod