@Override public synchronized void onFailure( InsertException e, BaseClientPutter state, ObjectContainer container) { try { if (e.getMode() == InsertException.COLLISION) { Logger.warning( this, "WoTOwnMessageList insert collided, trying to insert with higher index ..."); try { synchronized (mMessageManager) { // We must call getOwnMessageList() before calling onMessageListInsertFailed() because // the latter will increment the message list's // index, resulting in the ID of the message list changing - getIDFromURI would fail // with the old state.getURI() if we called it after // onMessageListInsertFailed() WoTOwnMessageList list = (WoTOwnMessageList) mMessageManager.getOwnMessageList( MessageListID.construct(state.getURI()).toString()); mMessageManager.onMessageListInsertFailed(state.getURI(), true); insertMessageList(list); } } catch (Exception ex) { Logger.error(this, "Inserting WoTOwnMessageList with higher index failed", ex); } } else { if (e.isFatal()) Logger.error(this, "WoTOwnMessageList insert failed", e); else Logger.warning(this, "WoTOwnMessageList insert failed non-fatally", e); mMessageManager.onMessageListInsertFailed(state.getURI(), false); } } catch (Exception ex) { Logger.error(this, "WoTOwnMessageList insert failed and failure handling threw", ex); } finally { removeInsert(state); Closer.close(((ClientPutter) state).getData()); } }
private void fail( InsertException e, boolean forceFatal, ObjectContainer container, ClientContext context) { synchronized (this) { if (finished) return; finished = true; } if (persistent) container.store(this); if (e.isFatal() || forceFatal) parent.fatallyFailedBlock(container, context); else parent.failedBlock(container, context); unregister(container, context, getPriorityClass(container)); if (freeData) { if (persistent) container.activate(sourceData, 1); sourceData.free(); if (persistent) sourceData.removeFrom(container); sourceData = null; if (persistent) container.store(this); } if (persistent) container.activate(cb, 1); cb.onFailure(e, this, container, context); }
public boolean send( NodeClientCore core, RequestScheduler sched, final ClientContext context, ChosenBlock req) { // Ignore keyNum, key, since we're only sending one block. ClientKeyBlock b; ClientKey key = null; if (SingleBlockInserter.logMINOR) Logger.minor(this, "Starting request: " + SingleBlockInserter.this); BlockItem block = (BlockItem) req.token; try { try { b = innerEncode( context.random, block.uri, block.copyBucket, block.isMetadata, block.compressionCodec, block.sourceLength, compressorDescriptor); } catch (CHKEncodeException e) { throw new LowLevelPutException( LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e); } catch (SSKEncodeException e) { throw new LowLevelPutException( LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e); } catch (MalformedURLException e) { throw new LowLevelPutException( LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e); } catch (InsertException e) { throw new LowLevelPutException( LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e); } catch (IOException e) { throw new LowLevelPutException( LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e); } catch (InvalidCompressionCodecException e) { throw new LowLevelPutException( LowLevelPutException.INTERNAL_ERROR, e.toString() + ":" + e.getMessage(), e); } if (b == null) { Logger.error( this, "Asked to send empty block on " + SingleBlockInserter.this, new Exception("error")); return false; } key = b.getClientKey(); final ClientKey k = key; if (block.persistent) { context.jobRunner.queue( new DBJob() { public boolean run(ObjectContainer container, ClientContext context) { if (!container.ext().isStored(SingleBlockInserter.this)) return false; container.activate(SingleBlockInserter.this, 1); onEncode(k, container, context); container.deactivate(SingleBlockInserter.this, 1); return false; } }, NativeThread.NORM_PRIORITY + 1, false); } else { context.mainExecutor.execute( new Runnable() { public void run() { onEncode(k, null, context); } }, "Got URI"); } if (req.localRequestOnly) try { core.node.store(b, false, req.canWriteClientCache, true, false); } catch (KeyCollisionException e) { throw new LowLevelPutException(LowLevelPutException.COLLISION); } else core.realPut(b, req.canWriteClientCache, req.forkOnCacheable); } catch (LowLevelPutException e) { if (e.code == LowLevelPutException.COLLISION) { // Collision try { ClientSSKBlock collided = (ClientSSKBlock) core.node.fetch((ClientSSK) key, true, true, req.canWriteClientCache); byte[] data = collided.memoryDecode(true); byte[] inserting = BucketTools.toByteArray(block.copyBucket); if (collided.isMetadata() == block.isMetadata && collided.getCompressionCodec() == block.compressionCodec && Arrays.equals(data, inserting)) { if (SingleBlockInserter.logMINOR) Logger.minor(this, "Collided with identical data: " + SingleBlockInserter.this); req.onInsertSuccess(context); return true; } } catch (KeyVerifyException e1) { Logger.error(this, "Caught " + e1 + " when checking collision!", e1); } catch (KeyDecodeException e1) { Logger.error(this, "Caught " + e1 + " when checking collision!", e1); } catch (IOException e1) { Logger.error(this, "Caught " + e1 + " when checking collision!", e1); } } req.onFailure(e, context); if (SingleBlockInserter.logMINOR) Logger.minor(this, "Request failed: " + SingleBlockInserter.this + " for " + e); return true; } catch (DatabaseDisabledException e) { // Impossible, and nothing to do. Logger.error(this, "Running persistent insert but database is disabled!"); } finally { block.copyBucket.free(); } if (SingleBlockInserter.logMINOR) Logger.minor(this, "Request succeeded: " + SingleBlockInserter.this); req.onInsertSuccess(context); return true; }
@Override public void onFailure( LowLevelPutException e, Object keyNum, ObjectContainer container, ClientContext context) { synchronized (this) { if (finished) return; } if (persistent) container.activate(errors, 1); if (parent.isCancelled()) { fail(new InsertException(InsertException.CANCELLED), container, context); return; } if (logMINOR) Logger.minor(this, "onFailure() on " + e + " for " + this); switch (e.code) { case LowLevelPutException.COLLISION: fail(new InsertException(InsertException.COLLISION), container, context); return; case LowLevelPutException.INTERNAL_ERROR: fail(new InsertException(InsertException.INTERNAL_ERROR), container, context); return; case LowLevelPutException.REJECTED_OVERLOAD: errors.inc(InsertException.REJECTED_OVERLOAD); break; case LowLevelPutException.ROUTE_NOT_FOUND: errors.inc(InsertException.ROUTE_NOT_FOUND); break; case LowLevelPutException.ROUTE_REALLY_NOT_FOUND: errors.inc(InsertException.ROUTE_REALLY_NOT_FOUND); break; default: Logger.error(this, "Unknown LowLevelPutException code: " + e.code); errors.inc(InsertException.INTERNAL_ERROR); } if (persistent) container.activate(ctx, 1); if (e.code == LowLevelPutException.ROUTE_NOT_FOUND || e.code == LowLevelPutException.ROUTE_REALLY_NOT_FOUND) { consecutiveRNFs++; if (logMINOR) Logger.minor( this, "Consecutive RNFs: " + consecutiveRNFs + " / " + ctx.consecutiveRNFsCountAsSuccess); if (consecutiveRNFs == ctx.consecutiveRNFsCountAsSuccess) { if (logMINOR) Logger.minor(this, "Consecutive RNFs: " + consecutiveRNFs + " - counting as success"); onSuccess(keyNum, container, context); return; } } else consecutiveRNFs = 0; if (logMINOR) Logger.minor(this, "Failed: " + e); retries++; if ((retries > ctx.maxInsertRetries) && (ctx.maxInsertRetries != -1)) { fail(InsertException.construct(persistent ? errors.clone() : errors), container, context); if (persistent) container.deactivate(ctx, 1); return; } if (persistent) { container.store(this); container.deactivate(ctx, 1); } getScheduler(context).registerInsert(this, persistent, false, container); }
public static void main(String[] args) throws InvalidThresholdException, IOException, NodeInitException, InterruptedException { Node node = null; Node secondNode = null; try { String ipOverride = null; if (args.length > 0) ipOverride = args[0]; File dir = new File("bootstrap-push-pull-test"); FileUtil.removeAll(dir); RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, LogLevel.ERROR, "", false); File seednodes = new File("seednodes.fref"); if (!seednodes.exists() || seednodes.length() == 0 || !seednodes.canRead()) { System.err.println("Unable to read seednodes.fref, it doesn't exist, or is empty"); System.exit(EXIT_NO_SEEDNODES); } File innerDir = new File(dir, Integer.toString(DARKNET_PORT1)); innerDir.mkdir(); FileInputStream fis = new FileInputStream(seednodes); FileUtil.writeTo(fis, new File(innerDir, "seednodes.fref")); fis.close(); // Create one node Executor executor = new PooledExecutor(); node = NodeStarter.createTestNode( DARKNET_PORT1, OPENNET_PORT1, dir.getPath(), false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 5 * 1024 * 1024, true, true, true, true, true, true, true, 12 * 1024, false, true, false, false, ipOverride); // NodeCrypto.DISABLE_GROUP_STRIP = true; // Logger.setupStdoutLogging(LogLevel.MINOR, // "freenet:NORMAL,freenet.node.NodeDispatcher:MINOR,freenet.node.FNPPacketMangler:MINOR"); Logger.getChain().setThreshold(LogLevel.ERROR); // kill logging // Start it node.start(true); if (!TestUtil.waitForNodes(node)) { node.park(); System.exit(EXIT_FAILED_TARGET); } System.err.println("Creating test data: " + TEST_SIZE + " bytes."); Bucket data = node.clientCore.tempBucketFactory.makeBucket(TEST_SIZE); OutputStream os = data.getOutputStream(); byte[] buf = new byte[4096]; for (long written = 0; written < TEST_SIZE; ) { node.fastWeakRandom.nextBytes(buf); int toWrite = (int) Math.min(TEST_SIZE - written, buf.length); os.write(buf, 0, toWrite); written += toWrite; } os.close(); System.err.println("Inserting test data."); HighLevelSimpleClient client = node.clientCore.makeClient((short) 0); InsertBlock block = new InsertBlock(data, new ClientMetadata(), FreenetURI.EMPTY_CHK_URI); long startInsertTime = System.currentTimeMillis(); FreenetURI uri; try { uri = client.insert(block, false, null); } catch (InsertException e) { System.err.println("INSERT FAILED: " + e); e.printStackTrace(); System.exit(EXIT_INSERT_FAILED); return; } long endInsertTime = System.currentTimeMillis(); System.err.println( "RESULT: Insert took " + (endInsertTime - startInsertTime) + "ms (" + TimeUtil.formatTime(endInsertTime - startInsertTime) + ") to " + uri + " ."); node.park(); // Bootstrap a second node. File secondInnerDir = new File(dir, Integer.toString(DARKNET_PORT2)); secondInnerDir.mkdir(); fis = new FileInputStream(seednodes); FileUtil.writeTo(fis, new File(secondInnerDir, "seednodes.fref")); fis.close(); executor = new PooledExecutor(); secondNode = NodeStarter.createTestNode( DARKNET_PORT2, OPENNET_PORT2, dir.getPath(), false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 5 * 1024 * 1024, true, true, true, true, true, true, true, 12 * 1024, false, true, false, false, ipOverride); secondNode.start(true); if (!TestUtil.waitForNodes(secondNode)) { secondNode.park(); System.exit(EXIT_FAILED_TARGET); } // Fetch the data long startFetchTime = System.currentTimeMillis(); client = secondNode.clientCore.makeClient((short) 0); try { client.fetch(uri); } catch (FetchException e) { System.err.println("FETCH FAILED: " + e); e.printStackTrace(); System.exit(EXIT_FETCH_FAILED); return; } long endFetchTime = System.currentTimeMillis(); System.err.println( "RESULT: Fetch took " + (endFetchTime - startFetchTime) + "ms (" + TimeUtil.formatTime(endFetchTime - startFetchTime) + ") of " + uri + " ."); secondNode.park(); System.exit(0); } catch (Throwable t) { System.err.println("CAUGHT: " + t); t.printStackTrace(); try { if (node != null) node.park(); } catch (Throwable t1) { } ; try { if (secondNode != null) secondNode.park(); } catch (Throwable t1) { } ; System.exit(EXIT_THREW_SOMETHING); } }
public static void main(String[] args) { if (args.length < 1 || args.length > 2) { System.err.println( "Usage: java freenet.node.simulator.LongTermPushPullTest <unique identifier>"); System.exit(1); } String uid = args[0]; List<String> csvLine = new ArrayList<String>(); System.out.println("DATE:" + dateFormat.format(today.getTime())); csvLine.add(dateFormat.format(today.getTime())); System.out.println("Version:" + Version.buildNumber()); csvLine.add(String.valueOf(Version.buildNumber())); int exitCode = 0; Node node = null; Node node2 = null; FileInputStream fis = null; File file = new File("many-single-blocks-test-" + uid + ".csv"); long t1, t2; try { // INSERT STUFF final File dir = new File("longterm-mhk-test-" + uid); FileUtil.removeAll(dir); RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, LogLevel.ERROR, "", false); File seednodes = new File("seednodes.fref"); if (!seednodes.exists() || seednodes.length() == 0 || !seednodes.canRead()) { System.err.println("Unable to read seednodes.fref, it doesn't exist, or is empty"); System.exit(EXIT_NO_SEEDNODES); } final File innerDir = new File(dir, Integer.toString(DARKNET_PORT1)); innerDir.mkdir(); fis = new FileInputStream(seednodes); FileUtil.writeTo(fis, new File(innerDir, "seednodes.fref")); fis.close(); // Create one node node = NodeStarter.createTestNode( DARKNET_PORT1, OPENNET_PORT1, dir.getPath(), false, Node.DEFAULT_MAX_HTL, 0, random, new PooledExecutor(), 1000, 4 * 1024 * 1024, true, true, true, true, true, true, true, 12 * 1024, true, true, false, false, null); Logger.getChain().setThreshold(LogLevel.ERROR); // Start it node.start(true); t1 = System.currentTimeMillis(); if (!TestUtil.waitForNodes(node)) { exitCode = EXIT_FAILED_TARGET; return; } t2 = System.currentTimeMillis(); System.out.println("SEED-TIME:" + (t2 - t1)); csvLine.add(String.valueOf(t2 - t1)); HighLevelSimpleClient client = node.clientCore.makeClient((short) 0, false, false); int successes = 0; long startInsertsTime = System.currentTimeMillis(); InsertBatch batch = new InsertBatch(client); // Inserts are sloooooow so do them in parallel. for (int i = 0; i < INSERTED_BLOCKS; i++) { System.err.println("Inserting block " + i); RandomAccessBucket single = randomData(node); InsertBlock block = new InsertBlock(single, new ClientMetadata(), FreenetURI.EMPTY_CHK_URI); batch.startInsert(block); } batch.waitUntilFinished(); FreenetURI[] uris = batch.getURIs(); long[] times = batch.getTimes(); InsertException[] errors = batch.getErrors(); for (int i = 0; i < INSERTED_BLOCKS; i++) { if (uris[i] != null) { csvLine.add(String.valueOf(times[i])); csvLine.add(uris[i].toASCIIString()); System.out.println("Pushed block " + i + " : " + uris[i] + " in " + times[i]); successes++; } else { csvLine.add(InsertException.getShortMessage(errors[i].getMode())); csvLine.add("N/A"); System.out.println("Failed to push block " + i + " : " + errors[i]); } } long endInsertsTime = System.currentTimeMillis(); System.err.println( "Succeeded inserts: " + successes + " of " + INSERTED_BLOCKS + " in " + (endInsertsTime - startInsertsTime) + "ms"); FetchContext fctx = client.getFetchContext(); fctx.maxNonSplitfileRetries = 0; fctx.maxSplitfileBlockRetries = 0; RequestClient requestContext = new RequestClientBuilder().build(); // PARSE FILE AND FETCH OLD STUFF IF APPROPRIATE FreenetURI[] mhkURIs = new FreenetURI[3]; fis = new FileInputStream(file); BufferedReader br = new BufferedReader(new InputStreamReader(fis, ENCODING)); String line = null; GregorianCalendar target = (GregorianCalendar) today.clone(); target.set(Calendar.HOUR_OF_DAY, 0); target.set(Calendar.MINUTE, 0); target.set(Calendar.MILLISECOND, 0); target.set(Calendar.SECOND, 0); GregorianCalendar[] targets = new GregorianCalendar[MAX_N + 1]; for (int i = 0; i < targets.length; i++) { targets[i] = ((GregorianCalendar) target.clone()); targets[i].add(Calendar.DAY_OF_MONTH, -((1 << i) - 1)); targets[i].getTime(); } int[] totalFetchesByDelta = new int[MAX_N + 1]; int[] totalSuccessfulFetchesByDelta = new int[MAX_N + 1]; long[] totalFetchTimeByDelta = new long[MAX_N + 1]; loopOverLines: while ((line = br.readLine()) != null) { for (int i = 0; i < mhkURIs.length; i++) mhkURIs[i] = null; // System.out.println("LINE: "+line); String[] split = line.split("!"); Date date = dateFormat.parse(split[0]); GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); calendar.setTime(date); System.out.println("Date: " + dateFormat.format(calendar.getTime())); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.MILLISECOND, 0); calendar.set(Calendar.SECOND, 0); calendar.getTime(); FreenetURI[] insertedURIs = new FreenetURI[INSERTED_BLOCKS]; int[] insertTimes = new int[INSERTED_BLOCKS]; if (split.length < 3) continue; int seedTime = Integer.parseInt(split[2]); System.out.println("Seed time: " + seedTime); if (split.length < 4) continue; int token = 3; if (split.length < token + INSERTED_BLOCKS * 2) continue; for (int i = 0; i < INSERTED_BLOCKS; i++) { try { insertTimes[i] = Integer.parseInt(split[token]); } catch (NumberFormatException e) { insertTimes[i] = -1; } token++; try { insertedURIs[i] = new FreenetURI(split[token]); } catch (MalformedURLException e) { insertedURIs[i] = null; } token++; System.out.println("Key insert " + i + " : " + insertedURIs[i] + " in " + insertTimes[i]); } for (int i = 0; i < targets.length; i++) { if (Math.abs(targets[i].getTimeInMillis() - calendar.getTimeInMillis()) < HOURS.toMillis(12)) { System.out.println("Found row for target date " + ((1 << i) - 1) + " days ago."); System.out.println("Version: " + split[1]); csvLine.add(Integer.toString(i)); int pulled = 0; int inserted = 0; for (int j = 0; j < INSERTED_BLOCKS; j++) { if (insertedURIs[j] == null) { csvLine.add("INSERT FAILED"); continue; } inserted++; try { t1 = System.currentTimeMillis(); FetchWaiter fw = new FetchWaiter(requestContext); client.fetch(insertedURIs[j], 32768, fw, fctx); fw.waitForCompletion(); t2 = System.currentTimeMillis(); System.out.println("PULL-TIME FOR BLOCK " + j + ": " + (t2 - t1)); csvLine.add(String.valueOf(t2 - t1)); pulled++; } catch (FetchException e) { if (e.getMode() != FetchExceptionMode.ALL_DATA_NOT_FOUND && e.getMode() != FetchExceptionMode.DATA_NOT_FOUND) e.printStackTrace(); csvLine.add(FetchException.getShortMessage(e.getMode())); System.err.println("FAILED PULL FOR BLOCK " + j + ": " + e); } } System.out.println( "Pulled " + pulled + " blocks of " + inserted + " from " + ((1 << i) - 1) + " days ago."); } } while (split.length > token + INSERTED_BLOCKS) { int delta; try { delta = Integer.parseInt(split[token]); } catch (NumberFormatException e) { System.err.println("Unable to parse token " + token + " = \"" + token + "\""); System.err.println("This is supposed to be a delta"); System.err.println( "Skipping the rest of the line for date " + dateFormat.format(calendar.getTime())); continue loopOverLines; } System.out.println("Delta: " + ((1 << delta) - 1) + " days"); token++; int totalFetchTime = 0; int totalSuccesses = 0; int totalFetches = 0; for (int i = 0; i < INSERTED_BLOCKS; i++) { if (split[token].equals("")) continue; int mhkFetchTime = -1; totalFetches++; try { mhkFetchTime = Integer.parseInt(split[token]); System.out.println( "Fetched block #" + i + " on " + date + " in " + mhkFetchTime + "ms"); totalSuccesses++; totalFetchTime += mhkFetchTime; } catch (NumberFormatException e) { System.out.println("Failed block #" + i + " on " + date + " : " + split[token]); } token++; } totalFetchesByDelta[delta] += totalFetches; totalSuccessfulFetchesByDelta[delta] += totalSuccesses; totalFetchTimeByDelta[delta] += totalFetchTime; System.err.println( "Succeeded: " + totalSuccesses + " of " + totalFetches + " average " + ((double) totalFetchTime) / ((double) totalSuccesses) + "ms for delta " + delta + " on " + dateFormat.format(date)); } } System.out.println(); System.out.println(); for (int i = 0; i < MAX_N + 1; i++) { System.out.println( "DELTA: " + i + " days: Total fetches: " + totalFetchesByDelta[i] + " total successes " + totalSuccessfulFetchesByDelta[i] + " = " + ((totalSuccessfulFetchesByDelta[i] * 100.0) / totalFetchesByDelta[i]) + "% in " + (totalFetchTimeByDelta[i] * 1.0) / totalSuccessfulFetchesByDelta[i] + "ms"); } fis.close(); fis = null; } catch (Throwable t) { t.printStackTrace(); exitCode = EXIT_THREW_SOMETHING; } finally { try { if (node != null) node.park(); } catch (Throwable tt) { } try { if (node2 != null) node2.park(); } catch (Throwable tt) { } Closer.close(fis); writeToStatusLog(file, csvLine); System.out.println("Exiting with status " + exitCode); System.exit(exitCode); } }