wip on server-side handling of browse v2

browse-v2
Zlatin Balevsky 2022-08-28 00:45:51 +01:00
parent 5a172d1eaf
commit 1d8f0f74af
No known key found for this signature in database
GPG Key ID: A72832072D525E41
8 changed files with 114 additions and 39 deletions

View File

@ -115,10 +115,10 @@ class BrowseManager {
tempTree.list(path, topLevelItems)
}
int itemCount = topLevelItems.dirs.size() + topLevelItems.files.size()
topLevelItems.files.values().each {it.hit(browser, System.currentTimeMillis(), "Browse Host")}
OutputStream os = endpoint.getOutputStream()
os.write("ItemCount:${itemCount}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("Files:${topLevelItems.files.size()}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("Dirs:${topLevelItems.dirs.size()}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("\r\n".getBytes(StandardCharsets.US_ASCII))
JsonOutput jsonOutput = new JsonOutput()
@ -158,8 +158,8 @@ class BrowseManager {
def cb = new ListCallback()
tempTree.list(requestedPath, cb)
itemCount = cb.dirs.size() + cb.files.size()
os.write("ItemCount:${itemCount}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("Files:${cb.files.size()}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("Dirs:${cb.dirs.size()}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("\r\n".getBytes(StandardCharsets.US_ASCII))
gzos = new GZIPOutputStream(os)

View File

@ -1,5 +1,6 @@
package com.muwire.core.search
import com.muwire.core.Constants
import com.muwire.core.EventBus
import com.muwire.core.Persona
import com.muwire.core.connection.Endpoint
@ -23,7 +24,7 @@ class BrowseSession implements Runnable {
private final EventBus eventBus
private final I2PConnector connector
private final Persona me
private volatile Thread currentThrad
private volatile Thread currentThread
private volatile boolean closed
BrowseSession(EventBus eventBus, I2PConnector connector, UIBrowseEvent event, Persona me) {
@ -36,7 +37,7 @@ class BrowseSession implements Runnable {
void run() {
if (closed)
return
currentThrad = Thread.currentThread()
currentThread = Thread.currentThread()
Endpoint endpoint = null
try {
eventBus.publish(new BrowseStatusEvent(host : event.host, status : BrowseStatus.CONNECTING,
@ -46,6 +47,7 @@ class BrowseSession implements Runnable {
os.write("BROWSE\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("Persona:${me.toBase64()}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("Path:true\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("Version:${Constants.BROWSE_VERSION}\r\n".getBytes(StandardCharsets.US_ASCII))
os.write("\r\n".getBytes(StandardCharsets.US_ASCII))
InputStream is = endpoint.getInputStream()
@ -70,41 +72,92 @@ class BrowseSession implements Runnable {
if (profileHeader.getPersona() != event.host)
throw new IOException("Sender profile mismatch")
}
int version = 1
if (headers.containsKey("Version"))
version = Integer.parseInt(headers['Version'])
// at this stage, start pulling the results
UUID uuid = event.uuid
eventBus.publish(new BrowseStatusEvent(host: event.host, status : BrowseStatus.FETCHING,
totalResults : results, uuid : uuid))
log.info("Starting to fetch $results results with uuid $uuid")
// if we're version 1 just pull everything
if (version == 1) {
eventBus.publish(new BrowseStatusEvent(host: event.host, status: BrowseStatus.FETCHING,
totalResults: results, currentItems: results, uuid: uuid))
log.info("Starting to fetch $results results with uuid $uuid")
JsonSlurper slurper = new JsonSlurper()
DataInputStream dis = new DataInputStream(new GZIPInputStream(is))
UIResultEvent[] batch = new UIResultEvent[Math.min(BATCH_SIZE, results)]
int j = 0
for (int i = 0; i < results; i++) {
if (closed)
return
log.fine("parsing result $i at batch position $j")
JsonSlurper slurper = new JsonSlurper()
DataInputStream dis = new DataInputStream(new GZIPInputStream(is))
UIResultEvent[] batch = new UIResultEvent[Math.min(BATCH_SIZE, results)]
int j = 0
for (int i = 0; i < results; i++) {
if (closed)
return
log.fine("parsing result $i at batch position $j")
int size = dis.readUnsignedShort()
byte [] tmp = new byte[size]
dis.readFully(tmp)
def json = slurper.parse(tmp)
UIResultEvent result = ResultsParser.parse(event.host, uuid, json)
result.chat = chat
result.profileHeader = profileHeader
batch[j++] = result
def json = readJson(slurper, dis)
UIResultEvent result = ResultsParser.parse(event.host, uuid, json)
result.chat = chat
result.profileHeader = profileHeader
batch[j++] = result
// publish piecemally
if (j == batch.length) {
eventBus.publish(new UIResultBatchEvent(results : batch, uuid : uuid))
j = 0
batch = new UIResultEvent[Math.min(results - i - 1, BATCH_SIZE)]
log.fine("publishing batch, next batch size ${batch.length}")
// publish piecemally
if (j == batch.length) {
eventBus.publish(new UIResultBatchEvent(results: batch, uuid: uuid))
j = 0
batch = new UIResultEvent[Math.min(results - i - 1, BATCH_SIZE)]
log.fine("publishing batch, next batch size ${batch.length}")
}
}
}
} else if (version == 2) {
// version 2 should have Files and Dirs headers
if (!headers.containsKey("Files"))
throw new Exception("Files header missing")
int files = Integer.parseInt(headers['Files'])
if (!headers.containsKey("Dirs"))
throw new Exception("Dirs header missing")
int dirs = Integer.parseInt(headers['Dirs'])
eventBus.publish(new BrowseStatusEvent(host: event.host, status: BrowseStatus.FETCHING,
totalResults: results, currentItems: (files + dirs), uuid: uuid))
log.info("starting to fetch top-level ${files} files and ${dirs} dirs with uuid $uuid")
JsonSlurper slurper = new JsonSlurper()
DataInputStream dis = new DataInputStream(new GZIPInputStream(is))
UIResultEvent[] batch = new UIResultEvent[Math.min(BATCH_SIZE, results)]
int j = 0
for (int i = 0; i < files; i ++) {
if (closed)
return
log.fine("parsing result $i at batch position $j")
def json = readJson(slurper, dis)
UIResultEvent result = ResultsParser.parse(event.host, uuid, json)
result.chat = chat
result.profileHeader = profileHeader
batch[j++] = result
// publish piecemally
if (j == batch.length) {
eventBus.publish(new UIResultBatchEvent(results: batch, uuid: uuid))
j = 0
batch = new UIResultEvent[Math.min(results - i - 1, BATCH_SIZE)]
log.fine("publishing batch, next batch size ${batch.length}")
}
}
for (int i = 0; i < dirs; i++) {
if (closed)
return
def json = readJson(slurper, dis)
if (!json.directory || json.path == null)
throw new Exception("Invalid dir json")
List<String> path = json.path.collect {DataUtil.readi18nString(Base64.decode(it))}
def event = new UIBrowseDirEvent(uuid : uuid,
path : path.toArray(new String[0]))
eventBus.publish(event)
}
} else
throw new Exception("unrecognized version $version")
eventBus.publish(new BrowseStatusEvent(host: event.host, status : BrowseStatus.FINISHED, uuid : uuid))
} catch (Exception bad) {
if (!closed) {
@ -112,14 +165,21 @@ class BrowseSession implements Runnable {
eventBus.publish(new BrowseStatusEvent(host: event.host, status: BrowseStatus.FAILED, uuid: event.uuid))
}
} finally {
currentThrad = null
currentThread = null
endpoint?.close()
}
}
private static def readJson(JsonSlurper slurper, DataInputStream dis) {
int size = dis.readUnsignedShort()
byte[] tmp = new byte[size]
dis.readFully(tmp)
slurper.parse(tmp)
}
void close() {
log.info("closing browse session for UUID ${event.uuid}")
closed = true
currentThrad?.interrupt()
currentThread?.interrupt()
}
}

View File

@ -8,5 +8,6 @@ class BrowseStatusEvent extends Event {
BrowseStatus status
BrowseSession session
int totalResults
int currentItems
UUID uuid
}

View File

@ -0,0 +1,8 @@
package com.muwire.core.search
import com.muwire.core.Event
class UIBrowseDirEvent extends Event {
UUID uuid
String[] path
}

View File

@ -105,8 +105,10 @@ class BrowseController {
}
for(BrowseStatusEvent event : statusCopy) {
model.status = event.status
if (event.status == BrowseStatus.FETCHING)
if(event.status == BrowseStatus.FETCHING) {
model.currentBatch = event.currentItems
model.totalResults = event.totalResults
}
}
if (!statusCopy.isEmpty()) {
if ((model.status == BrowseStatus.FINISHED || model.status == BrowseStatus.FAILED) &&

View File

@ -508,7 +508,8 @@ ADD_COMMENT_SINGLE=Add comment to {0}
ADD_COMMENT_TOO_LONG=Comment too long
ADD_COMMENT_TOO_LONG_BODY=Your comment is too long - {0} characters. The maximum length is {1} characters.
## Browse dialog
## Browse pane
BROWSE_TOTAL_FILES=Total files
## Close Warning prompt
CLOSE_MUWIRE_QUESTION=Close MuWire?

View File

@ -27,6 +27,7 @@ class BrowseModel {
@Observable boolean downloadActionEnabled
@Observable boolean viewDetailsActionEnabled
@Observable int totalResults
@Observable int currentBatch
@Observable int resultCount
@Observable boolean filterEnabled
@Observable boolean clearFilterEnabled

View File

@ -67,9 +67,11 @@ class BrowseView {
label(text: trans("STATUS") + ":")
label(text: bind { trans(model.status.name()) })
label(text: bind {
model.totalResults == 0 ? "" :
"$model.resultCount/$model.totalResults (" + Math.round(model.resultCount * 100 / model.totalResults)+ "%)"
model.currentBatch == 0 ? "" :
"$model.resultCount/$model.currentBatch (" + Math.round(model.resultCount * 100 / model.currentBatch)+ "%)"
})
label(text : trans("BROWSE_TOTAL_FILES") + ":")
label(text: bind {model.totalResults})
}
panel(constraints: BorderLayout.EAST) {
button(text: trans("VIEW_PROFILE"), toolTipText: trans("TOOLTIP_VIEW_PROFILE"), viewProfileAction)