<commit_before>package plugins.Sharesite;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.Locale;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;

import freenet.client.HighLevelSimpleClient;
import freenet.keys.FreenetURI;
import freenet.node.RequestStarter;
import freenet.support.Ticker;
import freenet.support.api.ManifestElement;
import freenet.support.io.ArrayBucket;
import java.io.*;
import static java.util.concurrent.TimeUnit.MINUTES;

/**
 * Inserts new or the first editions of freesites.
 * The Sharesite freesites is inserted as
 * normal freesites, and can be accessed as such.
 */
public class Inserter extends Thread {
	private boolean running;
	private LinkedList<Freesite> queuedInserts;
	private Ticker ticker;

	public Inserter(Ticker t) {
		running = true;
		queuedInserts = new LinkedList<Freesite>();
		ticker = t;
	}

	@Override
	public void run() {
		Freesite nextToInsert;
		
		Integer currentHour = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US)
			.get(Calendar.HOUR_OF_DAY); // 0-23
		Integer currentMinute = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US)
			.get(Calendar.MINUTE); // 0-59
		// Quick do everything that requires locking
		nextToInsert = getNextToInsert(currentHour, queuedInserts);

		// Now safely perform the blocking inserts
		if (nextToInsert != null) {
			// TODO: Wait for a random fraction of the remaining
			// part of the current hour to prevent detection of
			// people who click insert during the insertHour.
			if (!nextToInsert.getInsertHour().equals(-1)) { // no instant insert
				// wait until at most 5 minutes before end of the hour
				Integer waitTime = (int)(Math.random() * (55 - currentMinute));
				try {
					if (waitTime > 0) {
						Thread.sleep((waitTime * 60 * 1000));
					}
				} catch (InterruptedException e) {
				}
			}
			performInsert(nextToInsert);
		}
	}

	private synchronized Freesite getNextToInsert(Integer currentHour, LinkedList<Freesite> queuedInserts) {
		for(Freesite c : queuedInserts) {
			if (c.getInsertHour() == null
				|| c.getInsertHour().equals(-1)
				|| c.getInsertHour().equals(currentHour)) {
				queuedInserts.remove(c);
				if (!queuedInserts.isEmpty()) {
					tick();
				}
				return c;
			}
		}
		if (!queuedInserts.isEmpty()) {
			tick();
		}
		return null;
	}

	public synchronized void terminate() {
		running = false;
		notify();
		// TODO: how do we terminate a running insert? it is blocking.
	}

	private synchronized void tick() {
		ticker.queueTimedJob(this, "Sharesite waiter", MINUTES.toMillis(5), false, false);
	}
	
	private synchronized boolean isTerminated() {
		return running == false;
	}

	public synchronized void add(Freesite freesite) {
		freesite.setL10nStatus("Status.Queue", freesite.getRealStatus());
		queuedInserts.addLast(freesite);
		tick();
	}

	private void performInsert(Freesite c) {
		c.setL10nStatus("Status.Inserting", "Status.InsertFailed");
		Plugin.instance.database.save();


		try {
			// prepare the buckets to insert<commit_msg>tick within 10ms after requesting an insert<commit_after>package plugins.Sharesite;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.Locale;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;

import freenet.client.HighLevelSimpleClient;
import freenet.keys.FreenetURI;
import freenet.node.RequestStarter;
import freenet.support.Ticker;
import freenet.support.api.ManifestElement;
import freenet.support.io.ArrayBucket;
import java.io.*;
import static java.util.concurrent.TimeUnit.MINUTES;

/**
 * Inserts new or the first editions of freesites.
 * The Sharesite freesites is inserted as
 * normal freesites, and can be accessed as such.
 */
public class Inserter extends Thread {
	private boolean running;
	private LinkedList<Freesite> queuedInserts;
	private Ticker ticker;

	public Inserter(Ticker t) {
		running = true;
		queuedInserts = new LinkedList<Freesite>();
		ticker = t;
	}

	@Override
	public void run() {
		Freesite nextToInsert;
		
		Integer currentHour = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US)
			.get(Calendar.HOUR_OF_DAY); // 0-23
		Integer currentMinute = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US)
			.get(Calendar.MINUTE); // 0-59
		// Quick do everything that requires locking
		nextToInsert = getNextToInsert(currentHour, queuedInserts); // also sets up the time to check for the next site

		// Now safely perform the blocking inserts
		if (nextToInsert != null) {
			// TODO: Wait for a random fraction of the remaining
			// part of the current hour to prevent detection of
			// people who click insert during the insertHour.
			if (!nextToInsert.getInsertHour().equals(-1)) { // no instant insert
				// wait until at most 5 minutes before end of the hour
				Integer waitTime = (int)(Math.random() * (55 - currentMinute));
				if (waitTime > 0) {
					tick(waitTime * 60 * 1000);
					return;
				}
			}
			performInsert(nextToInsert);
		}
	}

	private synchronized Freesite getNextToInsert(Integer currentHour, LinkedList<Freesite> queuedInserts) {
		for(Freesite c : queuedInserts) {
			if (c.getInsertHour() == null
				|| c.getInsertHour().equals(-1)
				|| c.getInsertHour().equals(currentHour)) {
				queuedInserts.remove(c);
				if (!queuedInserts.isEmpty()) {
					tick(); // keep the insert loop running
				}
				return c;
			}
		}
		if (!queuedInserts.isEmpty()) {
			tick();
		}
		return null;
	}

	public synchronized void terminate() {
		running = false;
		notify();
		// TODO: how do we terminate a running insert? it is blocking.
	}

	private synchronized void tick() {
		tick(MINUTES.toMillis(5));
	}
	
	private synchronized void tick(long millis) {
		ticker.queueTimedJob(this, "Sharesite waiter", millis, false, false);
	}
	
	private synchronized boolean isTerminated() {
		return running == false;
	}

	public synchronized void add(Freesite freesite) {
		freesite.setL10nStatus("Status.Queue", freesite.getRealStatus());
		queuedInserts.addLast(freesite);
		tick(10);
	}

	private void performInsert(Freesite c) {
		c.setL10nStatus("Status.Inserting", "Status.InsertFailed");
		Plugin.instance.database.save();


		try {
			// prepare the buckets to insert
{'fraction_non_alphanumeric': 0.1128356355734906, 'fraction_numerical': 0.007760360080707745, 'mean_word_length': 4.006993006993007, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4651482', 'n_tokens_mistral': 2307, 'n_tokens_neox': 2036, 'n_words': 542}