From 3782568df6e047d8fdc1f83b6aca785e38e9dbff Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@71dcc7fd-b1f2-4e5d-bb8e-274146e81173> Date: Sun, 10 Mar 2024 17:38:04 +0000 Subject: [PATCH] checkDataIntegrity - major improved version; git-svn-id: svn://home0/checkDataIntegrity@3514 71dcc7fd-b1f2-4e5d-bb8e-274146e81173 --- bin/checkDataIntegrity/Args.class | Bin 0 -> 1654 bytes bin/checkDataIntegrity/BufferPool.class | Bin 0 -> 864 bytes bin/checkDataIntegrity/Main$1.class | Bin 2528 -> 3210 bytes bin/checkDataIntegrity/Main.class | Bin 6680 -> 3633 bytes bin/checkDataIntegrity/ProgramState.class | Bin 0 -> 1859 bytes bin/checkDataIntegrity/Task.class | Bin 0 -> 4187 bytes bin/checkDataIntegrity/Worker.class | Bin 0 -> 1407 bytes bin/checkDataIntegrity/WorkerPool.class | Bin 0 -> 3055 bytes bin/module-info.class | Bin 157 -> 157 bytes checkDataIntegrity.jar | Bin 12897 -> 19231 bytes src/checkDataIntegrity/Args.java | 6 + src/checkDataIntegrity/BufferPool.java | 21 ++++ src/checkDataIntegrity/Main.java | 137 ++++++++-------------- src/checkDataIntegrity/ProgramState.java | 7 ++ src/checkDataIntegrity/Task.java | 71 +++++++++++ src/checkDataIntegrity/Worker.java | 30 +++++ src/checkDataIntegrity/WorkerPool.java | 62 ++++++++++ 17 files changed, 246 insertions(+), 88 deletions(-) create mode 100644 bin/checkDataIntegrity/Args.class create mode 100644 bin/checkDataIntegrity/BufferPool.class create mode 100644 bin/checkDataIntegrity/ProgramState.class create mode 100644 bin/checkDataIntegrity/Task.class create mode 100644 bin/checkDataIntegrity/Worker.class create mode 100644 bin/checkDataIntegrity/WorkerPool.class create mode 100644 src/checkDataIntegrity/Args.java create mode 100644 src/checkDataIntegrity/BufferPool.java create mode 100644 src/checkDataIntegrity/ProgramState.java create mode 100644 src/checkDataIntegrity/Task.java create mode 100644 src/checkDataIntegrity/Worker.java create mode 100644 src/checkDataIntegrity/WorkerPool.java diff --git a/bin/checkDataIntegrity/Args.class b/bin/checkDataIntegrity/Args.class new file mode 100644 index 0000000000000000000000000000000000000000..5a2fc18e528e937ec6c30d94cc658fad3164c5d0 GIT binary patch literal 1654 zcmaJ>*-qO)6g>mkaT^jyQ&N^LP!h8QTDqDpEUFqQT~rVc?UR#?5|hME?Fkb9)Q2K9 zs>DM-pdVHBj%~mq%frlE-7eLV}l`GzS=twwqe#ae{+)|a8Q)HsrVO42g!}FwB&Pq=POu`GJduRr{>l zdYcPw)A8wipX*f#EEu+%Qk9CNFxY-|J?r z#ht~nWi`7UEuhk`!hpvI9-emiK6k3N(Giv%gzU9+#|b+87~lGX1lhIVQ~AkBMz9gX zbB3JTAex*vHQ5K+Wd|e~QZ%M$WN2g=l#*$3+m*qo<=!wXT_tP8y`$J+m>+$V3c*Vf z8D95dgBoL;o>aYwvUA*(`o>+UYiNzpn1F&Y+#st(YnaxY`WrXZl^#;+Y7bND zTn`yF6Y3#*M!RE}p*cbvk|9U)mWRR}%+eR(T~@iDb9u*HOEODUIoYv`n_PDW+`ZiRv9L&{zB>}8U5TcHY1inkf~9S7#0SwWPXfbNeqN!heJ~IH@FbC zOycETqUt&B0oSEbMY+tB6YBm8X+h8uaGfa#%A?@lCr?Z=EirZF9O@`k2x~6sI*PQW q3IEi6*k^cwm(Z|{SL9ES|25uXmmYqPzH{_=URilX<&~6MQ2zmSP)WrA literal 0 HcmV?d00001 diff --git a/bin/checkDataIntegrity/BufferPool.class b/bin/checkDataIntegrity/BufferPool.class new file mode 100644 index 0000000000000000000000000000000000000000..444dc5c8ab75b286d761233796550c1b992cdd61 GIT binary patch literal 864 zcma)4Yira%6g`vdHjk#=?si*iwcYwoA~YZU(52KUf^>bcvSRnsY&x5!86Z}mg-bsTM1!-Vra?jjz@0m06{pZIo0B*z8pfIcj2O^l<kAsF0VxmV;->;-8O6j>&c-0MZjMC|)< z8cd=jd?ItV7>s@tCOj`PB5t0U*d6-YMAo}O93@e{&7j)OfT4CL-4`0>80@oZFkzu# zVF4z?Ot-9NfT3lfjv0mq$rcZb7bB59<)fHXwt8v6;{nei8JD056%Fd1A4IPhI=%ne zN4nKekY6?18TzvQ1q&CkM!+yn(ky8pV!K3Wl4e&#k5;)`caO33H>F-u ztdj&R;~XXGSi$*%OIIwG_}IwV;+JX`Lr;+B8cs zvaKA6#klB8Fn27@d}EfL4*ZeP0Yn$h|5J?vkL@POf(mV*>-7}o!RvCs^p%i zxjp-0r7Ew!8Y_^?Ln_btL3v80a=Le27hI53g{ql8+kMX0=klF1{Q1vszXM3&I}1$= z9qv4L7sedrq@b> zMyrs1^J(D=HOz2l!$CAcH4ZmAsB^B-@d|JHXBncSL7vAznYLk}MN2zv#1PlgZX26n zYpKJ=7Ho|pg1t6cv5z6rr_Eb4!sip^;vAPbXU?M}v}Xd>@n#(<^zZ6sRLu*@{oY0{ zRro=v*;bO3!jB0_+z8|%!(25>HFiunYJR9v{@R|SloWGi#gijWC|pgT)Z?visDG7q zjbGC|EPIMBj*s7Rc}a=D4=o&~R2X&+7pYZKe*PR+2JJ!|!#HE% zb)wrEooUm286m2M3!-Ff(s7L8tOd$$R|A_TJz(P;&XY;0OqcC$$ff>SUD^va-q3Z6 z<;JJ8>4{WsJdP|TEljMKS~H8G;zb)%I-G6Qxsww`o)w-a!Z@apvoJ$NZ{Sva@7cJh zAvV$EkVnq#^jMd& zTv9w=YYnQ*HNy=?{OGRuxTZ4Ey{#7Fbj4E!cA1z)Bhp>SI;HB&Xsr?WtV8hR?1hE} ztR4! zQDsTx9<3|)ij34;)ArTR`RR&s?Z`~HVPZt#P zBFPN9`mWTuP~$Cwo%Ve$M?EJDIgQVj2_CBRR8(|Rj1hV^A==iizj*+y^u;qPeecXl zUpxB0CPq&y+DLmFNn>atE1)wmu!Q!+;1YHujxJ$Wq9eM5J&B*u`6Hb+p^M(lWCL_y zKfP@ucj5ru4U#Fnr1c!hQTo+mut!LW=$%LCeMoCPN|!> zH+e;E_U^s!VMQMx8X4}okIj$pcKf@_c%S4L89YF(&BvQK$y!Rs-y#K;|I`JB?0U#{x+nS#F0_u)w38 zXV~AcS!~3jE12%1r?RnLo=>ik=f`eD5ujx9Onv#EkWa0F{G@^gxh+LL%cqbN6sG1z zJTdSG!og*fS2KiWG@UmQb5k@kHh^$*J%r;}e6|lCu7_}NBM2X_i9kg7)Wq`{J~!(Z Z_>$HrZsRV#AxY0E-Cz3eTY8#s`(I7q40-?n literal 2528 zcmb_dTTdHD6#mBEu-GiO5K198($W+RWRtc@(?Z;uTQC@t0wHbE3*+@*CYW7ocN~!) zkUvo6rBc<`zNS%0l|Dpy?vJW^X6-u0#D+?>v^!^K=6vV&o#Vg${__=pPf;)tVHk9F zgtI%x6;HcL6nv>3+bdkUBiBqA3_TC|BW@SDTd-Gi4~3&lw2@M{>q^hwmPKJN&}&l$ zQh7c@>=7@HI9}OR45OLwVp++e?Rc(J_I=?hn=5ZmI(8~tGM-zQVrbWD!LBSZuyhrr z#MMqfKGdOPWT5D_sc-M`eTKGa=}MJkxOHM<=|;Tt*d~K9>*YlZ45uxaXxGvi3o*pC z^p1rNSXz45LMP&JL@{Kc3uhUkqguT?BVCa#@8yKQ!E;4HI2q63#ZB%@{axKO)Q+T( z&SsjXoucb4`IUUmNuN^g`HvZL)$nRbzeCBHszg%T<4XB5S60HF;em8?T~hyU1yf@U zw`*lv6G6GC(;A=OcSK1^&kanBF!Y7xqcW#gYbP;W#;A!88O}FhK?Tmj7!p+1+12bu zI(v7X;o`COqj^aTI@543jFjP&j*fCS*>K!CXiX(eO&x3puHj=7A2Ey{cD*Hpg->vu zp;HEHqEIe!UqgjuzaOVI`pm>lhRY`-x`od{dG403a%wE}WY)r*MvoSR(p6fpa9fukwlTl9lFp_!s0PM% z=zQn8;?C|0FI8#TUCYq|rwe3esRiE-6XFECii&-QJg*e4L7N(-xoc zQDIh0&)+NBW2)V{EVx{iePY~fCI0%tH?)G*uMXnrhNG~FlA3$-u2b{^=@wRm+VS!x z$jm^Kab&>(k-^v_k7x>xKB#kHon{SMW7a`s1zL0k)Bg9 zdQR)H3eZYJHC$<=hARzJ`bUb<(}ixj-9yqGBBTWjCB_fXn>crXzQp7K`V;-e0R|F( zVDL9Ojo=);+einPzxU(xm)^V+9q7+F_{b{&Jbff3xS^DSBPEs4ddZ^^1}Y0_^;bfkaA zq%lCfjO8Pqw#q@W&W=&DW7O;z$Y3SR0rkv(LSATs{3g30a!-nUUOj@Gpls;u#uMYO zacANM)*7ove@b*7Ay%cRpHG0W(F(!F=J7tB2WiB2;=z{--YY<_<>df TTgX9>q-Tg`rT%Tx6T#L$&MP#( diff --git a/bin/checkDataIntegrity/Main.class b/bin/checkDataIntegrity/Main.class index b333cbac1da189aac52353e92ca489033834f649..99724f1c19ae86a122df0f3bc0523baf705bd31c 100644 GIT binary patch literal 3633 zcmb_e`*#~x5&o_vdu3%q94E1xlq60`f-O5yl9mvn)JHsw*@@p{w_~?4}tLzH8Zqj2xXDxtTYszUA1ShE9b&n^GGqNhs{qu@7Ae z?N!6|%u8;8=bnsI8fA>gXEZ#da5%!$an~uhMrFb`e4=mw@73^d6KoSpo^Muk9K<1o z-T9j9nzlb_Rm_}KE(-#L@v4R%h2w$wHQy?y^N!t+OdGyavGVCl!H{+ALK273oIhsgN|xFq9_o=)N%G6K~Fg;yHKyo;zt=nGgI z1?gs7GEvJ-hzsC@xTxWY_2k;{<}#5X*q896f_}p&mt?G{@QqHIbRll7m6m%3}5fw&GVPBXeOttYa zNUmvAG6|FvhNnEEV4m;UPVSSEpFJ0ZCZ`6&@ia%TWK}u%tgTtAV);E4Z!n1p91ZLu zVRL9cNJkZ)RL}x~lqs|?BDEz6Jk&HWX1g~#OwcS%SI2eSAWMQkaqd1kMx}BsNoIda zp)cZ;?ImTD^bo*a(D9i7FsDWuRq&En{qldE6E^3dE4I0&S1VJr8=u$liZD>v;d17S z__BsCtrs`}Dm`3t4e6jdzJjmP4`*S$FLn1`Z6s!sU`Et@UB@@1%qDy%?8lwFP<%_r ztN1ocbHyl;EOy@TXDq+SHy&?G@*R(GJfc2}>EG4ynxtQAkba#^=Ubxw`{MVyUBR`a zaUT$?exT!r;%+;wGTB1sJ<;@I9X|;)%`N$+*GfbAi=z`QxYfyf%PqPw-#~#4BMd~d z%gmVxr{?BOsan)8#X2A%+sKoS<9ohqRCA_ZbmYiiQHp=K$&$lqAY2)Nl)r=6|T4&Z-vt7lI zQ7%tdzM0w8hBp)VBa>v32AuCv3EZLA0)!W)ra2$X-eZbQ7G0-SC{}Aer+RYMT-rfSlNnyvB>G?TRZlNBI zkUp_S+({|4@mu3}nxo>_np#2PE?-)Zjrk6`Zf*@tG6L7~=mj|DywSWCxZpzKqHC*ItJfe-rUo9W&xUEO6j# zVC*g$)j^YYb8atE=;9sbAv}TocovW2W9;m6{90fSU&Ihz#Bkv7W1%Z}4$o5`>lHpq zSvEgR;p6xOoj;3F7~C7bnZ1Wk6POqK?{Hh_-pRnw zrx>RzjK?UQ%+kRebA62U@)~+Dj^mt5;c1*^7neA8g~vABN)eXN25yPrF{ln&$;(2+ z%6~SjEHZ?tWqi)8;|mQtzP5^Q0yLRsap^k@!YaNO%+Si)5|Bs2r5|xgrYd{!dhlPx zPq*xp@U7x!!OUjl4h1MplWsG37|-AYuMB4yuPH{Oz({PmQVgOYG<_a#;ODelTuDH^ zjVX=AFpgjFy9K|*uQ(py_wOn5hv50A;CVNA{uzJex>Un+9Obu+I#$V&HNFeU&;17+ CR@)K) literal 6680 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 diff --git a/bin/checkDataIntegrity/ProgramState.class b/bin/checkDataIntegrity/ProgramState.class new file mode 100644 index 0000000000000000000000000000000000000000..304fda4936f44cd5dde33f14cc13ec40cd0171d1 GIT binary patch literal 1859 zcmb_c+invv5It^_ZW0#Sq?FPYD3=zJ<+9vw;Z|A@Md2cf`T$SP)=HKp>*95gD)C7m zfkcJW2R?w0LX5o&EKt%upva!dtk2B&%#6Q&+x!Ax4)+}lFiZz+5v(q7%@-prS}N4* z{!=Aeig%YZ*TO-LVdNEm!~G7ATK+Q;NVUR{k2P1CfjuNWkiCfXYQvuE>9FGmG75T1 ziAeig%WfF>b5=BD)T%QSEaaY2gl?{D5i<>mMc#=)kJ8a2u3Lp?_RaGQv!%_Etj+kqZXzA17|Cm zSnCyPieoMgV}{{Ub=$Pk$XO2*qs`;Cq0eTxXk1oZ%%a9Hvjdll)CA&nk9X*XV`($l z08g5)M4;=n7slgh7aq4-Zj>f`0#PO{PK*+Ql~4-esd0oNHO?U2{) ztR_26Y~9Z5Fi}Tql-3xnaRzrWiiEOhh}gj#!|X4z`rO;WJj0>>N2xIql1NEjAe^P? z8>Du~p<>38w2B!@D`_OHq=6)9)-Jdhz;4pIgfge6ywBLdy=o!-ExH<8=Gm^YE% z!1zb{Jb($>hbRch{Uq%dNfL~H2S^&tgf-u%Y+#ejlz9y(C8L?(c^o9YoU>4e)FQ1C zEqeBFh<20FECsV+yiX{0KOe6GwqRLDW(lAQeS8bh3EJgiezXhcqcb;svjx`-+DZY sb0jN-ziJD24RzeWP29q5vX{ty2Y0bRg}+DtC#j4{UnO0Y^px$W@51Jpa{vGU literal 0 HcmV?d00001 diff --git a/bin/checkDataIntegrity/Task.class b/bin/checkDataIntegrity/Task.class new file mode 100644 index 0000000000000000000000000000000000000000..931e1a4a87928c2ed7908d5baf3609fcffa55fce GIT binary patch literal 4187 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 literal 0 HcmV?d00001 diff --git a/bin/module-info.class b/bin/module-info.class index 52a3e4c6fa7d1badc5c836e8a7bbca953f78d4f0..d68e9cd397777f607a04a877e6ab2559723e6480 100644 GIT binary patch delta 16 YcmbQsIG2&*)W2Q(7#J8FCvr>$05xI-^Z)<= delta 16 YcmbQsIG2&*)W2Q(7#JALCvr>$05v)V>Hq)$ diff --git a/checkDataIntegrity.jar b/checkDataIntegrity.jar index 7a1a7f55b80ac476fe46c72e9194d39d8b367dc1..36619df17a10a427b25a420c879ac37ffff8e641 100644 GIT binary patch delta 16867 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 diff --git a/src/checkDataIntegrity/Args.java b/src/checkDataIntegrity/Args.java new file mode 100644 index 0000000..2ca1246 --- /dev/null +++ b/src/checkDataIntegrity/Args.java @@ -0,0 +1,6 @@ +package checkDataIntegrity; + + +record Args(String path0, String path1, int skip, int timeLimit) { + +} diff --git a/src/checkDataIntegrity/BufferPool.java b/src/checkDataIntegrity/BufferPool.java new file mode 100644 index 0000000..c9bf12e --- /dev/null +++ b/src/checkDataIntegrity/BufferPool.java @@ -0,0 +1,21 @@ +package checkDataIntegrity; + +import java.util.concurrent.LinkedBlockingQueue; + +class BufferPool { + + private static final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + + static byte[] get() { + byte[] buf = queue.poll(); + if (buf == null) { + buf = new byte[16384]; + } + return buf; + } + + static void put(final byte[] buf) { + queue.offer(buf); + } + +} diff --git a/src/checkDataIntegrity/Main.java b/src/checkDataIntegrity/Main.java index 1822296..2aec56a 100644 --- a/src/checkDataIntegrity/Main.java +++ b/src/checkDataIntegrity/Main.java @@ -1,47 +1,28 @@ package checkDataIntegrity; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; -import java.nio.file.InvalidPathException; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.concurrent.atomic.AtomicLong; public class Main { - public static void main(final String[] args) throws IOException { - if (args.length < 4) { - System.err.println("Usage: checkDataIntegrity.java "); + public static void main(final String[] args) throws Exception { + final Args parsedArgs = parseArgs(args); + if (parsedArgs == null) { return; } - final String path0 = args[0]; - final String path1 = args[1]; - final int skip = Integer.parseInt(args[2]); - final int limit = Integer.parseInt(args[3]); - final int max = skip + limit; - System.out.println("Path0: " + path0); - System.out.println("Path1: " + path1); - System.out.println("Skip: " + skip); - System.out.println("Limit: " + limit); - final long start = System.currentTimeMillis(); - final AtomicLong count = new AtomicLong(); + final ProgramState state = new ProgramState(System.currentTimeMillis(), new AtomicLong(), new AtomicLong(), new AtomicLong()); - System.out.println("Scanning Tree"); + final WorkerPool workerPool = new WorkerPool(parsedArgs, state, 32); - final List paths = new ArrayList<>(limit); - Files.walkFileTree(Path.of(path0), new FileVisitor<>() { + final AtomicLong walkTreeCounter = new AtomicLong(); + Files.walkFileTree(Path.of(parsedArgs.path0()), new FileVisitor<>() { @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { @@ -50,85 +31,65 @@ public class Main { @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { - if (attrs.isRegularFile() && count.incrementAndGet() > skip) { - paths.add(file); + if (attrs.isRegularFile() && walkTreeCounter.incrementAndGet() > parsedArgs.skip()) { + try { + workerPool.put(file); + } + catch (final InterruptedException e) { + return FileVisitResult.TERMINATE; + } } - return count.get() < max ? FileVisitResult.CONTINUE : FileVisitResult.TERMINATE; + + final boolean timeLimitReached = System.currentTimeMillis() - state.start() >= parsedArgs.timeLimit(); + if (timeLimitReached) { + System.out.println("Time limit reached"); + } + return timeLimitReached ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(final Path file, final IOException exc) throws IOException { - // System.out.println(exc.getClass().getSimpleName() + " " + exc.getMessage()); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { - // if (exc != null) { - // System.out.println(exc.getClass().getSimpleName() + " " + exc.getMessage()); - // } return FileVisitResult.CONTINUE; } }); - count.set(0); - final AtomicLong countErr = new AtomicLong(); - final ThreadLocal bufs0 = ThreadLocal.withInitial(() -> new byte[8192]); - final ThreadLocal bufs1 = ThreadLocal.withInitial(() -> new byte[8192]); + workerPool.awaitEmpty(); + workerPool.interrupt(); + workerPool.join(); - try { - paths - .stream() - .parallel() - .forEach(p0 -> { - try { - final long cnt = count.incrementAndGet(); - if (cnt % 1000 == 0) { - System.out.println(cnt); - } - - final String rel = p0.toString().substring(path0.length()); - final Path p1 = Path.of(path1 + rel); - - final byte[] buf0 = bufs0.get(); - final byte[] buf1 = bufs1.get(); - try (InputStream inputStream0 = new BufferedInputStream(new FileInputStream(p0.toFile()), 65536); InputStream inputStream1 = new BufferedInputStream(new FileInputStream(p1.toFile()), 65536)) { - int len0, len1; - do { - len0 = inputStream0.read(buf0); - len1 = inputStream1.read(buf1); - if (len0 != len1) { - System.out.println(rel + ": Length mismatch"); - countErr.incrementAndGet(); - break; - } - if (len0 > -1 && !Arrays.equals(buf0, 0, len0, buf1, 0, len1)) { - System.out.println(rel + ": Data mismatch"); - countErr.incrementAndGet(); - break; - } - } while (len0 > -1); - } - } - catch (NoSuchFileException | FileNotFoundException | InvalidPathException ex) { - // System.out.println(rel + ": NoSuchFileException"); - } - catch (final Exception ex) { - System.out.println(p0 + ": Exception: " + ex.getClass().getName() + " " + ex.getMessage()); - countErr.incrementAndGet(); - } - }); - } - catch (final Exception ex) { - System.out.println("General Exception: " + ex.getClass().getName() + " " + ex.getMessage()); - countErr.incrementAndGet(); + printStats(state); + + System.exit(state.countErr().get() > 0 ? 1 : 0); + } + + private static Args parseArgs(final String[] args) { + if (args.length < 4) { + System.err.println("Usage: checkDataIntegrity.java "); + return null; } - System.out.println("Took " + Duration.ofMillis(System.currentTimeMillis() - start).toString()); - System.out.println(((count.get() > 0) ? count.get() : "No") + " files checked"); - System.out.println(countErr.get() + " errors"); - - System.exit(countErr.get() > 0 ? 1 : 0); + final Args result = new Args( + args[0], + args[1], + Integer.parseInt(args[2]), + Integer.parseInt(args[3])); + System.out.println(result); + return result; + } + + private static void printStats(final ProgramState state) { + final Duration duration = Duration.ofMillis(System.currentTimeMillis() - state.start()); + System.out.println("Took: " + duration.toString()); + System.out.println("Files checked: " + state.count().get()); + if (duration.toSeconds() > 0) { + System.out.println("Throughput: " + (state.bytes().get() / duration.toSeconds() / 1024 / 1024) + " Mib/s"); + } + System.out.println("Errors: " + state.countErr().get()); } } diff --git a/src/checkDataIntegrity/ProgramState.java b/src/checkDataIntegrity/ProgramState.java new file mode 100644 index 0000000..feff392 --- /dev/null +++ b/src/checkDataIntegrity/ProgramState.java @@ -0,0 +1,7 @@ +package checkDataIntegrity; + +import java.util.concurrent.atomic.AtomicLong; + +record ProgramState(long start, AtomicLong count, AtomicLong countErr, AtomicLong bytes) { + +} diff --git a/src/checkDataIntegrity/Task.java b/src/checkDataIntegrity/Task.java new file mode 100644 index 0000000..fe929b3 --- /dev/null +++ b/src/checkDataIntegrity/Task.java @@ -0,0 +1,71 @@ +package checkDataIntegrity; + +import java.io.FileNotFoundException; +import java.io.RandomAccessFile; +import java.nio.file.InvalidPathException; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.function.Consumer; + +class Task implements Consumer { + + private final Args args; + + private final ProgramState state; + + Task(final Args args, final ProgramState state) { + this.args = args; + this.state = state; + } + + @Override + public void accept(final Path path) { + try { + final long cnt = this.state.count().incrementAndGet(); + if (cnt % 1000 == 0) { + System.out.println(cnt); + } + + final String rel = path.toString().substring(this.args.path0().length()); + final Path p1 = Path.of(this.args.path1() + rel); + + int len0, len1; + final byte[] buf0 = BufferPool.get(); + final byte[] buf1 = BufferPool.get(); + try ( + RandomAccessFile raf0 = new RandomAccessFile(path.toFile(), "r"); + RandomAccessFile raf1 = new RandomAccessFile(p1.toFile(), "r")) { + + do { + len0 = raf0.read(buf0); + len1 = raf1.read(buf1); + if (len0 != len1) { + System.out.println(rel + ": Length mismatch"); + this.state.countErr().incrementAndGet(); + break; + } + if (len0 > -1) { + this.state.bytes().addAndGet(len0); + if (!Arrays.equals(buf0, 0, len0, buf1, 0, len1)) { + System.out.println(rel + ": Data mismatch"); + this.state.countErr().incrementAndGet(); + break; + } + } + } while (len0 > -1); + } + finally { + BufferPool.put(buf0); + BufferPool.put(buf1); + } + } + catch (NoSuchFileException | FileNotFoundException | InvalidPathException ex) { + } + catch (final Exception ex) { + System.out.println(path + ": Exception: " + ex.getClass().getName() + " " + ex.getMessage()); + this.state.countErr().incrementAndGet(); + } + } + +} diff --git a/src/checkDataIntegrity/Worker.java b/src/checkDataIntegrity/Worker.java new file mode 100644 index 0000000..c7f885d --- /dev/null +++ b/src/checkDataIntegrity/Worker.java @@ -0,0 +1,30 @@ +package checkDataIntegrity; + +import java.nio.file.Path; +import java.util.concurrent.BlockingQueue; + +class Worker extends Thread { + + private final Task task; + + private final BlockingQueue queue; + + public Worker(final Args args, final ProgramState state, final BlockingQueue queue) { + super(); + this.queue = queue; + this.task = new Task(args, state); + } + + @Override + public void run() { + try { + while (!Thread.interrupted()) { + final Path p = this.queue.take(); + this.task.accept(p); + } + } + catch (final InterruptedException e) { + } + } + +} diff --git a/src/checkDataIntegrity/WorkerPool.java b/src/checkDataIntegrity/WorkerPool.java new file mode 100644 index 0000000..036291e --- /dev/null +++ b/src/checkDataIntegrity/WorkerPool.java @@ -0,0 +1,62 @@ +package checkDataIntegrity; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +class WorkerPool { + + private final List workers; + + private final BlockingQueue queue; + + WorkerPool(final Args args, final ProgramState state, final int threads) { + System.out.println("Threads: " + threads); + + this.queue = new LinkedBlockingQueue<>(threads * 2); + + this.workers = new ArrayList<>(threads); + for (int i = 0; i < threads; i++) { + final Worker worker = new Worker(args, state, this.queue); + worker.setDaemon(true); + worker.setName("Worker #" + i); + worker.start(); + + this.workers.add(worker); + } + } + + void put(final Path path) throws InterruptedException { + this.queue.put(path); + } + + void awaitEmpty() { + while (!this.queue.isEmpty()) { + try { + Thread.sleep(10); + } + catch (final InterruptedException e) { + break; + } + } + } + + void interrupt() { + for (final Worker worker : this.workers) { + worker.interrupt(); + } + } + + void join() { + for (final Worker worker : this.workers) { + try { + worker.join(); + } + catch (final InterruptedException e) { + } + } + } + +}