aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--gnunet-build/packages/gnunet/gnunet/Buildrules39
-rw-r--r--gnunet-build/packages/gnunet/gnunet/files/plugin_peerstore_emscripten.c219
-rw-r--r--src/js/configuration.js3
-rw-r--r--src/js/pre.js4
5 files changed, 176 insertions, 92 deletions
diff --git a/README.md b/README.md
index 1271812..c82e0bb 100644
--- a/README.md
+++ b/README.md
@@ -17,8 +17,7 @@ Roadmap
* gnunet-service-cadet.js - Done.
* gnunet-service-datastore.js - Building with heap backend plugin.
* Needs an [indexedDB] backend plugin.
- * gnunet-service-peerstore.js - TODO.
- * Needs an [indexedDB] backend plugin.
+ * gnunet-service-peerstore.js - Done, with [indexedDB] backend plugin.
* gnunet-service-fs.js - Done.
* Write a minimal UI that allows publishing, searching, and downloading via the
file-sharing service.
diff --git a/gnunet-build/packages/gnunet/gnunet/Buildrules b/gnunet-build/packages/gnunet/gnunet/Buildrules
index 6cafbad..3b58cd9 100644
--- a/gnunet-build/packages/gnunet/gnunet/Buildrules
+++ b/gnunet-build/packages/gnunet/gnunet/Buildrules
@@ -382,6 +382,44 @@ pkg_compile() {
cp "${S}/src/cadet/.libs/gnunet-service-cadet.js" \
"${D}/var/lib/gnunet/js/"
#
+ # Peerstore
+ #
+ ./libtool --tag=CC --mode=link \
+ emcc -fno-strict-aliasing -Wall \
+ -O2 \
+ -s DLOPEN_SUPPORT=1 -s SIDE_MODULE=1 \
+ -s EXPORTED_FUNCTIONS='[
+ "_libgnunet_plugin_peerstore_emscripten_init",
+ ]' \
+ "-I${SYSROOT}/usr/include" "-L${SYSROOT}/usr/lib" \
+ -o "${S}/src/peerstore/libgnunet_plugin_peerstore_emscripten.js" \
+ "${S}/src/peerstore/plugin_peerstore_emscripten.lo"
+ ( echo '['
+ sed -e 's/.*/"&",/' < "${TEMP_DIR}/imports"
+ echo '"_GNUNET_log_setup",'
+ echo '"_GNUNET_xstrdup_",'
+ echo '"_main"]' ) > peerstore.exports
+ ./libtool --tag=CC --mode=link \
+ emcc -fno-strict-aliasing -Wall \
+ -O2 \
+ -s DLOPEN_SUPPORT=1 -s MAIN_MODULE=1 \
+ -s EXPORTED_FUNCTIONS=@peerstore.exports \
+ "-I${SYSROOT}/usr/include" "-L${SYSROOT}/usr/lib" \
+ -o "${S}/src/peerstore/gnunet-service-peerstore.js" \
+ "${S}/src/peerstore/gnunet_service_peerstore"*.o \
+ "${S}/src/util/libgnunetutil.la" \
+ "${SYSROOT}/usr/lib/libgcrypt.la" \
+ "${SYSROOT}/usr/lib/libgpg-error.la" \
+ --js-library "${BUILDROOT}/src/js/configuration.js" \
+ --js-library "${BUILDROOT}/src/js/plugin.js" \
+ --js-library "${BUILDROOT}/src/js/scheduler.js" \
+ --js-library "${BUILDROOT}/src/js/server.js" \
+ --js-library "${BUILDROOT}/src/js/service.js" \
+ --pre-js "${BUILDROOT}/src/js/pre.js"
+ cp "${S}/src/peerstore/.libs/gnunet-service-peerstore.js" \
+ "${S}/src/peerstore/libgnunet_plugin_peerstore_emscripten.js" \
+ "${D}/var/lib/gnunet/js/"
+ #
# File Sharing
#
( echo '['
@@ -404,6 +442,7 @@ pkg_compile() {
"${S}/src/datastore/libgnunetdatastore.la" \
"${S}/src/dht/libgnunetdht.la" \
"${S}/src/fs/libgnunetfs.la" \
+ "${S}/src/peerstore/libgnunetpeerstore.la" \
"${S}/src/statistics/libgnunetstatistics.la" \
"${S}/src/util/libgnunetutil.la" \
"${SYSROOT}/usr/lib/libgcrypt.la" \
diff --git a/gnunet-build/packages/gnunet/gnunet/files/plugin_peerstore_emscripten.c b/gnunet-build/packages/gnunet/gnunet/files/plugin_peerstore_emscripten.c
index 88f84e5..79cab26 100644
--- a/gnunet-build/packages/gnunet/gnunet/files/plugin_peerstore_emscripten.c
+++ b/gnunet-build/packages/gnunet/gnunet/files/plugin_peerstore_emscripten.c
@@ -1,6 +1,6 @@
/*
* This file is part of GNUnet
- * (C) 2013 Christian Grothoff (and other contributing authors)
+ * (C) 2013-2014 Christian Grothoff (and other contributing authors)
*
* GNUnet is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
@@ -19,36 +19,25 @@
*/
/**
- * @file peerstore/plugin_peerstore_sqlite.c
- * @brief sqlite-based peerstore backend
+ * @file peerstore/plugin_peerstore_emscripten.c
+ * @brief IndexedDB-based peerstore backend
* @author Omar Tarabai
+ * @author David Barksdale <amatus@amatus.name>
*/
+#include <emscripten.h>
#include "platform.h"
#include "gnunet_peerstore_plugin.h"
#include "gnunet_peerstore_service.h"
#include "peerstore.h"
/**
- * After how many ms "busy" should a DB operation fail for good? A
- * low value makes sure that we are more responsive to requests
- * (especially PUTs). A high value guarantees a higher success rate
- * (SELECTs in iterate can take several seconds despite LIMIT=1).
- *
- * The default value of 1s should ensure that users do not experience
- * huge latencies while at the same time allowing operations to
- * succeed with reasonable probability.
- */
-#define BUSY_TIMEOUT_MS 1000
-
-/**
* Log an error message at log-level 'level' that indicates
* a failure of the command 'cmd' on file 'filename'
* with the message given by strerror(errno).
*/
-#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "peerstore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
-
-#define LOG(kind,...) GNUNET_log_from (kind, "peerstore-sqlite", __VA_ARGS__)
+#define LOG(kind,...) \
+ GNUNET_log_from (kind, "peerstore-emscripten", __VA_ARGS__)
/**
* Context for all functions in this plugin.
@@ -60,76 +49,9 @@ struct Plugin
* Configuration handle
*/
const struct GNUNET_CONFIGURATION_Handle *cfg;
-
- /**
- * Database filename.
- */
- char *fn;
-
- /**
- * Native SQLite database handle.
- */
- //XXX sqlite3 *dbh;
-
- /**
- * Precompiled SQL for inserting into peerstoredata
- */
- //XXX sqlite3_stmt *insert_peerstoredata;
-
- /**
- * Precompiled SQL for selecting from peerstoredata
- */
- //XXX sqlite3_stmt *select_peerstoredata;
-
- /**
- * Precompiled SQL for selecting from peerstoredata
- */
- //XXX sqlite3_stmt *select_peerstoredata_by_pid;
-
- /**
- * Precompiled SQL for selecting from peerstoredata
- */
- //XXX sqlite3_stmt *select_peerstoredata_by_key;
-
- /**
- * Precompiled SQL for selecting from peerstoredata
- */
- //XXX sqlite3_stmt *select_peerstoredata_by_all;
-
- /**
- * Precompiled SQL for deleting expired
- * records from peerstoredata
- */
- //XXX sqlite3_stmt *expire_peerstoredata;
-
- /**
- * Precompiled SQL for deleting records
- * with given key
- */
- //XXX sqlite3_stmt *delete_peerstoredata;
-
};
/**
- * Delete records with the given key
- *
- * @param cls closure (internal context for the plugin)
- * @param sub_system name of sub system
- * @param peer Peer identity (can be NULL)
- * @param key entry key string (can be NULL)
- * @return number of deleted records
- */
-static int
-peerstore_emscripten_delete_records(void *cls,
- const char *sub_system,
- const struct GNUNET_PeerIdentity *peer,
- const char *key)
-{
- struct Plugin *plugin = cls;
- return 0;
-}
-
-/**
* Delete expired records (expiry < now)
*
* @param cls closure (internal context for the plugin)
@@ -140,7 +62,22 @@ static int
peerstore_emscripten_expire_records(void *cls,
struct GNUNET_TIME_Absolute now)
{
- struct Plugin *plugin = cls;
+ EM_ASM_ARGS({
+ var now = $0;
+ var store =
+ psdb.transaction(['peerstore'], 'readwrite').objectStore('peerstore');
+ store.index('by_expiry').openKeyCursor(
+ IDBKeyRange.upperBound(now, true)).onsuccess = function(e) {
+ var cursor = e.target.result;
+ if (cursor) {
+ var request = store.delete(cursor.value);
+ request.onerror = function(e) {
+ Module.print('expiry request failed');
+ };
+ cursor.continue();
+ }
+ };
+ }, (double)now.abs_value_us);
return 0;
}
@@ -164,7 +101,56 @@ peerstore_emscripten_iterate_records (void *cls,
const char *key,
GNUNET_PEERSTORE_Processor iter, void *iter_cls)
{
- struct Plugin *plugin = cls;
+ EM_ASM_ARGS({
+ var sub_system = Pointer_stringify($0);
+ var peer = $1 ? Array.apply([], HEAP8.subarray($1, $1 + 32)) : null;
+ var key = $2 ? Pointer_stringify($2) : null;
+ var iter = $3;
+ var iter_cls = $4;
+ var key_range = [sub_system];
+ if (peer) {
+ key_range.push(peer);
+ }
+ if (key) {
+ key_range.push(key);
+ }
+ var store =
+ psdb.transaction(['peerstore'], 'readonly').objectStore('peerstore');
+ var index;
+ if (!peer && !key) {
+ index = store.index('by_subsystem');
+ } else if (!peer) {
+ index = store.index('by_key');
+ } else if (!key) {
+ index = store.index('by_peer');
+ } else {
+ index = store.index('by_all');
+ }
+ index.openCursor(IDBKeyRange.only(key_range)).onsuccess = function(e) {
+ var cursor = e.target.result;
+ if (cursor) {
+ var stack = Runtime.stackSave();
+ var record = Runtime.stackAlloc(6 * 4);
+ var sub_system = allocate(intArrayFromString(cursor.value.sub_system),
+ 'i8', ALLOC_STACK);
+ var peer = allocate(cursor.value.peer, 'i8', ALLOC_STACK);
+ var key = allocate(intArrayFromString(cursor.value.key), 'i8',
+ ALLOC_STACK);
+ var value = allocate(cursor.value.value, 'i8', ALLOC_STACK);
+ var expiry = Runtime.stackAlloc(8);
+ setValue(expiry, cursor.value.expiry, 'i64');
+ setValue(record, sub_system, 'i32');
+ setValue(record + 4, peer, 'i32');
+ setValue(record + 8, key, 'i32');
+ setValue(record + 12, value, 'i32');
+ setValue(record + 16, cursor.value.value.length, 'i32');
+ setValue(record + 20, expiry, 'i32');
+ Runtime.dynCall('viii', iter, [iter_cls, record, 0]);
+ Runtime.stackRestore(stack);
+ cursor.continue();
+ }
+ };
+ }, sub_system, peer, key, iter, iter_cls);
return GNUNET_OK;
}
@@ -190,7 +176,44 @@ peerstore_emscripten_store_record(void *cls,
struct GNUNET_TIME_Absolute expiry,
enum GNUNET_PEERSTORE_StoreOption options)
{
- struct Plugin *plugin = cls;
+ EM_ASM_ARGS({
+ var sub_system = Pointer_stringify($0);
+ var peer = Array.apply([], HEAP8.subarray($1, $1 + 32));
+ var key = Pointer_stringify($2);
+ var value = new Uint8Array(HEAP8.subarray($3, $3 + $4));
+ var expiry = $5;
+ var options = $6;
+ var store =
+ psdb.transaction(['peerstore'], 'readwrite').objectStore('peerstore');
+ var put = function() {
+ var request = store.put(
+ {sub_system: sub_system,
+ peer: peer,
+ key: key,
+ value: value,
+ expiry: expiry});
+ request.onerror = function(e) {
+ Module.print('put request failed');
+ };
+ };
+ if (options == 1) {
+ store.index('by_all').openKeyCursor(
+ IDBKeyRange.only([sub_system, peer, key])).onsuccess = function(e) {
+ var cursor = e.target.result;
+ if (cursor) {
+ var request = store.delete(cursor.value);
+ request.onerror = function(e) {
+ Module.print('replace request failed');
+ };
+ cursor.continue();
+ } else {
+ put();
+ }
+ }
+ } else {
+ put();
+ }
+ }, sub_system, peer, key, value, size, (double)expiry.abs_value_us, options);
return GNUNET_OK;
}
@@ -206,6 +229,24 @@ peerstore_emscripten_store_record(void *cls,
static int
database_setup (struct Plugin *plugin)
{
+ EM_ASM({
+ var request = indexedDB.open('peerstore', 1);
+ request.onsuccess = function(e) {
+ psdb = e.target.result;
+ };
+ request.onerror = function(e) {
+ Module.print('Error opening peerstore database');
+ };
+ request.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ var store = db.createObjectStore('peerstore', {autoIncrement: true});
+ store.createIndex('by_subsystem', 'sub_system');
+ store.createIndex('by_pid', ['sub_system', 'peer_id']);
+ store.createIndex('by_key', ['sub_system', 'key']);
+ store.createIndex('by_all', ['sub_system', 'peer_id', 'key']);
+ store.createIndex('by_expiry', 'expiry');
+ };
+ });
return GNUNET_OK;
}
@@ -270,4 +311,4 @@ libgnunet_plugin_peerstore_emscripten_done (void *cls)
}
-/* end of plugin_peerstore_emscripten.c */
+/* vim: set expandtab ts=2 sw=2: */
diff --git a/src/js/configuration.js b/src/js/configuration.js
index 877edc0..20cc50b 100644
--- a/src/js/configuration.js
+++ b/src/js/configuration.js
@@ -78,6 +78,9 @@ mergeInto(LibraryManager.library, {
peerinfo: {
HOSTS: '/peerinfo/hosts',
},
+ peerstore: {
+ DATABASE: 'emscripten',
+ },
},
GNUNET_CONFIGURATION_get_value__deps: ['$CONFIG'],
GNUNET_CONFIGURATION_get_value: function(section, option) {
diff --git a/src/js/pre.js b/src/js/pre.js
index dd2c4a5..3b30669 100644
--- a/src/js/pre.js
+++ b/src/js/pre.js
@@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-var xhrs = [];
+var xhrs = []; // plugin_transport_http_client
+var psdb; // plugin_peerstore_emscripten
var WorkerMessageQueue = [];
function flush_worker_message_queue(f) {
@@ -34,6 +35,7 @@ gnunet_prerun = function() {
'block_fs',
'datacache_heap',
'datastore_heap',
+ 'peerstore_emscripten',
'transport_http_client',
].forEach(function(plugin) {
FS.createPreloadedFile('/', 'libgnunet_plugin_' + plugin + '.js',