-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
ShuffleZZZ
committed
May 20, 2019
1 parent
bd30472
commit 4ee1c22
Showing
11 changed files
with
355 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
javac -cp ../artifacts/info.kgeorgiy.java.advanced.crawler.jar ru/ifmo/rain/glagolev/crawler/WebCrawler.java | ||
java -p ../artifacts;../lib; -classpath . -m info.kgeorgiy.java.advanced.crawler easy ru.ifmo.rain.glagolev.crawler.WebCrawler %* | ||
TIMEOUT /T -1 |
152 changes: 152 additions & 0 deletions
152
JavaAdvanced/Crawler/ru/ifmo/rain/glagolev/crawler/WebCrawler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package ru.ifmo.rain.glagolev.crawler; | ||
|
||
import info.kgeorgiy.java.advanced.crawler.*; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Phaser; | ||
|
||
/** | ||
* Downloads all of the pages within the given depth from the starting URL, using multithreading. | ||
*/ | ||
public class WebCrawler implements Crawler { | ||
private final ExecutorService downloaders; | ||
private final ExecutorService extractors; | ||
private final Downloader downloader; | ||
|
||
/** | ||
* Default constructor. | ||
*/ | ||
public WebCrawler() { | ||
this((Downloader) null, 0, 0, 0); | ||
} | ||
|
||
/** | ||
* Constructor with given parameters. | ||
* | ||
* @param downloader {@link Downloader}. | ||
* @param downloaders maximum amount of pages to download at one time. | ||
* @param extractors maximum amount of pages to extract links. | ||
* @param perHost maximum amount of pages to download from 1 host. | ||
*/ | ||
public WebCrawler(Downloader downloader, int downloaders, int extractors, int perHost) { | ||
this.downloaders = Executors.newFixedThreadPool(downloaders); | ||
this.extractors = Executors.newFixedThreadPool(extractors); | ||
this.downloader = downloader; | ||
} | ||
|
||
/** | ||
* The entry point, which executes program with given parameters. | ||
* | ||
* @param args Expected starting {@link java.net.URL}, | ||
* depth, | ||
* amount of downloaders, | ||
* amount of extractors | ||
* and maximum downloads from 1 host. | ||
* @throws IOException May occur while creating {@link Downloader}. | ||
*/ | ||
public static void main(String[] args) throws IOException { | ||
if (args.length != 5 || args[0] == null) { | ||
System.out.println("Input error: wrong number of arguments or illegal arguments"); | ||
return; | ||
} | ||
int depth, downloaders, extractors, perHost; | ||
try { | ||
depth = Integer.parseInt(args[1]); | ||
downloaders = Integer.parseInt(args[2]); | ||
extractors = Integer.parseInt(args[3]); | ||
perHost = Integer.parseInt(args[4]); | ||
} catch (NumberFormatException e) { | ||
throw new IllegalArgumentException("Expected integer value, not: ", e); | ||
} | ||
Downloader downloader = new CachingDownloader(); | ||
WebCrawler crawler = new WebCrawler(downloader, downloaders, extractors, perHost); | ||
String url = args[0]; | ||
Result result = crawler.download(url, depth); | ||
System.out.println(result.getDownloaded().size() + " pages were successfully downloaded:" | ||
+ System.lineSeparator()); | ||
result.getDownloaded().forEach(System.out::println); | ||
System.out.println(result.getErrors().size() + " errors occurred:" + System.lineSeparator()); | ||
result.getErrors().forEach((s, e) -> { | ||
System.out.println("URL: " + s); | ||
System.out.println("Error: " + e.getMessage()); | ||
}); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* @param url Starting url. | ||
* @param depth Depth of crawling. | ||
* @return All the downloaded pages and errors of not downloaded ones. | ||
*/ | ||
@Override | ||
public Result download(String url, int depth) { | ||
final Set<String> result = ConcurrentHashMap.newKeySet(); | ||
final Map<String, IOException> errors = new ConcurrentHashMap<>(); | ||
final Phaser phaser = new Phaser(1); | ||
result.add(url); | ||
crawl(url, depth, result, errors, phaser); | ||
phaser.arriveAndAwaitAdvance(); | ||
result.removeAll(errors.keySet()); | ||
return new Result(new ArrayList<>(result), errors); | ||
} | ||
|
||
/** | ||
* Crawler, which handles all URLs within given depth from the first one. | ||
* | ||
* @param url current {@link java.net.URL} to download and extract links. | ||
* @param depth depth needed from this exact {@link java.net.URL} furthermore. | ||
* @param vistited {@link java.net.URL URLs} which already processed. | ||
* @param errors {@link Map} of failed downloaded {@link java.net.URL URLs} and their | ||
* {@link Exception Exceptions}. | ||
* @param phaser {@link Phaser} to synchronize. | ||
*/ | ||
private void crawl(final String url, final int depth, final Set<String> vistited, | ||
final Map<String, IOException> errors, final Phaser phaser) { | ||
if (depth > 0) { | ||
Runnable downloadTask = () -> { | ||
try { | ||
final Document document = downloader.download(url); | ||
Runnable extractTask = () -> { | ||
try { | ||
for (String link : document.extractLinks()) { | ||
if (vistited.add(link)) { | ||
crawl(link, depth - 1, vistited, errors, phaser); | ||
} | ||
} | ||
} catch (IOException e) { | ||
errors.put(url, e); | ||
} finally { | ||
phaser.arrive(); | ||
} | ||
}; | ||
if (depth > 1) { | ||
phaser.register(); | ||
extractors.submit(extractTask); | ||
} | ||
} catch (IOException e) { | ||
errors.put(url, e); | ||
} finally { | ||
phaser.arrive(); | ||
} | ||
}; | ||
phaser.register(); | ||
downloaders.submit(downloadTask); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public void close() { | ||
downloaders.shutdownNow(); | ||
extractors.shutdownNow(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
javac ru/ifmo/rain/glagolev/walk/*.java | ||
java -p ../artifacts;../lib; -classpath . -m info.kgeorgiy.java.advanced.walk Walk ru.ifmo.rain.glagolev.walk.Walk | ||
TIMEOUT /T -1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
javac -cp ../artifacts/info.kgeorgiy.java.advanced.hello.jar ru/ifmo/rain/glagolev/hello/*.java | ||
java -p ../artifacts;../lib; -classpath . -m info.kgeorgiy.java.advanced.hello client-i18n ru.ifmo.rain.glagolev.hello.HelloUDPClient | ||
java -p ../artifacts;../lib; -classpath . -m info.kgeorgiy.java.advanced.hello server-i18n ru.ifmo.rain.glagolev.hello.HelloUDPServer | ||
TIMEOUT /T -1 |
90 changes: 90 additions & 0 deletions
90
JavaAdvanced/HelloUDP/ru/ifmo/rain/glagolev/hello/HelloUDPClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package ru.ifmo.rain.glagolev.hello; | ||
|
||
import info.kgeorgiy.java.advanced.hello.HelloClient; | ||
|
||
import java.io.IOException; | ||
import java.net.*; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Arrays; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
public class HelloUDPClient implements HelloClient { | ||
private static final int TIMEOUT = 1000; | ||
private final int MAX_REQUESTS = 10; | ||
|
||
public HelloUDPClient() {} | ||
|
||
public static void main(String[] args) { | ||
if (args.length < 5 || Arrays.asList(args).contains(null)) { | ||
System.out.println("Wrong input: 5 non-null arguments expected"); | ||
return; | ||
} | ||
HelloUDPClient client = new HelloUDPClient(); | ||
try { | ||
client.run(args[0], Integer.valueOf(args[1]), args[2], Integer.valueOf(args[3]), Integer.valueOf(args[4])); | ||
} catch (NumberFormatException e) { | ||
System.out.println("Wrong input: expected integer, found: " + e.getMessage()); | ||
} | ||
} | ||
@Override | ||
public void run(String host, int port, String prefix, int streamsAmount, int capacity) { | ||
ExecutorService[] streams = new ExecutorService[streamsAmount]; | ||
for (int i = 0; i < streamsAmount; i++) { | ||
streams[i] = Executors.newSingleThreadExecutor(); | ||
} | ||
final InetAddress address; | ||
try { | ||
address = InetAddress.getByName(host); | ||
} catch (UnknownHostException e) { | ||
System.out.println("Wrong host address: " + e.getMessage()); | ||
return; | ||
} | ||
for (int i = 0; i < streamsAmount; i++) { | ||
ExecutorService stream = streams[i]; | ||
final int ind = i; | ||
stream.submit(() -> { | ||
for (int j = 0; j < capacity; j++) { | ||
final DatagramSocket socket; | ||
int packetSize; | ||
try { | ||
socket = new DatagramSocket(); | ||
socket.setSoTimeout(TIMEOUT); | ||
packetSize = socket.getReceiveBufferSize(); | ||
} catch (SocketException e) { | ||
return; | ||
} | ||
String requestString = prefix + ind + "_" + j; | ||
byte[] request = requestString.getBytes(StandardCharsets.UTF_8); | ||
byte[] response = new byte[packetSize]; | ||
DatagramPacket sendPacket = new DatagramPacket(request, request.length, address, port); | ||
for (int k = 0; k < MAX_REQUESTS; ++k) { | ||
try { | ||
socket.send(sendPacket); | ||
DatagramPacket recievePacket = new DatagramPacket(response, packetSize); | ||
socket.receive(recievePacket); | ||
String input = new String(response, 0, recievePacket.getLength(), StandardCharsets.UTF_8); | ||
if (input.contains(requestString)) { | ||
System.out.println(input); | ||
} else { | ||
continue; | ||
} | ||
} catch (IOException e) { | ||
continue; | ||
} | ||
break; | ||
} | ||
} | ||
}); | ||
} | ||
Arrays.stream(streams).forEach(ExecutorService::shutdown); | ||
Arrays.stream(streams).forEach(stream -> { | ||
try { | ||
stream.awaitTermination(streamsAmount * capacity * 10, TimeUnit.SECONDS); | ||
} catch (InterruptedException ignored) { | ||
// | ||
} | ||
}); | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
JavaAdvanced/HelloUDP/ru/ifmo/rain/glagolev/hello/HelloUDPServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package ru.ifmo.rain.glagolev.hello; | ||
|
||
import info.kgeorgiy.java.advanced.hello.HelloServer; | ||
|
||
import java.io.IOException; | ||
import java.net.DatagramPacket; | ||
import java.net.DatagramSocket; | ||
import java.net.InetAddress; | ||
import java.net.SocketException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Semaphore; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
public class HelloUDPServer implements HelloServer { | ||
private ExecutorService stream = null; | ||
private Semaphore amount = null; | ||
private DatagramSocket socket = null; | ||
|
||
public HelloUDPServer() {} | ||
|
||
public static void main(String[] args) { | ||
if (args.length < 2 || args[0] == null || args[1] == null) { | ||
System.out.println("Wrong input: 5 non-null arguments expected"); | ||
return; | ||
} | ||
HelloUDPServer server = new HelloUDPServer(); | ||
try { | ||
server.start(Integer.valueOf(args[0]), Integer.valueOf(args[1])); | ||
} catch (NumberFormatException e) { | ||
System.out.println("Wrong input: expected integer, found: " + e.getMessage()); | ||
} | ||
} | ||
|
||
@Override | ||
public void start(int port, int streamsAmount) { | ||
stream = Executors.newFixedThreadPool(streamsAmount + 1); | ||
amount = new Semaphore(streamsAmount); | ||
int packetSize; | ||
try { | ||
socket = new DatagramSocket(port); | ||
packetSize = socket.getSendBufferSize(); | ||
} catch (SocketException e) { | ||
return; | ||
} | ||
stream.submit(() -> { | ||
while (!Thread.currentThread().isInterrupted()) { | ||
final byte[] request = new byte[packetSize]; | ||
final DatagramPacket receivePacket = new DatagramPacket(request, packetSize); | ||
try { | ||
socket.receive(receivePacket); | ||
} catch (IOException e) { | ||
continue; | ||
} | ||
final InetAddress clientAddress = receivePacket.getAddress(); | ||
final int clientPort = receivePacket.getPort(); | ||
final String requestString = new String(request, 0, receivePacket.getLength(), StandardCharsets.UTF_8); | ||
try { | ||
amount.acquire(); | ||
} catch (InterruptedException ignored) { | ||
// | ||
} | ||
stream.submit(() -> { | ||
String responseString = "Hello, " + requestString; | ||
byte[] response = responseString.getBytes(StandardCharsets.UTF_8); | ||
DatagramPacket sendPacket = new DatagramPacket(response, response.length, clientAddress, clientPort); | ||
try { | ||
socket.send(sendPacket); | ||
} catch (IOException ignored) { | ||
// | ||
} | ||
amount.release(); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
if (socket != null) { | ||
socket.close(); | ||
} | ||
stream.shutdownNow(); | ||
try { | ||
stream.awaitTermination(5, TimeUnit.SECONDS); | ||
} catch (InterruptedException ignored) { | ||
// | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
javadoc -html5 -d Javadoc -link https://docs.oracle.com/en/java/javase/11/docs/api/ -cp ../lib/*;../artifacts/* ru/ifmo/rain/glagolev/concurrent/IterativeParallelism.java info/kgeorgiy/java/advanced/concurrent/ScalarIP.java |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
javac ru/ifmo/rain/glagolev/concurrent/IterativeParallelism.java | ||
java -p ../artifacts;../lib; -classpath . -m info.kgeorgiy.java.advanced.concurrent scalar ru.ifmo.rain.glagolev.concurrent.IterativeParallelism | ||
TIMEOUT /T -1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
javadoc -html5 -d Javadoc -link https://docs.oracle.com/en/java/javase/11/docs/api/ -cp ../lib/*;../artifacts/* ru/ifmo/rain/glagolev/mapper/IterativeParallelism.java ru/ifmo/rain/glagolev/mapper/ParallelMapperImpl.java info/kgeorgiy/java/advanced/mapper/ParallelMapper.java |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
javac -cp ../artifacts/info.kgeorgiy.java.advanced.mapper.jar ru/ifmo/rain/glagolev/mapper/ParallelMapperImpl.java | ||
javac -cp ../artifacts/info.kgeorgiy.java.advanced.concurrent.jar;../artifacts/info.kgeorgiy.java.advanced.mapper.jar ru/ifmo/rain/glagolev/mapper/IterativeParallelism.java | ||
java -p ../artifacts;../lib; -classpath . -m info.kgeorgiy.java.advanced.mapper scalar ru.ifmo.rain.glagolev.mapper.ParallelMapperImpl,ru.ifmo.rain.glagolev.mapper.IterativeParallelism %* | ||
TIMEOUT /T -1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
javac -cp ../artifacts/info.kgeorgiy.java.advanced.student.jar ru/ifmo/rain/glagolev/student/*.java | ||
java -p ../artifacts;../lib; -classpath . -m info.kgeorgiy.java.advanced.student StudentQuery ru.ifmo.rain.glagolev.student.StudentDB | ||
TIMEOUT /T -1 |