Browse Source

added support of multi-part files larger than MAX(LONGINT)

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@8200 8c9fc860-2736-0410-a75d-ab315db34111
eth.morozova 7 years ago
parent
commit
2d419eee62
1 changed files with 142 additions and 94 deletions
  1. 142 94
      ARM/ARM.A2/TestFs.Mod

+ 142 - 94
ARM/ARM.A2/TestFs.Mod

@@ -1,7 +1,7 @@
 MODULE TestFs;
 MODULE TestFs;
 
 
 IMPORT
 IMPORT
-	SYSTEM, Random, Files, Kernel, Commands, FoxBasic;
+	SYSTEM, Random, Files, Kernel, Commands, FoxBasic, Strings;
 
 
 TYPE
 TYPE
 
 
@@ -10,16 +10,22 @@ TYPE
 		id: LONGINT;
 		id: LONGINT;
 		file: Files.File;
 		file: Files.File;
 		fw: Files.Writer;
 		fw: Files.Writer;
-		fileSize: LONGINT;
-		byteCount: LONGINT;
+		fileSize: HUGEINT;
+		byteCount: HUGEINT;
 		rndData, rndUpdate: Random.Generator;
 		rndData, rndUpdate: Random.Generator;
 
 
 		tStart: Kernel.MilliTimer;
 		tStart: Kernel.MilliTimer;
+		startByteCount: HUGEINT;
+
+		fileName0: Files.FileName;
+		partNum: LONGINT;
+		partByteCount: LONGINT;
 
 
 		run := FALSE, exited := FALSE: BOOLEAN;
 		run := FALSE, exited := FALSE: BOOLEAN;
 
 
-		PROCEDURE &InitWriter(id: LONGINT; CONST fileName: ARRAY OF CHAR; fileSize: LONGINT);
+		PROCEDURE &InitWriter(id: LONGINT; CONST fileName: ARRAY OF CHAR; fileSize: HUGEINT);
 		BEGIN
 		BEGIN
+			ASSERT(~exited);
 
 
 			file := Files.New(fileName);
 			file := Files.New(fileName);
 			ASSERT(file # NIL);
 			ASSERT(file # NIL);
@@ -36,6 +42,12 @@ TYPE
 			SELF.id := id;
 			SELF.id := id;
 			SELF.fileSize := fileSize;
 			SELF.fileSize := fileSize;
 
 
+			COPY(fileName,fileName0);
+			partNum := 0;
+
+			byteCount := 0;
+			partByteCount := 0;
+
 			run := TRUE;
 			run := TRUE;
 		END InitWriter;
 		END InitWriter;
 
 
@@ -65,52 +77,55 @@ TYPE
 			RETURN exited
 			RETURN exited
 		END Exited;
 		END Exited;
 
 
-		PROCEDURE Loop1;
+		PROCEDURE Loop;
 		VAR
 		VAR
 			v: LONGINT;
 			v: LONGINT;
+			strNum: ARRAY 16 OF CHAR;
+			str: Files.FileName;
 		BEGIN
 		BEGIN
-			WHILE run & (byteCount < fileSize) DO
-				v := rndData.Dice(256);
-				fw.Char(CHR(v));
-				INC(byteCount);
+			WHILE run & ((fileSize <= 0) OR (byteCount < fileSize)) & (fw.res = 0) DO
+				v := rndData.Integer();
+				fw.RawLInt(v);
+				INC(byteCount,SIZEOF(LONGINT));
+				INC(partByteCount,SIZEOF(LONGINT));
+
+				IF partByteCount MOD 0x1000000 = 0 THEN
+					Kernel.SetTimer(tStart,0);
+					startByteCount := byteCount;
+				END;
+(*
 				IF rndUpdate.Dice(4096) = 0 THEN (* Files.DefaultWriterSize *)
 				IF rndUpdate.Dice(4096) = 0 THEN (* Files.DefaultWriterSize *)
 					fw.Update;
 					fw.Update;
 				END;
 				END;
-			END;
-
-			fw.Update;
-			run := FALSE;
-		END Loop1;
-
-		PROCEDURE Loop2;
-		TYPE
-			Char4 = ARRAY 4 OF CHAR;
-		VAR
-			buf: ARRAY 4096 OF CHAR; (* Files.DefaultWriterSize *)
-			v: LONGINT;
-			i: LONGINT;
-		BEGIN
-			WHILE run & (byteCount < fileSize) & (fw.res = 0) DO
-				FOR i := 0 TO LEN(buf)-1 BY 4 DO
-					v := rndData.Integer();
-					SYSTEM.MOVE(ADDRESSOF(v),ADDRESSOF(buf[i]),SIZEOF(LONGINT));
+*)
+				IF partByteCount = 0x40000000 THEN (* 1GB parts *)
+					partByteCount := 0;
+					INC(partNum);
+					fw.Update;
+					file.Close;
+					Strings.IntToStr(partNum,strNum);
+					Strings.Concat(fileName0,".p",str);
+					Strings.Concat(str,strNum,str);
+					file := Files.New(str);
+					Files.Register(file);
+					Files.OpenWriter(fw,file,0);
+					TRACE("started a new file part",id,fileName0,partNum,byteCount);
 				END;
 				END;
-				fw.Bytes(buf,0,LEN(buf));
-				fw.Update;
-				INC(byteCount,LEN(buf));
 			END;
 			END;
 
 
-			run := FALSE;
-
 			IF fw.res # 0 THEN
 			IF fw.res # 0 THEN
 				TRACE("TestFs writer",id,"stopped due to a writer error",fw.res);
 				TRACE("TestFs writer",id,"stopped due to a writer error",fw.res);
 			END;
 			END;
-		END Loop2;
+
+			fw.Update;
+			run := FALSE;
+		END Loop;
 
 
 	BEGIN{ACTIVE}
 	BEGIN{ACTIVE}
 		Kernel.SetTimer(tStart,0);
 		Kernel.SetTimer(tStart,0);
+		startByteCount := 0;
 
 
-		Loop1;
+		Loop;
 
 
 	FINALLY
 	FINALLY
 		BEGIN{EXCLUSIVE}
 		BEGIN{EXCLUSIVE}
@@ -123,24 +138,35 @@ TYPE
 	VAR
 	VAR
 		id: LONGINT;
 		id: LONGINT;
 		file: Files.File;
 		file: Files.File;
-		reader: Files.Reader;
+		fr: Files.Reader;
 		rndData: Random.Generator;
 		rndData: Random.Generator;
-		byteCount: LONGINT;
+		byteCount: HUGEINT;
 		run, exited: BOOLEAN;
 		run, exited: BOOLEAN;
 
 
 		tStart: Kernel.MilliTimer;
 		tStart: Kernel.MilliTimer;
+		startByteCount: HUGEINT;
 
 
-		PROCEDURE & Init*(id: LONGINT; CONST filename: ARRAY OF CHAR);
+		fileName0: Files.FileName;
+		partNum: LONGINT;
+		partByteCount: LONGINT;
+
+		PROCEDURE & InitReader(id: LONGINT; CONST fileName: ARRAY OF CHAR);
 		BEGIN
 		BEGIN
 			SELF.id := id;
 			SELF.id := id;
-			file := Files.Old(filename);
+			file := Files.Old(fileName);
 			ASSERT(file # NIL);
 			ASSERT(file # NIL);
-			Files.OpenReader(reader, file, 0);
-			ASSERT(reader # NIL);
+			Files.OpenReader(fr, file, 0);
 			NEW(rndData);
 			NEW(rndData);
 			rndData.InitSeed(id);
 			rndData.InitSeed(id);
+
+			COPY(fileName,fileName0);
+			partNum := 0;
+
+			byteCount := 0;
+			partByteCount := 0;
+
 			run := TRUE;
 			run := TRUE;
-		END Init;
+		END InitReader;
 
 
 		PROCEDURE Exit;
 		PROCEDURE Exit;
 		BEGIN {EXCLUSIVE}
 		BEGIN {EXCLUSIVE}
@@ -170,18 +196,42 @@ TYPE
 
 
 		PROCEDURE Loop;
 		PROCEDURE Loop;
 		VAR
 		VAR
-			buf: ARRAY 4096 OF CHAR;
-			i, len: LONGINT;
+			v: LONGINT;
+			strNum: ARRAY 16 OF CHAR;
+			str: Files.FileName;
 		BEGIN
 		BEGIN
-			WHILE run & (reader.res = 0) DO
-				reader.Bytes(buf, 0, LEN(buf), len);
-				INC(byteCount, len);
-				FOR i := 0 TO len - 1 DO ASSERT(ORD(buf[i]) = rndData.Dice(256)); END;
-			END
+			WHILE run & (fr.res = 0) DO
+				fr.RawLInt(v);
+				INC(partByteCount, SIZEOF(LONGINT));
+				INC(byteCount, SIZEOF(LONGINT));
+				ASSERT(v = rndData.Integer());
+
+				IF partByteCount MOD 0x1000000 = 0 THEN
+					Kernel.SetTimer(tStart,0);
+					startByteCount := byteCount;
+				END;
+
+				IF partByteCount = 0x40000000 THEN (* 1GB parts *)
+					partByteCount := 0;
+					INC(partNum);
+					file.Close;
+					Strings.IntToStr(partNum,strNum);
+					Strings.Concat(fileName0,".p",str);
+					Strings.Concat(str,strNum,str);
+					file := Files.Old(str);
+					IF file = NIL THEN
+						RETURN;
+					END;
+					Files.OpenReader(fr,file,0);
+					TRACE("started a new file part",id,fileName0,partNum,byteCount);
+				END;
+			END;
 		END Loop;
 		END Loop;
 
 
 	BEGIN {ACTIVE}
 	BEGIN {ACTIVE}
 		Kernel.SetTimer(tStart, 0);
 		Kernel.SetTimer(tStart, 0);
+		startByteCount := 0;
+
 		Loop;
 		Loop;
 	FINALLY
 	FINALLY
 		BEGIN {EXCLUSIVE}
 		BEGIN {EXCLUSIVE}
@@ -206,7 +256,7 @@ VAR
 	BEGIN{EXCLUSIVE}
 	BEGIN{EXCLUSIVE}
 		IF ~ctx.arg.GetInteger(id,FALSE) THEN ctx.result := 1; RETURN; END;
 		IF ~ctx.arg.GetInteger(id,FALSE) THEN ctx.result := 1; RETURN; END;
 		IF ~ctx.arg.GetString(fileName) THEN ctx.result := 1; RETURN;END;
 		IF ~ctx.arg.GetString(fileName) THEN ctx.result := 1; RETURN;END;
-		IF ~ctx.arg.GetInteger(fileSize,FALSE) THEN ctx.result := 1; RETURN; END;
+		IF ~ctx.arg.GetInteger(fileSize,FALSE) THEN fileSize := -1; END;
 
 
 		i := 0;
 		i := 0;
 		WHILE (i < writers.Length()) & (writers.Get(i)(Writer).id # id) DO
 		WHILE (i < writers.Length()) & (writers.Get(i)(Writer).id # id) DO
@@ -273,7 +323,7 @@ VAR
 			w := writers.Get(i)(Writer);
 			w := writers.Get(i)(Writer);
 			ctx.out.String("byteCount="); ctx.out.Int(w.byteCount,0); ctx.out.Ln;
 			ctx.out.String("byteCount="); ctx.out.Int(w.byteCount,0); ctx.out.Ln;
 
 
-			speed := 1000.0 * REAL(w.byteCount) / Kernel.Elapsed(w.tStart);
+			speed := 1000.0 * REAL(w.byteCount-w.startByteCount) / Kernel.Elapsed(w.tStart);
 			ctx.out.String("overall speed="); ctx.out.FloatFix(speed,0,5,0); ctx.out.String(" bytes/s"); ctx.out.Ln;
 			ctx.out.String("overall speed="); ctx.out.FloatFix(speed,0,5,0); ctx.out.String(" bytes/s"); ctx.out.Ln;
 			ctx.out.String("status: ");
 			ctx.out.String("status: ");
 			IF w.Exited() THEN
 			IF w.Exited() THEN
@@ -292,51 +342,51 @@ VAR
 
 
 	END ReportWriter;
 	END ReportWriter;
 
 
-	PROCEDURE StartReader*(context : Commands.Context);
+	PROCEDURE StartReader*(ctx: Commands.Context);
 	VAR
 	VAR
-		name: Files.FileName;
+		fileName: Files.FileName;
 		r: Reader;
 		r: Reader;
 		id: LONGINT;
 		id: LONGINT;
 		i: LONGINT;
 		i: LONGINT;
 	BEGIN {EXCLUSIVE}
 	BEGIN {EXCLUSIVE}
-		IF ~context.arg.GetInteger(id, FALSE) THEN context.result := 1; RETURN; END;
-		IF ~context.arg.GetString(name) THEN context.result := 1; RETURN; END;
+		IF ~ctx.arg.GetInteger(id,FALSE) THEN ctx.result := 1; RETURN; END;
+		IF ~ctx.arg.GetString(fileName) THEN ctx.result := 1; RETURN;END;
 
 
 		WHILE (i < readers.Length()) & (readers.Get(i)(Reader).id # id) DO INC(i); END;
 		WHILE (i < readers.Length()) & (readers.Get(i)(Reader).id # id) DO INC(i); END;
 		IF i < readers.Length() THEN
 		IF i < readers.Length() THEN
-			context.error.String("TestFs reader with ID ");
-			context.error.Int(id, 0);
-			context.error.String(" already running.");
-			context.error.Ln;
-			context.result := 1;
+			ctx.error.String("TestFs reader with ID ");
+			ctx.error.Int(id, 0);
+			ctx.error.String(" already running.");
+			ctx.error.Ln;
+			ctx.result := 1;
 			RETURN;
 			RETURN;
 		END;
 		END;
-		NEW(r, id, name);
+		NEW(r, id, fileName);
 		readers.Add(r);
 		readers.Add(r);
 
 
-		context.out.String("Added TestFs reader with ID ");
-		context.out.Int(id, 0);
-		context.out.String(", filename='");
-		context.out.String(name);
-		context.out.String("'");
-		context.out.Ln;
+		ctx.out.String("Added TestFs reader with ID ");
+		ctx.out.Int(id, 0);
+		ctx.out.String(", fileName='");
+		ctx.out.String(fileName);
+		ctx.out.String("'");
+		ctx.out.Ln;
 	END StartReader;
 	END StartReader;
 
 
-	PROCEDURE StopReader*(context : Commands.Context);
+	PROCEDURE StopReader*(ctx: Commands.Context);
 	VAR
 	VAR
 		r: Reader;
 		r: Reader;
 		id: LONGINT;
 		id: LONGINT;
 		i: LONGINT;
 		i: LONGINT;
 	BEGIN {EXCLUSIVE}
 	BEGIN {EXCLUSIVE}
-		IF ~context.arg.GetInteger(id, FALSE) THEN context.result := 1; RETURN; END;
+		IF ~ctx.arg.GetInteger(id, FALSE) THEN ctx.result := 1; RETURN; END;
 
 
 		WHILE (i < readers.Length()) & (readers.Get(i)(Reader).id # id) DO INC(i); END;
 		WHILE (i < readers.Length()) & (readers.Get(i)(Reader).id # id) DO INC(i); END;
 		IF i = readers.Length() THEN
 		IF i = readers.Length() THEN
-			context.error.String("TestFs reader with ID ");
-			context.error.Int(id, 0);
-			context.error.String(" is not running");
-			context.error.Ln;
-			context.result := 1;
+			ctx.error.String("TestFs reader with ID ");
+			ctx.error.Int(id, 0);
+			ctx.error.String(" is not running");
+			ctx.error.Ln;
+			ctx.result := 1;
 			RETURN;
 			RETURN;
 		END;
 		END;
 
 
@@ -344,45 +394,43 @@ VAR
 		r.Exit;
 		r.Exit;
 		readers.RemoveByIndex(i);
 		readers.RemoveByIndex(i);
 
 
-		context.out.String("TestFs reader ");
-		context.out.Int(id, 0);
-		context.out.String(" stopped");
-		context.out.Ln;
+		ctx.out.String("TestFs reader ");
+		ctx.out.Int(id, 0);
+		ctx.out.String(" stopped");
+		ctx.out.Ln;
 	END StopReader;
 	END StopReader;
 
 
-	PROCEDURE ReportReader*(context : Commands.Context);
+	PROCEDURE ReportReader*(ctx: Commands.Context);
 	VAR
 	VAR
 		r: Reader;
 		r: Reader;
 		id: LONGINT;
 		id: LONGINT;
 		i: LONGINT;
 		i: LONGINT;
-		bytes: LONGINT;
 		speed: LONGREAL;
 		speed: LONGREAL;
 	BEGIN {EXCLUSIVE}
 	BEGIN {EXCLUSIVE}
-		IF ~context.arg.GetInteger(id, FALSE) THEN context.result := 1; RETURN; END;
+		IF ~ctx.arg.GetInteger(id, FALSE) THEN ctx.result := 1; RETURN; END;
 		WHILE (i < readers.Length()) & (readers.Get(i)(Reader).id # id) DO INC(i); END;
 		WHILE (i < readers.Length()) & (readers.Get(i)(Reader).id # id) DO INC(i); END;
 		IF i = readers.Length() THEN
 		IF i = readers.Length() THEN
-			context.error.String("TestFs reader with ID ");
-			context.error.Int(id, 0);
-			context.error.String(" is not running");
-			context.error.Ln;
-			context.result := 1;
+			ctx.error.String("TestFs reader with ID ");
+			ctx.error.Int(id, 0);
+			ctx.error.String(" is not running");
+			ctx.error.Ln;
+			ctx.result := 1;
 			RETURN;
 			RETURN;
 		END;
 		END;
 		r := readers.Get(i)(Reader);
 		r := readers.Get(i)(Reader);
-		bytes := r.byteCount;
-		speed := 1000.0 * bytes / Kernel.Elapsed(r.tStart);
+		speed := 1000.0 * (r.byteCount-r.startByteCount) / Kernel.Elapsed(r.tStart);
 
 
-		context.out.String("byte count="); context.out.Int(r.byteCount, 0); context.out.Ln;
-		context.out.String("overall speed="); context.out.FloatFix(speed,0,5,0); context.out.Ln;
-		context.out.String("status: ");
+		ctx.out.String("byte count="); ctx.out.Int(r.byteCount, 0); ctx.out.Ln;
+		ctx.out.String("overall speed="); ctx.out.FloatFix(speed,0,5,0); ctx.out.Ln;
+		ctx.out.String("status: ");
 		IF r.Exited() THEN
 		IF r.Exited() THEN
-			context.out.String("Finished");
+			ctx.out.String("Finished");
 		ELSIF r.Running() THEN
 		ELSIF r.Running() THEN
-			context.out.String("Running");
+			ctx.out.String("Running");
 		ELSE
 		ELSE
-			context.out.String("Paused");
+			ctx.out.String("Paused");
 		END;
 		END;
-		context.out.Ln;
+		ctx.out.Ln;
 	END ReportReader;
 	END ReportReader;
 
 
 BEGIN
 BEGIN