/** * データ量を取得 * * @param topic * @param category * @return */ public int calcMessageDataSize(String topic, String category) { // メモリ上に存在している場合は,コメントをメモリ上から取得 SortedSet<CommentElement> comments = localTopic.get(topic, category); // StringBuffer commentBuf = new StringBuffer("<topic>\n"); if (comments == null) { // コメントをファイルから持ってくる try { loadTopicFromFile(topic, category); comments = localTopic.get(topic, category); } catch (CommentNotFoundException e) { // コメントが見つからなかった,無視 } } return localTopic.calcMessageDataSize(topic, category); }
/** * 指定したトピックのコメントを取得 * * @param topic * @param category * @param fromNo * @return * @throws CommentNotFoundException */ public String getComment(String topic, String category, int fromNo) throws CommentNotFoundException { // メモリ上に存在している場合は,コメントをメモリ上から取得 SortedSet<CommentElement> comments = localTopic.get(topic, category, fromNo); // StringBuffer commentBuf = new StringBuffer("<topic>\n"); StringBuffer commentBuf = new StringBuffer(""); if (comments == null) { // コメントをファイルから持ってくる loadTopicFromFile(topic, category); comments = localTopic.get(topic, category, fromNo); } // コメントを取得 for (CommentElement buf : comments) { commentBuf.append(commentElementToXML(buf) + "\n"); } // 現在表示中のトピックを更新 currentTopic = new Pair<String, String>(topic, category); return commentBuf.toString(); }
/** * Reduce the load on the current hub so that it reaches the target load. We reduce load by * releasing topics using the {@link TopicManager} passed to the constructor. We use {@link * TopicManager#releaseTopics(int, org.apache.hedwig.util.Callback, Object)} to actually release * topics. * * @param targetLoad * @param callback a Callback<Long> that indicates how many topics we tried to release. * @param ctx */ public void reduceLoadTo(HubLoad targetLoad, final Callback<Long> callback, final Object ctx) { int targetTopics = (int) targetLoad.toHubLoadData().getNumTopics(); int numTopicsToRelease = (int) numTopics - targetTopics; // The number of topics we own is less than the target topic size. We don't release // any topics in this case. if (numTopicsToRelease <= 0) { callback.operationFinished(ctx, 0L); return; } // Call releaseTopics() on the topic manager to do this. We let the manager handle the release // policy. tm.releaseTopics(numTopicsToRelease, callback, ctx); }
/** 現在表示中のトピックを除いてメモリ上から削除する また,削除したトピックはファイルへと保存する */ public void garbageCollection() { // メモリ上に保持されているトピックをファイルへ移動する saveTopicToFile(); // トピック一覧を取得 Set<Pair<String, String>> topics = localTopic.getTopics(); if (topics == null) { return; } // 現在表示しているトピック以外を削除 for (Pair<String, String> topic : topics) { if (topic.equals(getCurrentTopic())) { continue; } remove(topic.getFirst(), topic.getSecond()); } }
/** * ファイルからトピックを読み込む * * @param topic * @param category * @throws CommentNotFoundException */ public void loadTopicFromFile(String topic, String category) throws CommentNotFoundException { try { File f = new File("./" + logDirectory + "/" + category + "/" + topic + ".dat"); byte[] b = new byte[(int) f.length()]; FileInputStream fi = new FileInputStream(f); fi.read(b); // 読み取ったデータ String data = new String(b, this.charsetName); fi.close(); List<CommentElement> topics = CommentElementXMLParser.XMLToCommentElement(data); if (topics != null) { for (CommentElement t : topics) { // データをメモリ上に読み込む localTopic.add(topic, category, t); // System.out.println("debug :" + t.getMessage() + " - " + t.getDate()); } } } catch (Exception e) { // データを読み込めなかった場合 throw new CommentNotFoundException("トピック:" + topic + "は見つかりませんでした."); } }
/** * メモリ上に保持しているトピックをファイルへ保存する * * @param topic * @param category * @return */ public boolean saveTopicToFile() { Set<Pair<String, String>> topics = localTopic.getTopics(); // データが一つも存在しない if (topics == null) { return false; } // ログディレクトリを作成 try { File logDir = new File("./" + logDirectory); if (!logDir.exists()) { // ディレクトリが存在しないので作成する if (logDir.mkdir() == false) { throw new IOException(logDirectory + "ディレクトリを作成できませんでした."); } } // メモリ上に存在するすべてのトピックをファイルへ保存する for (Pair<String, String> topic : topics) { // ファイル名 ./カテゴリ名/トピック名.dat String filename = "./" + logDirectory + "/" + topic.getSecond() + "/" + topic.getFirst() + ".dat"; // トピック保存ディレクトリを作成 // ディレクトリ名はトピックのカテゴリ名 File dir = new File("./" + logDirectory + "/" + topic.getSecond()); if (!dir.exists()) { // ディレクトリが存在しないので作成する if (dir.mkdir() == false) { throw new IOException("ディレクトリを作成できませんでした."); } } FileOutputStream fos = new FileOutputStream(filename); OutputStreamWriter osw = new OutputStreamWriter(fos, charsetName); BufferedWriter bw = new BufferedWriter(osw); // ファイル書き込みデータ StringBuffer writeData = new StringBuffer("<?xml version=\"1.0\" encoding=\"" + charsetName + "\"?>\n"); writeData.append("<topic>\n"); SortedSet<CommentElement> comments = localTopic.get(topic.getFirst(), topic.getSecond()); // トピックの所属するすべてのコメントデータを書き込む for (CommentElement comment : comments) { writeData.append(commentElementToXML(comment) + "\n"); } writeData.append("</topic>"); // ファイル書き込み bw.write(writeData.toString()); // ファイルを閉じる bw.close(); osw.close(); fos.close(); } } catch (Exception e) { System.err.println(e); e.printStackTrace(); } return false; }
/** * 指定したトピックをメモリ上から削除する * * @param topic * @param category */ public void remove(String topic, String category) { localTopic.remove(topic, category); }
/** * @param tm The topic manager used to handle load shedding * @param tolerancePercentage The tolerance percentage for shedding load * @param maxLoadToShed The maximum amoung of load to shed in one call. */ public TopicBasedLoadShedder( TopicManager tm, double tolerancePercentage, PubSubProtocol.HubLoadData maxLoadToShed) { // Make sure that all functions in this class have a consistent view // of the load. So, we use the same topic list throughout. this(tm, tm.getNumTopics(), tolerancePercentage, maxLoadToShed); }