private void startNewUploads() { boolean isLimited = true; int currentAllowedUploadCount = 0; { final int allowedConcurrentUploads = Core.frostSettings.getIntValue(SettingsClass.UPLOAD_MAX_THREADS); if (allowedConcurrentUploads <= 0) { isLimited = false; } else { int runningUploads = 0; for (final FrostUploadItem ulItem : uploadModelItems.values()) { if (!ulItem.isExternal() && ulItem.getState() == FrostUploadItem.STATE_PROGRESS) { runningUploads++; } } currentAllowedUploadCount = allowedConcurrentUploads - runningUploads; if (currentAllowedUploadCount < 0) { currentAllowedUploadCount = 0; } } } { while (!isLimited || currentAllowedUploadCount > 0) { final FrostUploadItem ulItem = FileTransferManager.inst().getUploadManager().selectNextUploadItem(); if (ulItem == null) { break; } if (startUpload(ulItem)) { currentAllowedUploadCount--; } } } }
private void addExternalItem(final FcpPersistentPut uploadRequest) { final FrostUploadItem ulItem = new FrostUploadItem(); ulItem.setGqIdentifier(uploadRequest.getIdentifier()); ulItem.setExternal(true); // direct uploads maybe have no filename, use identifier String fileName = uploadRequest.getFilename(); if (fileName == null) { fileName = uploadRequest.getIdentifier(); } else if (fileName.indexOf('/') > -1 || fileName.indexOf('\\') > -1) { // filename contains directories, use only filename final String stmp = new File(fileName).getName(); if (stmp.length() > 0) { fileName = stmp; // use plain filename } } ulItem.setFile(new File(fileName)); ulItem.setFileName(fileName); ulItem.setFileSize(uploadRequest.getFileSize()); ulItem.setPriority(uploadRequest.getPriority()); ulItem.setState(FrostUploadItem.STATE_PROGRESS); SwingUtilities.invokeLater( new Runnable() { public void run() { uploadModel.addExternalItem(ulItem); } }); applyState(ulItem, uploadRequest); }
public void persistentRequestError(final String id, final NodeMessage nm) { if (uploadModelItems.containsKey(id)) { final FrostUploadItem item = uploadModelItems.get(id); item.setEnabled(false); item.setState(FrostUploadItem.STATE_FAILED); item.setErrorCodeDescription(nm.getStringValue("CodeDescription")); } else if (downloadModelItems.containsKey(id)) { final FrostDownloadItem item = downloadModelItems.get(id); item.setEnabled(false); item.setState(FrostDownloadItem.STATE_FAILED); item.setErrorCodeDescription(nm.getStringValue("CodeDescription")); } else { System.out.println("persistentRequestError: ID not in any model: " + id); } }
public synchronized void appendItemToQueue(final FrostUploadItem item) { final String id = item.getGqIdentifier(); directPUTsInProgress.add(id); queue.addLast(item); notifyAll(); // notify all waiters (if any) of new record }
public boolean isDirectTransferInProgress(final FrostUploadItem ulItem) { final String id = ulItem.getGqIdentifier(); if (directPUTsInProgress.contains(id)) { return true; } if (directPUTsWithoutAnswer.contains(id)) { return true; } return false; }
public boolean startUpload(final FrostUploadItem ulItem) { if (ulItem == null || ulItem.getState() != FrostUploadItem.STATE_WAITING) { return false; } ulItem.setUploadStartedMillis(System.currentTimeMillis()); ulItem.setState(FrostUploadItem.STATE_PROGRESS); // start the upload final boolean doMime; final boolean setTargetFileName; if (ulItem.isSharedFile()) { doMime = false; setTargetFileName = false; } else { doMime = true; setTargetFileName = true; } // try to start using DDA boolean isDda = fcpTools.startPersistentPutUsingDda( ulItem.getGqIdentifier(), ulItem.getFile(), ulItem.getFileName(), doMime, setTargetFileName, ulItem.getCompress(), ulItem.getFreenetCompatibilityMode(), ulItem.getPriority()); if (!isDda) { // upload was not startet because DDA is not allowed... // if UploadManager selected this file then it is not already in progress! directTransferQueue.appendItemToQueue(ulItem); } return true; }
public void persistentRequestRemoved(final FcpPersistentPut uploadRequest) { if (uploadModelItems.containsKey(uploadRequest.getIdentifier())) { final FrostUploadItem ulItem = uploadModelItems.get(uploadRequest.getIdentifier()); if (ulItem.isExternal()) { SwingUtilities.invokeLater( new Runnable() { public void run() { List<FrostUploadItem> itemList = new ArrayList<FrostUploadItem>(); itemList.add(ulItem); uploadModel.removeItems(itemList); } }); } else { if (ulItem.isInternalRemoveExpected()) { ulItem.setInternalRemoveExpected(false); // clear flag } else if (ulItem.getState() != FrostUploadItem.STATE_DONE) { ulItem.setEnabled(false); ulItem.setState(FrostUploadItem.STATE_FAILED); ulItem.setErrorCodeDescription("Disappeared from global queue"); } } } }
public void persistentRequestModified(final FcpPersistentPut uploadRequest) { if (uploadModelItems.containsKey(uploadRequest.getIdentifier())) { final FrostUploadItem ulItem = uploadModelItems.get(uploadRequest.getIdentifier()); ulItem.setPriority(uploadRequest.getPriority()); } }
/** Must be called after the upload and download model is initialized! */ public PersistenceManager(final UploadModel um, final DownloadModel dm) throws Throwable { showExternalItemsDownload = Core.frostSettings.getBoolValue(SettingsClass.GQ_SHOW_EXTERNAL_ITEMS_DOWNLOAD); showExternalItemsUpload = Core.frostSettings.getBoolValue(SettingsClass.GQ_SHOW_EXTERNAL_ITEMS_UPLOAD); if (FcpHandler.inst().getFreenetNode() == null) { throw new Exception("No freenet nodes defined"); } final NodeAddress na = FcpHandler.inst().getFreenetNode(); fcpConn = FcpListenThreadConnection.createInstance(na); fcpTools = new FcpMultiRequestConnectionFileTransferTools(fcpConn); Core.frostSettings.addPropertyChangeListener( new PropertyChangeListener() { public void propertyChange(final PropertyChangeEvent evt) { if (evt.getPropertyName().equals(SettingsClass.GQ_SHOW_EXTERNAL_ITEMS_DOWNLOAD)) { showExternalItemsDownload = Core.frostSettings.getBoolValue(SettingsClass.GQ_SHOW_EXTERNAL_ITEMS_DOWNLOAD); if (showExternalItemsDownload) { // get external items showExternalDownloadItems(); } } else if (evt.getPropertyName().equals(SettingsClass.GQ_SHOW_EXTERNAL_ITEMS_UPLOAD)) { showExternalItemsUpload = Core.frostSettings.getBoolValue(SettingsClass.GQ_SHOW_EXTERNAL_ITEMS_UPLOAD); if (showExternalItemsUpload) { // get external items showExternalUploadItems(); } } } }); uploadModel = um; downloadModel = dm; // initially get all items from model for (int x = 0; x < uploadModel.getItemCount(); x++) { final FrostUploadItem ul = (FrostUploadItem) uploadModel.getItemAt(x); if (ul.getGqIdentifier() != null) { uploadModelItems.put(ul.getGqIdentifier(), ul); } } for (int x = 0; x < downloadModel.getItemCount(); x++) { final FrostDownloadItem ul = (FrostDownloadItem) downloadModel.getItemAt(x); if (ul.getGqIdentifier() != null) { downloadModelItems.put(ul.getGqIdentifier(), ul); } } // enqueue listeners to keep updated about the model items uploadModel.addOrderedModelListener( new SortedModelListener<FrostUploadItem>() { public void modelCleared() { for (final FrostUploadItem ul : uploadModelItems.values()) { if (ul.isExternal() == false) { fcpTools.removeRequest(ul.getGqIdentifier()); } } uploadModelItems.clear(); } public void itemAdded(final int position, final FrostUploadItem item) { uploadModelItems.put(item.getGqIdentifier(), item); if (!item.isExternal()) { // maybe start immediately startNewUploads(); } } public void itemChanged(final int position, final FrostUploadItem item) {} public void itemsRemoved(final int[] positions, final List<FrostUploadItem> items) { for (final FrostUploadItem item : items) { uploadModelItems.remove(item.getGqIdentifier()); if (item.isExternal() == false) { fcpTools.removeRequest(item.getGqIdentifier()); } } } }); downloadModel.addOrderedModelListener( new SortedModelListener<FrostDownloadItem>() { public void modelCleared() { for (final FrostDownloadItem ul : downloadModelItems.values()) { if (ul.isExternal() == false) { fcpTools.removeRequest(ul.getGqIdentifier()); } } downloadModelItems.clear(); } public void itemAdded(final int position, final FrostDownloadItem item) { downloadModelItems.put(item.getGqIdentifier(), item); if (!item.isExternal()) { // maybe start immediately startNewDownloads(); } } public void itemChanged(final int position, final FrostDownloadItem item) {} public void itemsRemoved(final int[] positions, final List<FrostDownloadItem> items) { for (final FrostDownloadItem item : items) { downloadModelItems.remove(item.getGqIdentifier()); if (item.isExternal() == false) { fcpTools.removeRequest(item.getGqIdentifier()); } } } }); directTransferQueue = new DirectTransferQueue(); directTransferThread = new DirectTransferThread(); persistentQueue = new FcpPersistentQueue(fcpTools, this); }
@Override public void run() { final int maxAllowedExceptions = 5; int catchedExceptions = 0; while (true) { try { // if there is no work in queue this call waits for a new queue item final ModelItem<?> item = directTransferQueue.getItemFromQueue(); if (item == null) { // paranoia, should never happen Mixed.wait(5 * 1000); continue; } if (item instanceof FrostUploadItem) { // transfer bytes to node final FrostUploadItem ulItem = (FrostUploadItem) item; // FIXME: provide item, state=Transfer to node, % shows progress final String gqid = ulItem.getGqIdentifier(); final boolean doMime; final boolean setTargetFileName; if (ulItem.isSharedFile()) { doMime = false; setTargetFileName = false; } else { doMime = true; setTargetFileName = true; } final NodeMessage answer = fcpTools.startDirectPersistentPut( gqid, ulItem.getFile(), ulItem.getFileName(), doMime, setTargetFileName, ulItem.getCompress(), ulItem.getFreenetCompatibilityMode(), ulItem.getPriority()); if (answer == null) { final String desc = "Could not open a new FCP2 socket for direct put!"; final FcpResultPut result = new FcpResultPut(FcpResultPut.Error, -1, desc, false); FileTransferManager.inst().getUploadManager().notifyUploadFinished(ulItem, result); logger.severe(desc); } else { // wait for an answer, don't start request again directPUTsWithoutAnswer.add(gqid); } directPUTsInProgress.remove(gqid); } else if (item instanceof FrostDownloadItem) { // transfer bytes from node final FrostDownloadItem dlItem = (FrostDownloadItem) item; // FIXME: provide item, state=Transfer from node, % shows progress final String gqid = dlItem.getGqIdentifier(); final File targetFile = new File(dlItem.getDownloadFilename()); final boolean retryNow; NodeMessage answer = null; try { answer = fcpTools.startDirectPersistentGet(gqid, targetFile); } catch (final FileNotFoundException e) { final String msg = "Could not write to " + dlItem.getDownloadFilename() + ": " + e.getMessage(); System.out.println(msg); logger.severe(msg); } if (answer != null) { final FcpResultGet result = new FcpResultGet(true); FileTransferManager.inst() .getDownloadManager() .notifyDownloadFinished(dlItem, result, targetFile); retryNow = false; } else { logger.severe("Could not open a new fcp socket for direct get!"); final FcpResultGet result = new FcpResultGet(false); retryNow = FileTransferManager.inst() .getDownloadManager() .notifyDownloadFinished(dlItem, result, targetFile); } directGETsInProgress.remove(gqid); if (retryNow) { startDownload(dlItem); } } } catch (final Throwable t) { logger.log(Level.SEVERE, "Exception catched", t); catchedExceptions++; } if (catchedExceptions > maxAllowedExceptions) { logger.log(Level.SEVERE, "Stopping DirectTransferThread because of too much exceptions"); break; } } }
/** Apply the states of FcpRequestPut to the FrostUploadItem. */ private void applyState(final FrostUploadItem ulItem, final FcpPersistentPut putReq) { // when cancelled and we expect this, don't set failed; don't even set the old priority! if (ulItem.isInternalRemoveExpected() && putReq.isFailed()) { final int returnCode = putReq.getCode(); if (returnCode == 25) { return; } } if (directPUTsWithoutAnswer.contains(ulItem.getGqIdentifier())) { // we got an answer directPUTsWithoutAnswer.remove(ulItem.getGqIdentifier()); } // apply externally changed priority if (ulItem.getPriority() != putReq.getPriority()) { if (Core.frostSettings.getBoolValue(SettingsClass.FCP2_ENFORCE_FROST_PRIO_FILE_UPLOAD)) { // reset priority with our current value fcpTools.changeRequestPriority(putReq.getIdentifier(), ulItem.getPriority()); } else { // apply to uploaditem ulItem.setPriority(putReq.getPriority()); } } if (!putReq.isProgressSet() && !putReq.isSuccess() && !putReq.isFailed()) { if (ulItem.getState() == FrostUploadItem.STATE_WAITING) { ulItem.setState(FrostUploadItem.STATE_PROGRESS); } return; } if (putReq.isProgressSet()) { final int doneBlocks = putReq.getDoneBlocks(); final int totalBlocks = putReq.getTotalBlocks(); final boolean isFinalized = putReq.isFinalized(); if (totalBlocks > 0) { ulItem.setDoneBlocks(doneBlocks); ulItem.setTotalBlocks(totalBlocks); ulItem.setFinalized(isFinalized); ulItem.fireValueChanged(); } if (ulItem.getState() != FrostUploadItem.STATE_PROGRESS) { ulItem.setState(FrostUploadItem.STATE_PROGRESS); } } if (putReq.isSuccess()) { // maybe progress was not completely sent ulItem.setFinalized(true); if (ulItem.getTotalBlocks() > 0 && ulItem.getDoneBlocks() != ulItem.getTotalBlocks()) { ulItem.setDoneBlocks(ulItem.getTotalBlocks()); } final String chkKey = putReq.getUri(); if (ulItem.isExternal()) { ulItem.setState(FrostUploadItem.STATE_DONE); ulItem.setKey(chkKey); } else { final FcpResultPut result = new FcpResultPut(FcpResultPut.Success, chkKey); FileTransferManager.inst().getUploadManager().notifyUploadFinished(ulItem, result); } } if (putReq.isFailed()) { final String desc = putReq.getCodeDesc(); if (ulItem.isExternal()) { ulItem.setState(FrostUploadItem.STATE_FAILED); ulItem.setErrorCodeDescription(desc); } else { final int returnCode = putReq.getCode(); final boolean isFatal = putReq.isFatal(); final FcpResultPut result; if (returnCode == 9) { result = new FcpResultPut(FcpResultPut.KeyCollision, returnCode, desc, isFatal); } else if (returnCode == 5) { result = new FcpResultPut(FcpResultPut.Retry, returnCode, desc, isFatal); } else { result = new FcpResultPut(FcpResultPut.Error, returnCode, desc, isFatal); } FileTransferManager.inst().getUploadManager().notifyUploadFinished(ulItem, result); } } }
/** * @param ulItem items whose global identifier is to check * @return true if this item is currently in the global queue, no matter in what state */ public boolean isItemInGlobalQueue(final FrostUploadItem ulItem) { return persistentQueue.isIdInGlobalQueue(ulItem.getGqIdentifier()); }