libdom: branch master updated. release/0.0.1-27-g2c5052d
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/libdom.git/shortlog/2c5052d450577d5c26b902...
...commit http://git.netsurf-browser.org/libdom.git/commit/2c5052d450577d5c26b902ae...
...tree http://git.netsurf-browser.org/libdom.git/tree/2c5052d450577d5c26b902ae5f...
The branch, master has been updated
via 2c5052d450577d5c26b902ae5f4402b87f76e406 (commit)
via dc6bcfdcc5058940a0ffc919587f1cce5c63ec2f (commit)
from ec446872606a65cf59e6bbbded464110353d9c59 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/libdom.git/commit/?id=2c5052d450577d5c26b9...
commit 2c5052d450577d5c26b902ae5f4402b87f76e406
Merge: ec44687 dc6bcfd
Author: Daniel Silverstone <dsilvers(a)digital-scurf.org>
Commit: Daniel Silverstone <dsilvers(a)digital-scurf.org>
Merge remote-tracking branch 'parwana/hrtag3'
This adds the HTMLHRElement (dom_html_hr_element).
Reviewed-By: Daniel Silverstone <dsilvers(a)netsurf-browser.org>
commitdiff http://git.netsurf-browser.org/libdom.git/commit/?id=dc6bcfdcc5058940a0ff...
commit dc6bcfdcc5058940a0ffc919587f1cce5c63ec2f
Author: rsk1994 <rsk1coder99(a)gmail.com>
Commit: rsk1994 <rsk1coder99(a)gmail.com>
final patch for adding hr tag to libdom
diff --git a/Makefile b/Makefile
index 7c50cad..3aac0c3 100644
--- a/Makefile
+++ b/Makefile
@@ -96,6 +96,7 @@ INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_text_area_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_option_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_opt_group_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_options_collection.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_hr_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) /$(LIBDIR)/pkgconfig:lib$(COMPONENT).pc.in
INSTALL_ITEMS := $(INSTALL_ITEMS) /$(LIBDIR):$(OUTPUT)
diff --git a/include/dom/dom.h b/include/dom/dom.h
index 2ef6e9b..d34f27f 100644
--- a/include/dom/dom.h
+++ b/include/dom/dom.h
@@ -55,6 +55,7 @@
#include <dom/html/html_option_element.h>
#include <dom/html/html_select_element.h>
#include <dom/html/html_options_collection.h>
+#include <dom/html/html_hr_element.h>
/* DOM Events header */
#include <dom/events/events.h>
diff --git a/include/dom/html/html_hr_element.h b/include/dom/html/html_hr_element.h
index 2e182d5..14f09f6 100644
--- a/include/dom/html/html_hr_element.h
+++ b/include/dom/html/html_hr_element.h
@@ -3,5 +3,39 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2009 Bo Yang <struggleyb.nku(a)gmail.com>
+ * Copyright 2014 Rupinder Singh Khokhar <rsk1coder99(a)gmail.com>
*/
+#ifndef dom_html_hr_element_h_
+#define dom_html_hr_element_h_
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+#include <dom/core/string.h>
+
+typedef struct dom_html_hr_element dom_html_hr_element;
+
+dom_exception dom_html_hr_element_get_no_shade(
+ dom_html_hr_element *ele, bool *no_shade);
+
+dom_exception dom_html_hr_element_set_no_shade(
+ dom_html_hr_element *ele, bool no_shade);
+
+dom_exception dom_html_hr_element_get_align(
+ dom_html_hr_element *element, dom_string **align);
+
+dom_exception dom_html_hr_element_set_align(
+ dom_html_hr_element *element, dom_string *align);
+
+dom_exception dom_html_hr_element_get_size(
+ dom_html_hr_element *element, dom_string **size);
+
+dom_exception dom_html_hr_element_set_size(
+ dom_html_hr_element *ele, dom_string *size);
+
+dom_exception dom_html_hr_element_get_width(
+ dom_html_hr_element *ele, dom_string **width);
+
+dom_exception dom_html_hr_element_set_width(
+ dom_html_hr_element *ele, dom_string *width);
+
+#endif
diff --git a/src/html/Makefile b/src/html/Makefile
index 4e1b4c4..5226b53 100644
--- a/src/html/Makefile
+++ b/src/html/Makefile
@@ -6,7 +6,7 @@ DIR_SOURCES := \
html_base_element.c html_isindex_element.c html_style_element.c \
html_body_element.c html_form_element.c html_select_element.c \
html_button_element.c html_input_element.c html_text_area_element.c \
- html_opt_group_element.c html_option_element.c
+ html_opt_group_element.c html_option_element.c html_hr_element.c
UNINMPLEMENTED_SOURCES := \
html_label_element.c html_fieldset_element.c \
@@ -15,7 +15,7 @@ UNINMPLEMENTED_SOURCES := \
html_li_element.c html_div_element.c html_paragraph_element.c \
html_heading_element.c html_quote_element.c html_pre_element.c \
html_br_element.c html_basefont_element.c html_font_element.c \
- html_hr_element.c html_mod_element.c html_anchor_element.c \
+ html_mod_element.c html_anchor_element.c \
html_image_element.c html_object_element.c html_param_element.c \
html_applet_element.c html_map_element.c html_area_element.c \
html_script_element.c html_table_element.c html_tablecaption_element.c \
diff --git a/src/html/TODO b/src/html/TODO
index 8ff489d..37ade2c 100644
--- a/src/html/TODO
+++ b/src/html/TODO
@@ -36,7 +36,7 @@ HTMLPreElement html_pre_element MISSING
HTMLBRElement html_br_element MISSING
HTMLBaseFontElement html_basefont_element MISSING
HTMLFontElement html_font_element MISSING
-HTMLHRElement html_hr_element MISSING
+HTMLHRElement html_hr_element DONE
HTMLModElement html_mod_element MISSING
HTMLAnchorElement html_anchor_element MISSING
HTMLImageElement html_image_element MISSING
diff --git a/src/html/html_document.c b/src/html/html_document.c
index fb880cf..0da16bb 100644
--- a/src/html/html_document.c
+++ b/src/html/html_document.c
@@ -24,6 +24,7 @@
#include "html/html_opt_group_element.h"
#include "html/html_option_element.h"
#include "html/html_select_element.h"
+#include "html/html_hr_element.h"
#include "core/attr.h"
#include "core/string.h"
@@ -220,6 +221,9 @@ _dom_html_document_create_element_internal(dom_html_document *html,
} else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_SELECT])) {
exc = _dom_html_select_element_create(html, namespace, prefix,
(dom_html_select_element **) result);
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_HR])) {
+ exc = _dom_html_hr_element_create(html, namespace, prefix,
+ (dom_html_hr_element **) result);
} else {
exc = _dom_html_element_create(html, tag_name, namespace,
prefix, result);
diff --git a/src/html/html_document_strings.h b/src/html/html_document_strings.h
index f2d6fa2..8e9d79e 100644
--- a/src/html/html_document_strings.h
+++ b/src/html/html_document_strings.h
@@ -80,6 +80,7 @@ HTML_DOCUMENT_STRINGS_ACTION(max_length,maxlength)
HTML_DOCUMENT_STRINGS_ACTION(read_only,readonly)
HTML_DOCUMENT_STRINGS_ACTION1(size)
HTML_DOCUMENT_STRINGS_ACTION1(src)
+HTML_DOCUMENT_STRINGS_ACTION1(width)
HTML_DOCUMENT_STRINGS_ACTION(tab_index,tabindex)
/* HTML_DOCUMENT_STRINGS_ACTION1(type) */
HTML_DOCUMENT_STRINGS_ACTION(use_map,usemap)
diff --git a/src/html/html_hr_element.c b/src/html/html_hr_element.c
index 2e182d5..eb8aa68 100644
--- a/src/html/html_hr_element.c
+++ b/src/html/html_hr_element.c
@@ -3,5 +3,189 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2009 Bo Yang <struggleyb.nku(a)gmail.com>
+ * Copyright 2014 Rupinder Singh Khokhar<rsk1coder99(a)gmail.com>
*/
+#include <assert.h>
+#include <stdlib.h>
+
+#include <dom/html/html_hr_element.h>
+
+#include "html/html_document.h"
+#include "html/html_hr_element.h"
+
+#include "core/node.h"
+#include "core/attr.h"
+#include "utils/utils.h"
+
+static struct dom_element_protected_vtable _protect_vtable = {
+ {
+ DOM_NODE_PROTECT_VTABLE_HTML_HR_ELEMENT
+ },
+ DOM_HTML_HR_ELEMENT_PROTECT_VTABLE
+};
+
+/**
+ * Create a dom_html_hr_element object
+ *
+ * \param doc The document object
+ * \param ele The returned element object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_html_hr_element_create(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element **ele)
+{
+ struct dom_node_internal *node;
+
+ *ele = malloc(sizeof(dom_html_hr_element));
+ if (*ele == NULL)
+ return DOM_NO_MEM_ERR;
+
+ /* Set up vtables */
+ node = (struct dom_node_internal *) *ele;
+ node->base.vtable = &_dom_html_element_vtable;
+ node->vtable = &_protect_vtable;
+
+ return _dom_html_hr_element_initialise(doc, namespace, prefix, *ele);
+}
+
+/**
+ * Initialise a dom_html_hr_element object
+ *
+ * \param doc The document object
+ * \param ele The dom_html_hr_element object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_html_hr_element_initialise(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element *ele)
+{
+ return _dom_html_element_initialise(doc, &ele->base,
+ doc->memoised[hds_HR],
+ namespace, prefix);
+}
+
+/**
+ * Finalise a dom_html_hr_element object
+ *
+ * \param ele The dom_html_hr_element object
+ */
+void _dom_html_hr_element_finalise(struct dom_html_hr_element *ele)
+{
+ _dom_html_element_finalise(&ele->base);
+}
+
+/**
+ * Destroy a dom_html_hr_element object
+ *
+ * \param ele The dom_html_hr_element object
+ */
+void _dom_html_hr_element_destroy(struct dom_html_hr_element *ele)
+{
+ _dom_html_hr_element_finalise(ele);
+ free(ele);
+}
+
+/**
+ * Get the no_shade property
+ *
+ * \param ele The dom_html_hr_element object
+ * \param no_shade The status
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception dom_html_hr_element_get_no_shade(dom_html_hr_element *ele,
+ bool *no_shade)
+{
+ return dom_html_element_get_bool_property(&ele->base, "noshade",
+ SLEN("noshade"), no_shade);
+}
+
+/**
+ * Set the no_shade property
+ *
+ * \param ele The dom_html_hr_element object
+ * \param no_shade The status
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception dom_html_hr_element_set_no_shade(dom_html_hr_element *ele,
+ bool no_shade)
+{
+ return dom_html_element_set_bool_property(&ele->base, "noshade",
+ SLEN("noshade"), no_shade);
+}
+
+/*------------------------------------------------------------------------*/
+/* The protected virtual functions */
+
+/* The virtual function used to parse attribute value, see src/core/element.c
+ * for detail */
+dom_exception _dom_html_hr_element_parse_attribute(dom_element *ele,
+ dom_string *name, dom_string *value,
+ dom_string **parsed)
+{
+ UNUSED(ele);
+ UNUSED(name);
+
+ dom_string_ref(value);
+ *parsed = value;
+
+ return DOM_NO_ERR;
+}
+
+/* The virtual destroy function, see src/core/node.c for detail */
+void _dom_virtual_html_hr_element_destroy(dom_node_internal *node)
+{
+ _dom_html_hr_element_destroy((struct dom_html_hr_element *) node);
+}
+
+/* The virtual copy function, see src/core/node.c for detail */
+dom_exception _dom_html_hr_element_copy(dom_node_internal *old,
+ dom_node_internal **copy)
+{
+ return _dom_html_element_copy(old, copy);
+}
+
+/*-----------------------------------------------------------------------*/
+/* API functions */
+
+#define SIMPLE_GET(attr) \
+ dom_exception dom_html_hr_element_get_##attr( \
+ dom_html_hr_element *element, \
+ dom_string **attr) \
+ { \
+ dom_exception ret; \
+ dom_string *_memo_##attr; \
+ \
+ _memo_##attr = \
+ ((struct dom_html_document *) \
+ ((struct dom_node_internal *)element)->owner)->\
+ memoised[hds_##attr]; \
+ \
+ ret = dom_element_get_attribute(element, _memo_##attr, attr); \
+ \
+ return ret; \
+ }
+#define SIMPLE_SET(attr) \
+dom_exception dom_html_hr_element_set_##attr( \
+ dom_html_hr_element *element, \
+ dom_string *attr) \
+ { \
+ dom_exception ret; \
+ dom_string *_memo_##attr; \
+ \
+ _memo_##attr = \
+ ((struct dom_html_document *) \
+ ((struct dom_node_internal *)element)->owner)->\
+ memoised[hds_##attr]; \
+ \
+ ret = dom_element_set_attribute(element, _memo_##attr, attr); \
+ \
+ return ret; \
+ }
+
+#define SIMPLE_GET_SET(attr) SIMPLE_GET(attr) SIMPLE_SET(attr)
+
+SIMPLE_GET_SET(size);
+SIMPLE_GET_SET(align);
+SIMPLE_GET_SET(width);
diff --git a/src/html/html_hr_element.h b/src/html/html_hr_element.h
index 2e182d5..c3cf717 100644
--- a/src/html/html_hr_element.h
+++ b/src/html/html_hr_element.h
@@ -3,5 +3,50 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2009 Bo Yang <struggleyb.nku(a)gmail.com>
+ * Copyright 2014 Rupinder Singh Khokhar <rsk1coder99(a)gmail.com>
*/
+#ifndef dom_internal_html_hr_element_h_
+#define dom_internal_html_hr_element_h_
+
+#include <dom/html/html_hr_element.h>
+#include "html/html_element.h"
+
+
+struct dom_html_hr_element {
+ struct dom_html_element base;
+ /**< The base class */
+};
+
+/* Create a dom_html_hr_element object */
+dom_exception _dom_html_hr_element_create(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element **ele);
+
+/* Initialise a dom_html_hr_element object */
+dom_exception _dom_html_hr_element_initialise(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element *ele);
+
+/* Finalise a dom_html_hr_element object */
+void _dom_html_hr_element_finalise(struct dom_html_hr_element *ele);
+
+/* Destroy a dom_html_hr_element object */
+void _dom_html_hr_element_destroy(struct dom_html_hr_element *ele);
+
+/* The protected virtual functions */
+dom_exception _dom_html_hr_element_parse_attribute(dom_element *ele,
+ dom_string *name, dom_string *value,
+ dom_string **parsed);
+void _dom_virtual_html_hr_element_destroy(dom_node_internal *node);
+dom_exception _dom_html_hr_element_copy(dom_node_internal *old,
+ dom_node_internal **copy);
+
+#define DOM_HTML_HR_ELEMENT_PROTECT_VTABLE \
+ _dom_html_hr_element_parse_attribute
+
+#define DOM_NODE_PROTECT_VTABLE_HTML_HR_ELEMENT \
+ _dom_virtual_html_hr_element_destroy, \
+ _dom_html_hr_element_copy
+
+#endif
diff --git a/test/DOMTSHandler.pm b/test/DOMTSHandler.pm
index 22fb418..df2b028 100644
--- a/test/DOMTSHandler.pm
+++ b/test/DOMTSHandler.pm
@@ -52,6 +52,7 @@ our %special_prefix = (
HTMLFormElement => "dom_html_form_element",
CharacterData => "dom_characterdata",
CDATASection => "dom_cdata_section *",
+ HTMLHRElement => "dom_html_hr_element",
);
our %unref_prefix = (
diff --git a/test/testcases/tests/level1/html/HTMLHRElement01.xml b/test/testcases/tests/level1/html/HTMLHRElement01.xml
new file mode 100644
index 0000000..c074605
--- /dev/null
+++ b/test/testcases/tests/level1/html/HTMLHRElement01.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
+
+<!--
+
+Copyright (c) 2001 World Wide Web Consortium,
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University). All
+Rights Reserved. This program is distributed under the W3C's Software
+Intellectual Property License. This program is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+-->
+<!DOCTYPE test SYSTEM "dom1.dtd">
+<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement01">
+<metadata>
+<title>HTMLHRElement01</title>
+<creator>NIST</creator>
+<description>
+ The align attribute specifies the rule alignment on the page.
+
+ Retrieve the align attribute and examine its value.
+</description>
+<contributor>Mary Brady</contributor>
+<date qualifier="created">2002-02-22</date>
+<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-1523..."/>
+</metadata>
+<var name="nodeList" type="NodeList"/>
+<var name="testNode" type="Node"/>
+<var name="valign" type="DOMString" />
+<var name="doc" type="Document"/>
+<load var="doc" href="hr" willBeModified="false"/>
+<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
+<assertSize collection="nodeList" size="1" id="Asize"/>
+<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
+<align interface="HTMLHRElement" obj="testNode" var="valign"/>
+<assertEquals actual="valign" expected='"center"' id="alignLink" ignoreCase="false"/>
+</test>
diff --git a/test/testcases/tests/level1/html/HTMLHRElement01.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement01.xml.kfail
deleted file mode 100644
index c074605..0000000
--- a/test/testcases/tests/level1/html/HTMLHRElement01.xml.kfail
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
-
-<!--
-
-Copyright (c) 2001 World Wide Web Consortium,
-(Massachusetts Institute of Technology, Institut National de
-Recherche en Informatique et en Automatique, Keio University). All
-Rights Reserved. This program is distributed under the W3C's Software
-Intellectual Property License. This program is distributed in the
-hope that it will be useful, but WITHOUT ANY WARRANTY; without even
-the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-PURPOSE.
-
-See W3C License http://www.w3.org/Consortium/Legal/ for more details.
-
--->
-<!DOCTYPE test SYSTEM "dom1.dtd">
-<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement01">
-<metadata>
-<title>HTMLHRElement01</title>
-<creator>NIST</creator>
-<description>
- The align attribute specifies the rule alignment on the page.
-
- Retrieve the align attribute and examine its value.
-</description>
-<contributor>Mary Brady</contributor>
-<date qualifier="created">2002-02-22</date>
-<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-1523..."/>
-</metadata>
-<var name="nodeList" type="NodeList"/>
-<var name="testNode" type="Node"/>
-<var name="valign" type="DOMString" />
-<var name="doc" type="Document"/>
-<load var="doc" href="hr" willBeModified="false"/>
-<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
-<assertSize collection="nodeList" size="1" id="Asize"/>
-<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
-<align interface="HTMLHRElement" obj="testNode" var="valign"/>
-<assertEquals actual="valign" expected='"center"' id="alignLink" ignoreCase="false"/>
-</test>
diff --git a/test/testcases/tests/level1/html/HTMLHRElement02.xml b/test/testcases/tests/level1/html/HTMLHRElement02.xml
new file mode 100644
index 0000000..37f1293
--- /dev/null
+++ b/test/testcases/tests/level1/html/HTMLHRElement02.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
+
+<!--
+
+Copyright (c) 2001 World Wide Web Consortium,
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University). All
+Rights Reserved. This program is distributed under the W3C's Software
+Intellectual Property License. This program is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+-->
+<!DOCTYPE test SYSTEM "dom1.dtd">
+<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement02">
+<metadata>
+<title>HTMLHRElement02</title>
+<creator>NIST</creator>
+<description>
+ The noShade attribute specifies that the rule should be drawn as
+ a solid color.
+
+ Retrieve the noShade attribute and examine its value.
+</description>
+<contributor>Mary Brady</contributor>
+<date qualifier="created">2002-02-22</date>
+<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-7981..."/>
+</metadata>
+<var name="nodeList" type="NodeList"/>
+<var name="testNode" type="Node"/>
+<var name="vnoshade" type="boolean" />
+<var name="doc" type="Document"/>
+<load var="doc" href="hr" willBeModified="false"/>
+<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
+<assertSize collection="nodeList" size="1" id="Asize"/>
+<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
+<noShade interface="HTMLHRElement" obj="testNode" var="vnoshade"/>
+<assertTrue actual="vnoshade" id="noShadeLink"/>
+</test>
diff --git a/test/testcases/tests/level1/html/HTMLHRElement02.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement02.xml.kfail
deleted file mode 100644
index 37f1293..0000000
--- a/test/testcases/tests/level1/html/HTMLHRElement02.xml.kfail
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
-
-<!--
-
-Copyright (c) 2001 World Wide Web Consortium,
-(Massachusetts Institute of Technology, Institut National de
-Recherche en Informatique et en Automatique, Keio University). All
-Rights Reserved. This program is distributed under the W3C's Software
-Intellectual Property License. This program is distributed in the
-hope that it will be useful, but WITHOUT ANY WARRANTY; without even
-the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-PURPOSE.
-
-See W3C License http://www.w3.org/Consortium/Legal/ for more details.
-
--->
-<!DOCTYPE test SYSTEM "dom1.dtd">
-<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement02">
-<metadata>
-<title>HTMLHRElement02</title>
-<creator>NIST</creator>
-<description>
- The noShade attribute specifies that the rule should be drawn as
- a solid color.
-
- Retrieve the noShade attribute and examine its value.
-</description>
-<contributor>Mary Brady</contributor>
-<date qualifier="created">2002-02-22</date>
-<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-7981..."/>
-</metadata>
-<var name="nodeList" type="NodeList"/>
-<var name="testNode" type="Node"/>
-<var name="vnoshade" type="boolean" />
-<var name="doc" type="Document"/>
-<load var="doc" href="hr" willBeModified="false"/>
-<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
-<assertSize collection="nodeList" size="1" id="Asize"/>
-<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
-<noShade interface="HTMLHRElement" obj="testNode" var="vnoshade"/>
-<assertTrue actual="vnoshade" id="noShadeLink"/>
-</test>
diff --git a/test/testcases/tests/level1/html/HTMLHRElement03.xml b/test/testcases/tests/level1/html/HTMLHRElement03.xml
new file mode 100644
index 0000000..03ddebc
--- /dev/null
+++ b/test/testcases/tests/level1/html/HTMLHRElement03.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
+
+<!--
+
+Copyright (c) 2001 World Wide Web Consortium,
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University). All
+Rights Reserved. This program is distributed under the W3C's Software
+Intellectual Property License. This program is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+-->
+<!DOCTYPE test SYSTEM "dom1.dtd">
+<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement03">
+<metadata>
+<title>HTMLHRElement03</title>
+<creator>NIST</creator>
+<description>
+ The size attribute specifies the height of the rule.
+
+ Retrieve the size attribute and examine its value.
+</description>
+<contributor>Mary Brady</contributor>
+<date qualifier="created">2002-02-22</date>
+<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-7761..."/>
+</metadata>
+<var name="nodeList" type="NodeList"/>
+<var name="testNode" type="Node"/>
+<var name="vsize" type="DOMString" />
+<var name="doc" type="Document"/>
+<load var="doc" href="hr" willBeModified="false"/>
+<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
+<assertSize collection="nodeList" size="1" id="Asize"/>
+<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
+<size interface="HTMLHRElement" obj="testNode" var="vsize"/>
+<assertEquals actual="vsize" expected='"5"' id="sizeLink" ignoreCase="false"/>
+</test>
diff --git a/test/testcases/tests/level1/html/HTMLHRElement03.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement03.xml.kfail
deleted file mode 100644
index 03ddebc..0000000
--- a/test/testcases/tests/level1/html/HTMLHRElement03.xml.kfail
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
-
-<!--
-
-Copyright (c) 2001 World Wide Web Consortium,
-(Massachusetts Institute of Technology, Institut National de
-Recherche en Informatique et en Automatique, Keio University). All
-Rights Reserved. This program is distributed under the W3C's Software
-Intellectual Property License. This program is distributed in the
-hope that it will be useful, but WITHOUT ANY WARRANTY; without even
-the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-PURPOSE.
-
-See W3C License http://www.w3.org/Consortium/Legal/ for more details.
-
--->
-<!DOCTYPE test SYSTEM "dom1.dtd">
-<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement03">
-<metadata>
-<title>HTMLHRElement03</title>
-<creator>NIST</creator>
-<description>
- The size attribute specifies the height of the rule.
-
- Retrieve the size attribute and examine its value.
-</description>
-<contributor>Mary Brady</contributor>
-<date qualifier="created">2002-02-22</date>
-<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-7761..."/>
-</metadata>
-<var name="nodeList" type="NodeList"/>
-<var name="testNode" type="Node"/>
-<var name="vsize" type="DOMString" />
-<var name="doc" type="Document"/>
-<load var="doc" href="hr" willBeModified="false"/>
-<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
-<assertSize collection="nodeList" size="1" id="Asize"/>
-<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
-<size interface="HTMLHRElement" obj="testNode" var="vsize"/>
-<assertEquals actual="vsize" expected='"5"' id="sizeLink" ignoreCase="false"/>
-</test>
diff --git a/test/testcases/tests/level1/html/HTMLHRElement04.xml b/test/testcases/tests/level1/html/HTMLHRElement04.xml
new file mode 100644
index 0000000..2090d14
--- /dev/null
+++ b/test/testcases/tests/level1/html/HTMLHRElement04.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
+
+<!--
+
+Copyright (c) 2001 World Wide Web Consortium,
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University). All
+Rights Reserved. This program is distributed under the W3C's Software
+Intellectual Property License. This program is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+-->
+<!DOCTYPE test SYSTEM "dom1.dtd">
+<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement04">
+<metadata>
+<title>HTMLHRElement04</title>
+<creator>NIST</creator>
+<description>
+ The width attribute specifies the width of the rule.
+
+ Retrieve the width attribute and examine its value.
+</description>
+<contributor>Mary Brady</contributor>
+<date qualifier="created">2002-02-22</date>
+<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-8774..."/>
+</metadata>
+<var name="nodeList" type="NodeList"/>
+<var name="testNode" type="Node"/>
+<var name="vwidth" type="DOMString" />
+<var name="doc" type="Document"/>
+<load var="doc" href="hr" willBeModified="false"/>
+<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
+<assertSize collection="nodeList" size="1" id="Asize"/>
+<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
+<width interface="HTMLHRElement" obj="testNode" var="vwidth"/>
+<assertEquals actual="vwidth" expected='"400"' id="widthLink" ignoreCase="false"/>
+</test>
diff --git a/test/testcases/tests/level1/html/HTMLHRElement04.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement04.xml.kfail
deleted file mode 100644
index 2090d14..0000000
--- a/test/testcases/tests/level1/html/HTMLHRElement04.xml.kfail
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet href="test-to-html.xsl" type="text/xml"?>
-
-<!--
-
-Copyright (c) 2001 World Wide Web Consortium,
-(Massachusetts Institute of Technology, Institut National de
-Recherche en Informatique et en Automatique, Keio University). All
-Rights Reserved. This program is distributed under the W3C's Software
-Intellectual Property License. This program is distributed in the
-hope that it will be useful, but WITHOUT ANY WARRANTY; without even
-the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-PURPOSE.
-
-See W3C License http://www.w3.org/Consortium/Legal/ for more details.
-
--->
-<!DOCTYPE test SYSTEM "dom1.dtd">
-<test xmlns="http://www.w3.org/2001/DOM-Test-Suite/Level-1" name="HTMLHRElement04">
-<metadata>
-<title>HTMLHRElement04</title>
-<creator>NIST</creator>
-<description>
- The width attribute specifies the width of the rule.
-
- Retrieve the width attribute and examine its value.
-</description>
-<contributor>Mary Brady</contributor>
-<date qualifier="created">2002-02-22</date>
-<subject resource="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html#ID-8774..."/>
-</metadata>
-<var name="nodeList" type="NodeList"/>
-<var name="testNode" type="Node"/>
-<var name="vwidth" type="DOMString" />
-<var name="doc" type="Document"/>
-<load var="doc" href="hr" willBeModified="false"/>
-<getElementsByTagName interface="Document" obj="doc" var="nodeList" tagname='"hr"'/>
-<assertSize collection="nodeList" size="1" id="Asize"/>
-<item interface="NodeList" obj="nodeList" var="testNode" index="0"/>
-<width interface="HTMLHRElement" obj="testNode" var="vwidth"/>
-<assertEquals actual="vwidth" expected='"400"' id="widthLink" ignoreCase="false"/>
-</test>
-----------------------------------------------------------------------
Summary of changes:
Makefile | 1 +
include/dom/dom.h | 1 +
include/dom/html/html_hr_element.h | 34 ++++
src/html/Makefile | 4 +-
src/html/TODO | 2 +-
src/html/html_document.c | 4 +
src/html/html_document_strings.h | 1 +
src/html/html_hr_element.c | 184 ++++++++++++++++++++
src/html/html_hr_element.h | 45 +++++
test/DOMTSHandler.pm | 1 +
...MLHRElement01.xml.kfail => HTMLHRElement01.xml} | 0
...MLHRElement02.xml.kfail => HTMLHRElement02.xml} | 0
...MLHRElement03.xml.kfail => HTMLHRElement03.xml} | 0
...MLHRElement04.xml.kfail => HTMLHRElement04.xml} | 0
14 files changed, 274 insertions(+), 3 deletions(-)
rename test/testcases/tests/level1/html/{HTMLHRElement01.xml.kfail => HTMLHRElement01.xml} (100%)
rename test/testcases/tests/level1/html/{HTMLHRElement02.xml.kfail => HTMLHRElement02.xml} (100%)
rename test/testcases/tests/level1/html/{HTMLHRElement03.xml.kfail => HTMLHRElement03.xml} (100%)
rename test/testcases/tests/level1/html/{HTMLHRElement04.xml.kfail => HTMLHRElement04.xml} (100%)
diff --git a/Makefile b/Makefile
index 7c50cad..3aac0c3 100644
--- a/Makefile
+++ b/Makefile
@@ -96,6 +96,7 @@ INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_text_area_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_option_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_opt_group_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_options_collection.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/html_hr_element.h
INSTALL_ITEMS := $(INSTALL_ITEMS) /$(LIBDIR)/pkgconfig:lib$(COMPONENT).pc.in
INSTALL_ITEMS := $(INSTALL_ITEMS) /$(LIBDIR):$(OUTPUT)
diff --git a/include/dom/dom.h b/include/dom/dom.h
index 2ef6e9b..d34f27f 100644
--- a/include/dom/dom.h
+++ b/include/dom/dom.h
@@ -55,6 +55,7 @@
#include <dom/html/html_option_element.h>
#include <dom/html/html_select_element.h>
#include <dom/html/html_options_collection.h>
+#include <dom/html/html_hr_element.h>
/* DOM Events header */
#include <dom/events/events.h>
diff --git a/include/dom/html/html_hr_element.h b/include/dom/html/html_hr_element.h
index 2e182d5..14f09f6 100644
--- a/include/dom/html/html_hr_element.h
+++ b/include/dom/html/html_hr_element.h
@@ -3,5 +3,39 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2009 Bo Yang <struggleyb.nku(a)gmail.com>
+ * Copyright 2014 Rupinder Singh Khokhar <rsk1coder99(a)gmail.com>
*/
+#ifndef dom_html_hr_element_h_
+#define dom_html_hr_element_h_
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+#include <dom/core/string.h>
+
+typedef struct dom_html_hr_element dom_html_hr_element;
+
+dom_exception dom_html_hr_element_get_no_shade(
+ dom_html_hr_element *ele, bool *no_shade);
+
+dom_exception dom_html_hr_element_set_no_shade(
+ dom_html_hr_element *ele, bool no_shade);
+
+dom_exception dom_html_hr_element_get_align(
+ dom_html_hr_element *element, dom_string **align);
+
+dom_exception dom_html_hr_element_set_align(
+ dom_html_hr_element *element, dom_string *align);
+
+dom_exception dom_html_hr_element_get_size(
+ dom_html_hr_element *element, dom_string **size);
+
+dom_exception dom_html_hr_element_set_size(
+ dom_html_hr_element *ele, dom_string *size);
+
+dom_exception dom_html_hr_element_get_width(
+ dom_html_hr_element *ele, dom_string **width);
+
+dom_exception dom_html_hr_element_set_width(
+ dom_html_hr_element *ele, dom_string *width);
+
+#endif
diff --git a/src/html/Makefile b/src/html/Makefile
index 4e1b4c4..5226b53 100644
--- a/src/html/Makefile
+++ b/src/html/Makefile
@@ -6,7 +6,7 @@ DIR_SOURCES := \
html_base_element.c html_isindex_element.c html_style_element.c \
html_body_element.c html_form_element.c html_select_element.c \
html_button_element.c html_input_element.c html_text_area_element.c \
- html_opt_group_element.c html_option_element.c
+ html_opt_group_element.c html_option_element.c html_hr_element.c
UNINMPLEMENTED_SOURCES := \
html_label_element.c html_fieldset_element.c \
@@ -15,7 +15,7 @@ UNINMPLEMENTED_SOURCES := \
html_li_element.c html_div_element.c html_paragraph_element.c \
html_heading_element.c html_quote_element.c html_pre_element.c \
html_br_element.c html_basefont_element.c html_font_element.c \
- html_hr_element.c html_mod_element.c html_anchor_element.c \
+ html_mod_element.c html_anchor_element.c \
html_image_element.c html_object_element.c html_param_element.c \
html_applet_element.c html_map_element.c html_area_element.c \
html_script_element.c html_table_element.c html_tablecaption_element.c \
diff --git a/src/html/TODO b/src/html/TODO
index 8ff489d..37ade2c 100644
--- a/src/html/TODO
+++ b/src/html/TODO
@@ -36,7 +36,7 @@ HTMLPreElement html_pre_element MISSING
HTMLBRElement html_br_element MISSING
HTMLBaseFontElement html_basefont_element MISSING
HTMLFontElement html_font_element MISSING
-HTMLHRElement html_hr_element MISSING
+HTMLHRElement html_hr_element DONE
HTMLModElement html_mod_element MISSING
HTMLAnchorElement html_anchor_element MISSING
HTMLImageElement html_image_element MISSING
diff --git a/src/html/html_document.c b/src/html/html_document.c
index fb880cf..0da16bb 100644
--- a/src/html/html_document.c
+++ b/src/html/html_document.c
@@ -24,6 +24,7 @@
#include "html/html_opt_group_element.h"
#include "html/html_option_element.h"
#include "html/html_select_element.h"
+#include "html/html_hr_element.h"
#include "core/attr.h"
#include "core/string.h"
@@ -220,6 +221,9 @@ _dom_html_document_create_element_internal(dom_html_document *html,
} else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_SELECT])) {
exc = _dom_html_select_element_create(html, namespace, prefix,
(dom_html_select_element **) result);
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_HR])) {
+ exc = _dom_html_hr_element_create(html, namespace, prefix,
+ (dom_html_hr_element **) result);
} else {
exc = _dom_html_element_create(html, tag_name, namespace,
prefix, result);
diff --git a/src/html/html_document_strings.h b/src/html/html_document_strings.h
index f2d6fa2..8e9d79e 100644
--- a/src/html/html_document_strings.h
+++ b/src/html/html_document_strings.h
@@ -80,6 +80,7 @@ HTML_DOCUMENT_STRINGS_ACTION(max_length,maxlength)
HTML_DOCUMENT_STRINGS_ACTION(read_only,readonly)
HTML_DOCUMENT_STRINGS_ACTION1(size)
HTML_DOCUMENT_STRINGS_ACTION1(src)
+HTML_DOCUMENT_STRINGS_ACTION1(width)
HTML_DOCUMENT_STRINGS_ACTION(tab_index,tabindex)
/* HTML_DOCUMENT_STRINGS_ACTION1(type) */
HTML_DOCUMENT_STRINGS_ACTION(use_map,usemap)
diff --git a/src/html/html_hr_element.c b/src/html/html_hr_element.c
index 2e182d5..eb8aa68 100644
--- a/src/html/html_hr_element.c
+++ b/src/html/html_hr_element.c
@@ -3,5 +3,189 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2009 Bo Yang <struggleyb.nku(a)gmail.com>
+ * Copyright 2014 Rupinder Singh Khokhar<rsk1coder99(a)gmail.com>
*/
+#include <assert.h>
+#include <stdlib.h>
+
+#include <dom/html/html_hr_element.h>
+
+#include "html/html_document.h"
+#include "html/html_hr_element.h"
+
+#include "core/node.h"
+#include "core/attr.h"
+#include "utils/utils.h"
+
+static struct dom_element_protected_vtable _protect_vtable = {
+ {
+ DOM_NODE_PROTECT_VTABLE_HTML_HR_ELEMENT
+ },
+ DOM_HTML_HR_ELEMENT_PROTECT_VTABLE
+};
+
+/**
+ * Create a dom_html_hr_element object
+ *
+ * \param doc The document object
+ * \param ele The returned element object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_html_hr_element_create(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element **ele)
+{
+ struct dom_node_internal *node;
+
+ *ele = malloc(sizeof(dom_html_hr_element));
+ if (*ele == NULL)
+ return DOM_NO_MEM_ERR;
+
+ /* Set up vtables */
+ node = (struct dom_node_internal *) *ele;
+ node->base.vtable = &_dom_html_element_vtable;
+ node->vtable = &_protect_vtable;
+
+ return _dom_html_hr_element_initialise(doc, namespace, prefix, *ele);
+}
+
+/**
+ * Initialise a dom_html_hr_element object
+ *
+ * \param doc The document object
+ * \param ele The dom_html_hr_element object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_html_hr_element_initialise(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element *ele)
+{
+ return _dom_html_element_initialise(doc, &ele->base,
+ doc->memoised[hds_HR],
+ namespace, prefix);
+}
+
+/**
+ * Finalise a dom_html_hr_element object
+ *
+ * \param ele The dom_html_hr_element object
+ */
+void _dom_html_hr_element_finalise(struct dom_html_hr_element *ele)
+{
+ _dom_html_element_finalise(&ele->base);
+}
+
+/**
+ * Destroy a dom_html_hr_element object
+ *
+ * \param ele The dom_html_hr_element object
+ */
+void _dom_html_hr_element_destroy(struct dom_html_hr_element *ele)
+{
+ _dom_html_hr_element_finalise(ele);
+ free(ele);
+}
+
+/**
+ * Get the no_shade property
+ *
+ * \param ele The dom_html_hr_element object
+ * \param no_shade The status
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception dom_html_hr_element_get_no_shade(dom_html_hr_element *ele,
+ bool *no_shade)
+{
+ return dom_html_element_get_bool_property(&ele->base, "noshade",
+ SLEN("noshade"), no_shade);
+}
+
+/**
+ * Set the no_shade property
+ *
+ * \param ele The dom_html_hr_element object
+ * \param no_shade The status
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception dom_html_hr_element_set_no_shade(dom_html_hr_element *ele,
+ bool no_shade)
+{
+ return dom_html_element_set_bool_property(&ele->base, "noshade",
+ SLEN("noshade"), no_shade);
+}
+
+/*------------------------------------------------------------------------*/
+/* The protected virtual functions */
+
+/* The virtual function used to parse attribute value, see src/core/element.c
+ * for detail */
+dom_exception _dom_html_hr_element_parse_attribute(dom_element *ele,
+ dom_string *name, dom_string *value,
+ dom_string **parsed)
+{
+ UNUSED(ele);
+ UNUSED(name);
+
+ dom_string_ref(value);
+ *parsed = value;
+
+ return DOM_NO_ERR;
+}
+
+/* The virtual destroy function, see src/core/node.c for detail */
+void _dom_virtual_html_hr_element_destroy(dom_node_internal *node)
+{
+ _dom_html_hr_element_destroy((struct dom_html_hr_element *) node);
+}
+
+/* The virtual copy function, see src/core/node.c for detail */
+dom_exception _dom_html_hr_element_copy(dom_node_internal *old,
+ dom_node_internal **copy)
+{
+ return _dom_html_element_copy(old, copy);
+}
+
+/*-----------------------------------------------------------------------*/
+/* API functions */
+
+#define SIMPLE_GET(attr) \
+ dom_exception dom_html_hr_element_get_##attr( \
+ dom_html_hr_element *element, \
+ dom_string **attr) \
+ { \
+ dom_exception ret; \
+ dom_string *_memo_##attr; \
+ \
+ _memo_##attr = \
+ ((struct dom_html_document *) \
+ ((struct dom_node_internal *)element)->owner)->\
+ memoised[hds_##attr]; \
+ \
+ ret = dom_element_get_attribute(element, _memo_##attr, attr); \
+ \
+ return ret; \
+ }
+#define SIMPLE_SET(attr) \
+dom_exception dom_html_hr_element_set_##attr( \
+ dom_html_hr_element *element, \
+ dom_string *attr) \
+ { \
+ dom_exception ret; \
+ dom_string *_memo_##attr; \
+ \
+ _memo_##attr = \
+ ((struct dom_html_document *) \
+ ((struct dom_node_internal *)element)->owner)->\
+ memoised[hds_##attr]; \
+ \
+ ret = dom_element_set_attribute(element, _memo_##attr, attr); \
+ \
+ return ret; \
+ }
+
+#define SIMPLE_GET_SET(attr) SIMPLE_GET(attr) SIMPLE_SET(attr)
+
+SIMPLE_GET_SET(size);
+SIMPLE_GET_SET(align);
+SIMPLE_GET_SET(width);
diff --git a/src/html/html_hr_element.h b/src/html/html_hr_element.h
index 2e182d5..c3cf717 100644
--- a/src/html/html_hr_element.h
+++ b/src/html/html_hr_element.h
@@ -3,5 +3,50 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2009 Bo Yang <struggleyb.nku(a)gmail.com>
+ * Copyright 2014 Rupinder Singh Khokhar <rsk1coder99(a)gmail.com>
*/
+#ifndef dom_internal_html_hr_element_h_
+#define dom_internal_html_hr_element_h_
+
+#include <dom/html/html_hr_element.h>
+#include "html/html_element.h"
+
+
+struct dom_html_hr_element {
+ struct dom_html_element base;
+ /**< The base class */
+};
+
+/* Create a dom_html_hr_element object */
+dom_exception _dom_html_hr_element_create(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element **ele);
+
+/* Initialise a dom_html_hr_element object */
+dom_exception _dom_html_hr_element_initialise(struct dom_html_document *doc,
+ dom_string *namespace, dom_string *prefix,
+ struct dom_html_hr_element *ele);
+
+/* Finalise a dom_html_hr_element object */
+void _dom_html_hr_element_finalise(struct dom_html_hr_element *ele);
+
+/* Destroy a dom_html_hr_element object */
+void _dom_html_hr_element_destroy(struct dom_html_hr_element *ele);
+
+/* The protected virtual functions */
+dom_exception _dom_html_hr_element_parse_attribute(dom_element *ele,
+ dom_string *name, dom_string *value,
+ dom_string **parsed);
+void _dom_virtual_html_hr_element_destroy(dom_node_internal *node);
+dom_exception _dom_html_hr_element_copy(dom_node_internal *old,
+ dom_node_internal **copy);
+
+#define DOM_HTML_HR_ELEMENT_PROTECT_VTABLE \
+ _dom_html_hr_element_parse_attribute
+
+#define DOM_NODE_PROTECT_VTABLE_HTML_HR_ELEMENT \
+ _dom_virtual_html_hr_element_destroy, \
+ _dom_html_hr_element_copy
+
+#endif
diff --git a/test/DOMTSHandler.pm b/test/DOMTSHandler.pm
index 22fb418..df2b028 100644
--- a/test/DOMTSHandler.pm
+++ b/test/DOMTSHandler.pm
@@ -52,6 +52,7 @@ our %special_prefix = (
HTMLFormElement => "dom_html_form_element",
CharacterData => "dom_characterdata",
CDATASection => "dom_cdata_section *",
+ HTMLHRElement => "dom_html_hr_element",
);
our %unref_prefix = (
diff --git a/test/testcases/tests/level1/html/HTMLHRElement01.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement01.xml
similarity index 100%
rename from test/testcases/tests/level1/html/HTMLHRElement01.xml.kfail
rename to test/testcases/tests/level1/html/HTMLHRElement01.xml
diff --git a/test/testcases/tests/level1/html/HTMLHRElement02.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement02.xml
similarity index 100%
rename from test/testcases/tests/level1/html/HTMLHRElement02.xml.kfail
rename to test/testcases/tests/level1/html/HTMLHRElement02.xml
diff --git a/test/testcases/tests/level1/html/HTMLHRElement03.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement03.xml
similarity index 100%
rename from test/testcases/tests/level1/html/HTMLHRElement03.xml.kfail
rename to test/testcases/tests/level1/html/HTMLHRElement03.xml
diff --git a/test/testcases/tests/level1/html/HTMLHRElement04.xml.kfail b/test/testcases/tests/level1/html/HTMLHRElement04.xml
similarity index 100%
rename from test/testcases/tests/level1/html/HTMLHRElement04.xml.kfail
rename to test/testcases/tests/level1/html/HTMLHRElement04.xml
--
Document Object Model library
8 years, 11 months
netsurf: branch vince/llcache updated. release/3.0-1149-g0918987
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/09189872900d083e2a528...
...commit http://git.netsurf-browser.org/netsurf.git/commit/09189872900d083e2a528ff...
...tree http://git.netsurf-browser.org/netsurf.git/tree/09189872900d083e2a528ff1e...
The branch, vince/llcache has been updated
via 09189872900d083e2a528ff1edde9c77b744322c (commit)
via 0107e222270a5a56c37857a33d193169e7d6d83d (commit)
from a0a5433b995a13eda8d6cce2afb9ee364de473ba (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=09189872900d083e2a5...
commit 09189872900d083e2a528ff1edde9c77b744322c
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
make generic file based backing store
diff --git a/content/Makefile b/content/Makefile
index 557e6c7..38b0b49 100644
--- a/content/Makefile
+++ b/content/Makefile
@@ -1,6 +1,6 @@
# Content sources
S_CONTENT := content.c content_factory.c dirlist.c fetch.c hlcache.c \
- llcache.c mimesniff.c urldb.c
+ llcache.c mimesniff.c urldb.c backing_store.c
S_CONTENT := $(addprefix content/,$(S_CONTENT))
\ No newline at end of file
diff --git a/content/backing_store.c b/content/backing_store.c
new file mode 100644
index 0000000..65e74fe
--- /dev/null
+++ b/content/backing_store.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Low-level resource cache persistant storage implementation.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "utils/nsurl.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "utils/sha1.h"
+#include "desktop/gui.h"
+
+#include "content/backing_store.h"
+
+#ifdef BACKING_STORE_FILE
+
+/* file based backing store */
+
+struct llcache_store_state {
+ /** parameters controlling the backing store */
+ struct llcache_store_parameters params;
+
+ /** key to filename conversion */
+ char *(*store_fname)(nsurl *url, enum llcache_store_flags flags);
+};
+
+struct llcache_store_state *storestate;
+
+
+static uint8_t encoding_table[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '-', '_'
+};
+static unsigned int mod_table[] = {0, 2, 1};
+
+
+static uint8_t *
+base64url_encode(const char *data,
+ size_t input_length,
+ size_t *output_length)
+{
+ uint8_t *encoded_data;
+ size_t i;
+ size_t j;
+
+ *output_length = 4 * ((input_length + 2) / 3);
+
+ encoded_data = malloc(*output_length + 1);
+ if (encoded_data == NULL) {
+ return NULL;
+ }
+
+ for (i = 0, j = 0; i < input_length;) {
+
+ uint32_t octet_a = i < input_length ? data[i++] : 0;
+ uint32_t octet_b = i < input_length ? data[i++] : 0;
+ uint32_t octet_c = i < input_length ? data[i++] : 0;
+
+ uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+ encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
+ }
+
+ for (i = 0; i < mod_table[input_length % 3]; i++) {
+ encoded_data[*output_length - 1 - i] = 0;
+ (*output_length)--;
+ }
+
+ return encoded_data;
+}
+
+/**
+ * create filename from url and flags
+ *
+ * This uses 160bit sha1 and a bit from the from flags which is then
+ * base64 encoded. This yeilds a 28 character base64 encoded string
+ * (168 bits is minimum byte representation of 161 bits) where the
+ * last character can be discarded (27*6 is 162 bits)
+ */
+static char *
+b64_store_fname_sha1(nsurl *url, enum llcache_store_flags flags)
+{
+ uint8_t hash[NSSHA1_DIGEST_SIZE + 1];
+ int fname_len;
+ char *fname;
+ uint8_t *b64u;
+ size_t b64ulen;
+
+ NSSHA1((uint8_t *)nsurl_access(url), nsurl_length(url), hash);
+
+ if ((flags & LLCACHE_STORE_META) != 0) {
+ hash[NSSHA1_DIGEST_SIZE] = 0xff;
+ } else {
+ hash[NSSHA1_DIGEST_SIZE] = 0;
+ }
+
+ b64u = base64url_encode((char *)hash, NSSHA1_DIGEST_SIZE + 1, &b64ulen);
+ if (b64u == NULL) {
+ return NULL;
+ }
+ b64u[27] = 0;
+ LOG(("b64u len:%d from %d with \"%s\"", b64ulen, NSSHA1_DIGEST_SIZE + 1, b64u));
+ fname_len = strlen(storestate->params.path) + 31;
+ fname = calloc(1, fname_len);
+ if (fname == NULL) {
+ free(b64u);
+ return NULL;
+ }
+
+ snprintf(fname,
+ fname_len,
+ "%s/%c%c/%s",
+ storestate->params.path,
+ b64u[0], b64u[1], b64u + 2 );
+ free(b64u);
+
+ return fname;
+}
+
+/**
+ * Create filename from url and flags
+ *
+ * This uses 17bits from the fnv url hash and one bit from the
+ * flags. Yeilding data in 3 bytes which is base64 encoded, the fourth
+ * character (last 6 bits) of the base 64 encoding is not used as it is
+ * empty.
+ */
+static char *
+b64_store_fname_fnv(nsurl *url, enum llcache_store_flags flags)
+{
+ uint32_t hash;
+ char *hashp;
+ int fname_len;
+ char *fname;
+ uint8_t *b64u;
+ size_t b64ulen;
+
+ hash = nsurl_hash(url);
+
+ hashp = (char *)&hash;
+
+ hashp[2] = hashp[2] & 0x80;
+
+ if ((flags & LLCACHE_STORE_META) != 0) {
+ hashp[2] = hashp[2] | 0x40;
+ }
+
+ b64u = base64url_encode(hashp, 3, &b64ulen);
+ if (b64u == NULL) {
+ return NULL;
+ }
+
+ fname_len = strlen(storestate->params.path) + 7;
+ fname = calloc(1, fname_len);
+ if (fname == NULL) {
+ free(b64u);
+ return NULL;
+ }
+
+ snprintf(fname,
+ fname_len,
+ "%s/%c/%c/%c",
+ storestate->params.path,
+ b64u[0], b64u[1], b64u[2]);
+ free(b64u);
+
+ return fname;
+}
+
+/**
+ * create filename from url and flags
+ *
+ * no hashing, just base64 encode the url
+ */
+static char *
+b64_store_fname(nsurl *url, enum llcache_store_flags flags)
+{
+ char *fname;
+ uint8_t *b64u;
+ size_t b64ulen;
+ char sep;
+
+ b64u = base64url_encode(nsurl_access(url),
+ strlen(nsurl_access(url)),
+ &b64ulen);
+ if (b64u == NULL) {
+ return NULL;
+ }
+
+ fname = malloc(strlen(storestate->params.path) +
+ SLEN("/x") + b64ulen + 1);
+ if (fname == NULL) {
+ free(b64u);
+ return NULL;
+ }
+
+ if ((flags & LLCACHE_STORE_META) == 0) {
+ sep ='d';
+ } else {
+ sep ='i';
+ }
+
+ snprintf(fname,
+ (strlen(storestate->params.path) + SLEN("/x") + b64ulen + 1),
+ "%s/%s%c",
+ storestate->params.path,
+ b64u,
+ sep);
+ free(b64u);
+
+ return fname;
+}
+
+/* backing store implementation */
+
+/**
+ * Initialise the backing store.
+ *
+ * @param parameters to configure backing store.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+initialise(const struct llcache_store_parameters *parameters)
+{
+ /* check backing store is not already initialised */
+ if (storestate != NULL) {
+ return NSERROR_INIT_FAILED;
+ }
+
+ storestate = calloc(1, sizeof(struct llcache_store_state));
+ if (storestate == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ memcpy(&storestate->params,
+ parameters,
+ sizeof(struct llcache_store_parameters));
+
+ if (storestate->params.hashsize == 0) {
+ storestate->store_fname = b64_store_fname;
+ } else if (storestate->params.hashsize < 32) {
+ storestate->store_fname = b64_store_fname_fnv;
+ } else {
+ storestate->store_fname = b64_store_fname_sha1;
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * Finalise the backing store.
+ *
+ * @return NSERROR_OK on success.
+ */
+static nserror
+finalise(void)
+{
+ if (storestate != NULL) {
+ free(storestate);
+ storestate = NULL;
+ }
+ return NSERROR_OK;
+}
+
+/* ensure that all directory elements needed to store a filename exist */
+static nserror mkfilepath(const char *fname)
+{
+ char *dname;
+ char *sep;
+ struct stat sb;
+
+ dname = strdup(fname);
+
+ sep = strrchr(dname, '/');
+ if (sep == NULL) {
+ /* no directory separator path is just filename so its ok */
+ free(dname);
+ return NSERROR_OK;
+ }
+
+ *sep = 0; /* null terminate directory path */
+
+ if (stat(dname, &sb) == 0) {
+ free(dname);
+ if (S_ISDIR(sb.st_mode)) {
+ /* path to file exists and is a directory */
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_FOUND;
+ }
+ *sep = '/'; /* restore separator */
+
+ sep = dname;
+ while (*sep == '/') {
+ sep++;
+ }
+ while ((sep = strchr(sep, '/')) != NULL) {
+ *sep = 0;
+ if (stat(dname, &sb) != 0) {
+ if (mkdir(dname, 0700) != 0) {
+ /* could not create path element */
+ free(dname);
+ return NSERROR_NOT_FOUND;
+ }
+ } else {
+ if (! S_ISDIR(sb.st_mode)) {
+ /* path element not a directory */
+ free(dname);
+ return NSERROR_NOT_FOUND;
+ }
+ }
+ *sep = '/'; /* restore separator */
+ /* skip directory separators */
+ while (*sep == '/') {
+ sep++;
+ }
+ }
+
+ free(dname);
+ return NSERROR_OK;
+}
+
+/**
+ * Place a source object and its metadata in the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the object is stored.
+ * @param data The objects source data.
+ * @param datalen The length of the \a data.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+store(nsurl *url,
+ enum llcache_store_flags flags,
+ const uint8_t *data,
+ const size_t datalen)
+{
+ char *fname;
+ FILE *file;
+ nserror ret;
+
+ LOG(("Writing object for url:%s", nsurl_access(url)));
+ fname = storestate->store_fname(url, flags);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* ensure path to file is usable */
+ ret = mkfilepath(fname);
+ if (ret != NSERROR_OK) {
+ LOG(("file path \"%s\" could not be created", fname));
+ free(fname);
+ return ret;
+ }
+
+ LOG(("Opening data file %s", fname));
+ file = fopen(fname, "wb");
+ free(fname);
+ if (file == NULL) {
+ return NSERROR_SAVE_FAILED;
+ }
+
+ LOG(("Writing %d bytes from %p", datalen, data));
+ if (fwrite(data, datalen, 1, file) != 1) {
+ LOG(("did not return 1"));
+ fclose(file);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ fclose(file);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Retrive an object from the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the object is stored.
+ * @param data The objects data.
+ * @param datalen The length of the \a data retrieved.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+fetch(nsurl *url,
+ enum llcache_store_flags *flags,
+ uint8_t **data_out,
+ size_t *datalen_out)
+{
+ char *fname;
+ FILE *file;
+ uint8_t *data;
+ size_t datalen;
+
+ data = *data_out;
+ datalen = *datalen_out;
+
+ LOG(("retriving cache file for url:%s", nsurl_access(url)));
+
+ fname = storestate->store_fname(url, *flags);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ LOG(("Opening file %s",fname));
+
+ file = fopen(fname, "rb");
+ free(fname);
+ if (file == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* need to deal with buffers */
+ if (data == NULL) {
+ if (datalen == 0) {
+ /* caller did not know the files length */
+ fseek(file, 0L, SEEK_END);
+ datalen = ftell(file);
+ fseek(file, 0L, SEEK_SET);
+ }
+
+ data = malloc(datalen);
+ if (data == NULL) {
+ fclose(file);
+ return NSERROR_NOMEM;
+ }
+ }
+
+ LOG(("Reading %d bytes into %p from file", datalen, data));
+ if (fread(data, datalen, 1, file) != 1) {
+ LOG(("did not return 1"));
+ fclose(file);
+ if ((*data_out) == NULL) {
+ free(data);
+ }
+ return NSERROR_NOT_FOUND;
+ }
+
+ fclose(file);
+
+ *data_out = data;
+ *datalen_out = datalen;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Invalidate a source object from the backing store.
+ *
+ * The entry (if present in the backing store) must no longer
+ * be returned as a result to the fetch or meta operations.
+ *
+ * @param url The url is used as the unique primary key to invalidate.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+invalidate(nsurl *url)
+{
+ char *fname;
+ fname = storestate->store_fname(url, LLCACHE_STORE_META);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ unlink(fname);
+ free(fname);
+
+ fname = storestate->store_fname(url, LLCACHE_STORE_NONE);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ unlink(fname);
+ free(fname);
+
+ return NSERROR_OK;
+}
+
+#else
+
+/* default to disabled backing store */
+static nserror initialise(const struct llcache_store_parameters *parameters)
+{
+ return NSERROR_OK;
+}
+
+static nserror finalise(void)
+{
+ return NSERROR_OK;
+}
+
+static nserror store(nsurl *url,
+ enum llcache_store_flags flags,
+ const uint8_t *data,
+ const size_t datalen)
+{
+ return NSERROR_SAVE_FAILED;
+}
+
+static nserror fetch(nsurl *url,
+ enum llcache_store_flags *flags,
+ uint8_t **data_out,
+ size_t *datalen_out)
+{
+ return NSERROR_NOT_FOUND;
+}
+
+static nserror invalidate(nsurl *url)
+{
+ return NSERROR_NOT_FOUND;
+}
+
+
+#endif
+
+
+static struct gui_llcache_table llcache_table = {
+ .initialise = initialise,
+ .finalise = finalise,
+ .store = store,
+ .fetch = fetch,
+ .invalidate = invalidate,
+};
+
+struct gui_llcache_table *default_llcache_table = &llcache_table;
diff --git a/content/backing_store.h b/content/backing_store.h
new file mode 100644
index 0000000..33f711e
--- /dev/null
+++ b/content/backing_store.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Low-level source data cache backing store interface
+ */
+
+#ifndef NETSURF_CONTENT_LLCACHE_PRIVATE_H_
+#define NETSURF_CONTENT_LLCACHE_PRIVATE_H_
+
+#include "content/llcache.h"
+
+/** storage control flags */
+enum llcache_store_flags {
+ LLCACHE_STORE_NONE = 0, /**< no special processing */
+ LLCACHE_STORE_META = 1, /**< data is metadata */
+ LLCACHE_STORE_MMAP = 2, /**< when data is retrived this indicates the
+ * returned buffer may be memory mapped,
+ * flag must be cleared if the storage is
+ * allocated and is not memory mapped.
+ */
+};
+
+/** low level cache backing store operation table
+ *
+ * The low level cache (source objects) has the capability to make
+ * objects and their metadata (headers etc) persistant by writing to a
+ * backing store using these operations.
+ */
+struct gui_llcache_table {
+ /**
+ * Initialise the backing store.
+ *
+ * @param parameters to configure backing store.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*initialise)(const struct llcache_store_parameters *parameters);
+
+ /**
+ * Finalise the backing store.
+ *
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*finalise)(void);
+
+ /**
+ * Place an object in the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the obejct is stored.
+ * @param data The objects data.
+ * @param datalen The length of the \a data.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*store)(struct nsurl *url, enum llcache_store_flags flags,
+ const uint8_t *data, const size_t datalen);
+
+ /**
+ * Retrive an object from the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the object is retrived.
+ * @param data The objects data.
+ * @param datalen The length of the \a data retrieved.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*fetch)(struct nsurl *url, enum llcache_store_flags *flags,
+ uint8_t **data, size_t *datalen);
+
+ /**
+ * Invalidate a source object from the backing store.
+ *
+ * The entry (if present in the backing store) must no longer
+ * be returned as a result to the fetch or meta operations.
+ *
+ * @param url The url is used as the unique primary key to invalidate.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*invalidate)(struct nsurl *url);
+};
+
+extern struct gui_llcache_table* default_llcache_table;
+
+#endif
diff --git a/content/llcache.c b/content/llcache.c
index 63fb14e..77d0335 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -55,7 +55,7 @@
#include "desktop/gui_factory.h"
#include "content/fetch.h"
-#include "content/llcache_private.h"
+#include "content/backing_store.h"
#include "content/urldb.h"
/** Define to enable tracing of llcache operations. */
diff --git a/content/llcache_private.h b/content/llcache_private.h
deleted file mode 100644
index ae1b3da..0000000
--- a/content/llcache_private.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/** \file
- * Low-level source data cache backing store interface
- */
-
-#ifndef NETSURF_CONTENT_LLCACHE_PRIVATE_H_
-#define NETSURF_CONTENT_LLCACHE_PRIVATE_H_
-
-#include "content/llcache.h"
-
-/** storage control flags */
-enum llcache_store_flags {
- LLCACHE_STORE_NONE = 0, /**< no special processing */
- LLCACHE_STORE_META = 1, /**< data is metadata */
- LLCACHE_STORE_MMAP = 2, /**< when data is retrived this indicates the
- * returned buffer may be memory mapped,
- * flag must be cleared if the storage is
- * allocated and is not memory mapped.
- */
-};
-
-/** low level cache backing store operation table
- *
- * The low level cache (source objects) has the capability to make
- * objects and their metadata (headers etc) persistant by writing to a
- * backing store using these operations.
- */
-struct gui_llcache_table {
- /**
- * Initialise the backing store.
- *
- * @param parameters to configure backing store.
- * @return NSERROR_OK on success or error code on faliure.
- */
- nserror (*initialise)(const struct llcache_store_parameters *parameters);
-
- /**
- * Finalise the backing store.
- *
- * @return NSERROR_OK on success or error code on faliure.
- */
- nserror (*finalise)(void);
-
- /**
- * Place an object in the backing store.
- *
- * @param url The url is used as the unique primary key for the data.
- * @param flags The flags to control how the obejct is stored.
- * @param data The objects data.
- * @param datalen The length of the \a data.
- * @return NSERROR_OK on success or error code on faliure.
- */
- nserror (*store)(struct nsurl *url, enum llcache_store_flags flags,
- const uint8_t *data, const size_t datalen);
-
- /**
- * Retrive an object from the backing store.
- *
- * @param url The url is used as the unique primary key for the data.
- * @param flags The flags to control how the object is retrived.
- * @param data The objects data.
- * @param datalen The length of the \a data retrieved.
- * @return NSERROR_OK on success or error code on faliure.
- */
- nserror (*fetch)(struct nsurl *url, enum llcache_store_flags *flags,
- uint8_t **data, size_t *datalen);
-
- /**
- * Invalidate a source object from the backing store.
- *
- * The entry (if present in the backing store) must no longer
- * be returned as a result to the fetch or meta operations.
- *
- * @param url The url is used as the unique primary key to invalidate.
- * @return NSERROR_OK on success or error code on faliure.
- */
- nserror (*invalidate)(struct nsurl *url);
-};
-
-#endif
diff --git a/desktop/gui.h b/desktop/gui.h
index 0eddf12..93775ca 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -531,7 +531,8 @@ struct gui_table {
*/
struct gui_utf8_table *utf8;
- /** Low level cache table
+ /**
+ * Low level cache table
*
* Used by the low level cache to push objects to persistant
* storage. The table is optional and may be NULL which
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index d91371d..df51392 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -17,7 +17,7 @@
*/
#include "content/hlcache.h"
-#include "content/llcache_private.h"
+#include "content/backing_store.h"
#include "desktop/download.h"
#include "desktop/gui_factory.h"
@@ -26,7 +26,6 @@
struct gui_table *guit = NULL;
-
static void gui_default_window_set_title(struct gui_window *g, const char *title)
{
}
@@ -345,51 +344,6 @@ static nserror verify_utf8_register(struct gui_utf8_table *gut)
return NSERROR_OK;
}
-static nserror
-gui_default_initialise(const struct llcache_store_parameters *parameters)
-{
- return NSERROR_OK;
-}
-
-static nserror
-gui_default_finalise(void)
-{
- return NSERROR_OK;
-}
-
-static nserror
-gui_default_store(nsurl *url,
- enum llcache_store_flags flags,
- const uint8_t *data,
- const size_t datalen)
-{
- return NSERROR_SAVE_FAILED;
-}
-
-static nserror
-gui_default_fetch(nsurl *url,
- enum llcache_store_flags *flags,
- uint8_t **data_out,
- size_t *datalen_out)
-{
- return NSERROR_NOT_FOUND;
-}
-
-static nserror
-gui_default_invalidate(nsurl *url)
-{
- return NSERROR_NOT_FOUND;
-}
-
-
-static struct gui_llcache_table default_llcache_table = {
- .initialise = gui_default_initialise,
- .finalise = gui_default_finalise,
- .store = gui_default_store,
- .fetch = gui_default_fetch,
- .invalidate = gui_default_invalidate,
-};
-
/** verify clipboard table is valid */
static nserror verify_llcache_register(struct gui_llcache_table *glt)
{
@@ -408,13 +362,11 @@ static nserror verify_llcache_register(struct gui_llcache_table *glt)
if (glt->invalidate == NULL) {
return NSERROR_BAD_PARAMETER;
}
-
- /* fill in the optional entries with defaults */
if (glt->initialise == NULL) {
- glt->initialise = gui_default_initialise;
+ return NSERROR_BAD_PARAMETER;
}
if (glt->finalise == NULL) {
- glt->finalise = gui_default_finalise;
+ return NSERROR_BAD_PARAMETER;
}
return NSERROR_OK;
@@ -613,8 +565,8 @@ nserror gui_factory_register(struct gui_table *gt)
/* llcache table */
if (gt->llcache == NULL) {
- /* set default clipboard table */
- gt->llcache = &default_llcache_table;
+ /* set default backing store table */
+ gt->llcache = default_llcache_table;
}
err = verify_llcache_register(gt->llcache);
if (err != NSERROR_OK) {
diff --git a/gtk/Makefile.target b/gtk/Makefile.target
index df9ac73..ec19d1b 100644
--- a/gtk/Makefile.target
+++ b/gtk/Makefile.target
@@ -110,7 +110,7 @@ S_GTK := font_pango.c bitmap.c gui.c schedule.c thumbnail.c plotters.c \
treeview.c scaffolding.c gdk.c completion.c login.c throbber.c \
selection.c history.c window.c fetch.c download.c menu.c \
print.c search.c tabs.c theme.c toolbar.c gettext.c \
- compat.c cookies.c hotlist.c llcache.c \
+ compat.c cookies.c hotlist.c \
$(addprefix dialogs/,preferences.c about.c source.c)
S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c)
diff --git a/gtk/gui.c b/gtk/gui.c
index 1e6ff4c..cf584c3 100644
--- a/gtk/gui.c
+++ b/gtk/gui.c
@@ -56,6 +56,14 @@
#include "desktop/tree.h"
#include "css/utils.h"
+#include "render/form.h"
+#include "utils/filepath.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/url.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+
#include "gtk/compat.h"
#include "gtk/completion.h"
#include "gtk/cookies.h"
@@ -69,15 +77,6 @@
#include "gtk/window.h"
#include "gtk/schedule.h"
#include "gtk/selection.h"
-#include "gtk/llcache.h"
-
-#include "render/form.h"
-#include "utils/filepath.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/url.h"
-#include "utils/utf8.h"
-#include "utils/utils.h"
char *options_file_location;
char *toolbar_indices_file_location;
@@ -1016,7 +1015,6 @@ int main(int argc, char** argv)
.clipboard = nsgtk_clipboard_table,
.download = nsgtk_download_table,
.fetch = nsgtk_fetch_table,
- .llcache = nsgtk_llcache_table,
};
/* check home directory is available */
diff --git a/gtk/llcache.c b/gtk/llcache.c
deleted file mode 100644
index 7c6f961..0000000
--- a/gtk/llcache.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/** \file
- * Low-level resource cache persistant storage implementation.
- */
-
-#include <unistd.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "utils/nsurl.h"
-#include "utils/log.h"
-#include "utils/utils.h"
-#include "utils/sha1.h"
-#include "desktop/gui.h"
-#include "content/llcache_private.h"
-
-#include "gtk/llcache.h"
-
-struct llcache_store_state {
- /** parameters controlling the backing store */
- struct llcache_store_parameters params;
-
- /** key to filename conversion */
- char *(*store_fname)(nsurl *url, enum llcache_store_flags flags);
-};
-
-struct llcache_store_state *storestate;
-
-
-static uint8_t encoding_table[] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
- 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
- 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
- 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
- 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
- 'w', 'x', 'y', 'z', '0', '1', '2', '3',
- '4', '5', '6', '7', '8', '9', '-', '_'
-};
-static unsigned int mod_table[] = {0, 2, 1};
-
-
-static uint8_t *
-base64url_encode(const char *data,
- size_t input_length,
- size_t *output_length)
-{
- uint8_t *encoded_data;
- size_t i;
- size_t j;
-
- *output_length = 4 * ((input_length + 2) / 3);
-
- encoded_data = malloc(*output_length + 1);
- if (encoded_data == NULL) {
- return NULL;
- }
-
- for (i = 0, j = 0; i < input_length;) {
-
- uint32_t octet_a = i < input_length ? data[i++] : 0;
- uint32_t octet_b = i < input_length ? data[i++] : 0;
- uint32_t octet_c = i < input_length ? data[i++] : 0;
-
- uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
-
- encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
- encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
- encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
- encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
- }
-
- for (i = 0; i < mod_table[input_length % 3]; i++) {
- encoded_data[*output_length - 1 - i] = 0;
- (*output_length)--;
- }
-
- return encoded_data;
-}
-
-/**
- * create filename from url and flags
- *
- * This uses 160bit sha1 and a bit from the from flags which is then
- * base64 encoded. This yeilds a 28 character base64 encoded string
- * (168 bits is minimum byte representation of 161 bits) where the
- * last character can be discarded (27*6 is 162 bits)
- */
-static char *
-b64_store_fname_sha1(nsurl *url, enum llcache_store_flags flags)
-{
- uint8_t hash[NSSHA1_DIGEST_SIZE + 1];
- int fname_len;
- char *fname;
- uint8_t *b64u;
- size_t b64ulen;
-
- NSSHA1((uint8_t *)nsurl_access(url), nsurl_length(url), hash);
-
- if ((flags & LLCACHE_STORE_META) != 0) {
- hash[NSSHA1_DIGEST_SIZE] = 0xff;
- } else {
- hash[NSSHA1_DIGEST_SIZE] = 0;
- }
-
- b64u = base64url_encode((char *)hash, NSSHA1_DIGEST_SIZE + 1, &b64ulen);
- if (b64u == NULL) {
- return NULL;
- }
- b64u[27] = 0;
- LOG(("b64u len:%d from %d with \"%s\"", b64ulen, NSSHA1_DIGEST_SIZE + 1, b64u));
- fname_len = strlen(storestate->params.path) + 31;
- fname = calloc(1, fname_len);
- if (fname == NULL) {
- free(b64u);
- return NULL;
- }
-
- snprintf(fname,
- fname_len,
- "%s/%c%c/%s",
- storestate->params.path,
- b64u[0], b64u[1], b64u + 2 );
- free(b64u);
-
- return fname;
-}
-
-/**
- * Create filename from url and flags
- *
- * This uses 17bits from the fnv url hash and one bit from the
- * flags. Yeilding data in 3 bytes which is base64 encoded, the fourth
- * character (last 6 bits) of the base 64 encoding is not used as it is
- * empty.
- */
-static char *
-b64_store_fname_fnv(nsurl *url, enum llcache_store_flags flags)
-{
- uint32_t hash;
- char *hashp;
- int fname_len;
- char *fname;
- uint8_t *b64u;
- size_t b64ulen;
-
- hash = nsurl_hash(url);
-
- hashp = (char *)&hash;
-
- hashp[2] = hashp[2] & 0x80;
-
- if ((flags & LLCACHE_STORE_META) != 0) {
- hashp[2] = hashp[2] | 0x40;
- }
-
- b64u = base64url_encode(hashp, 3, &b64ulen);
- if (b64u == NULL) {
- return NULL;
- }
-
- fname_len = strlen(storestate->params.path) + 7;
- fname = calloc(1, fname_len);
- if (fname == NULL) {
- free(b64u);
- return NULL;
- }
-
- snprintf(fname,
- fname_len,
- "%s/%c/%c/%c",
- storestate->params.path,
- b64u[0], b64u[1], b64u[2]);
- free(b64u);
-
- return fname;
-}
-
-/**
- * create filename from url and flags
- *
- * no hashing, just base64 encode the url
- */
-static char *
-b64_store_fname(nsurl *url, enum llcache_store_flags flags)
-{
- char *fname;
- uint8_t *b64u;
- size_t b64ulen;
- char sep;
-
- b64u = base64url_encode(nsurl_access(url),
- strlen(nsurl_access(url)),
- &b64ulen);
- if (b64u == NULL) {
- return NULL;
- }
-
- fname = malloc(strlen(storestate->params.path) +
- SLEN("/x") + b64ulen + 1);
- if (fname == NULL) {
- free(b64u);
- return NULL;
- }
-
- if ((flags & LLCACHE_STORE_META) == 0) {
- sep ='d';
- } else {
- sep ='i';
- }
-
- snprintf(fname,
- (strlen(storestate->params.path) + SLEN("/x") + b64ulen + 1),
- "%s/%s%c",
- storestate->params.path,
- b64u,
- sep);
- free(b64u);
-
- return fname;
-}
-
-/* backing store implementation */
-
-/**
- * Initialise the backing store.
- *
- * @param parameters to configure backing store.
- * @return NSERROR_OK on success or error code on faliure.
- */
-static nserror
-initialise(const struct llcache_store_parameters *parameters)
-{
- /* check backing store is not already initialised */
- if (storestate != NULL) {
- return NSERROR_INIT_FAILED;
- }
-
- storestate = calloc(1, sizeof(struct llcache_store_state));
- if (storestate == NULL) {
- return NSERROR_NOMEM;
- }
-
- memcpy(&storestate->params,
- parameters,
- sizeof(struct llcache_store_parameters));
-
- if (storestate->params.hashsize == 0) {
- storestate->store_fname = b64_store_fname;
- } else if (storestate->params.hashsize < 32) {
- storestate->store_fname = b64_store_fname_fnv;
- } else {
- storestate->store_fname = b64_store_fname_sha1;
- }
-
- return NSERROR_OK;
-}
-
-/**
- * Finalise the backing store.
- *
- * @return NSERROR_OK on success.
- */
-static nserror
-finalise(void)
-{
- if (storestate != NULL) {
- free(storestate);
- storestate = NULL;
- }
- return NSERROR_OK;
-}
-
-/* ensure that all directory elements needed to store a filename exist */
-static nserror mkfilepath(const char *fname)
-{
- char *dname;
- char *sep;
- struct stat sb;
-
- dname = strdup(fname);
-
- sep = strrchr(dname, '/');
- if (sep == NULL) {
- /* no directory separator path is just filename so its ok */
- free(dname);
- return NSERROR_OK;
- }
-
- *sep = 0; /* null terminate directory path */
-
- if (stat(dname, &sb) == 0) {
- free(dname);
- if (S_ISDIR(sb.st_mode)) {
- /* path to file exists and is a directory */
- return NSERROR_OK;
- }
- return NSERROR_NOT_FOUND;
- }
- *sep = '/'; /* restore separator */
-
- sep = dname;
- while (*sep == '/') {
- sep++;
- }
- while ((sep = strchr(sep, '/')) != NULL) {
- *sep = 0;
- if (stat(dname, &sb) != 0) {
- if (mkdir(dname, 0700) != 0) {
- /* could not create path element */
- free(dname);
- return NSERROR_NOT_FOUND;
- }
- } else {
- if (! S_ISDIR(sb.st_mode)) {
- /* path element not a directory */
- free(dname);
- return NSERROR_NOT_FOUND;
- }
- }
- *sep = '/'; /* restore separator */
- /* skip directory separators */
- while (*sep == '/') {
- sep++;
- }
- }
-
- free(dname);
- return NSERROR_OK;
-}
-
-/**
- * Place a source object and its metadata in the backing store.
- *
- * @param url The url is used as the unique primary key for the data.
- * @param flags The flags to control how the object is stored.
- * @param data The objects source data.
- * @param datalen The length of the \a data.
- * @return NSERROR_OK on success or error code on faliure.
- */
-static nserror
-store(nsurl *url,
- enum llcache_store_flags flags,
- const uint8_t *data,
- const size_t datalen)
-{
- char *fname;
- FILE *file;
- nserror ret;
-
- LOG(("Writing object for url:%s", nsurl_access(url)));
- fname = storestate->store_fname(url, flags);
- if (fname == NULL) {
- return NSERROR_NOMEM;
- }
-
- /* ensure path to file is usable */
- ret = mkfilepath(fname);
- if (ret != NSERROR_OK) {
- LOG(("file path \"%s\" could not be created", fname));
- free(fname);
- return ret;
- }
-
- LOG(("Opening data file %s", fname));
- file = fopen(fname, "wb");
- free(fname);
- if (file == NULL) {
- return NSERROR_SAVE_FAILED;
- }
-
- LOG(("Writing %d bytes from %p", datalen, data));
- if (fwrite(data, datalen, 1, file) != 1) {
- LOG(("did not return 1"));
- fclose(file);
- return NSERROR_SAVE_FAILED;
- }
-
- fclose(file);
-
- return NSERROR_OK;
-}
-
-/**
- * Retrive an object from the backing store.
- *
- * @param url The url is used as the unique primary key for the data.
- * @param flags The flags to control how the object is stored.
- * @param data The objects data.
- * @param datalen The length of the \a data retrieved.
- * @return NSERROR_OK on success or error code on faliure.
- */
-static nserror
-fetch(nsurl *url,
- enum llcache_store_flags *flags,
- uint8_t **data_out,
- size_t *datalen_out)
-{
- char *fname;
- FILE *file;
- uint8_t *data;
- size_t datalen;
-
- data = *data_out;
- datalen = *datalen_out;
-
- LOG(("retriving cache file for url:%s", nsurl_access(url)));
-
- fname = storestate->store_fname(url, *flags);
- if (fname == NULL) {
- return NSERROR_NOMEM;
- }
-
- LOG(("Opening file %s",fname));
-
- file = fopen(fname, "rb");
- free(fname);
- if (file == NULL) {
- return NSERROR_NOT_FOUND;
- }
-
- /* need to deal with buffers */
- if (data == NULL) {
- if (datalen == 0) {
- /* caller did not know the files length */
- fseek(file, 0L, SEEK_END);
- datalen = ftell(file);
- fseek(file, 0L, SEEK_SET);
- }
-
- data = malloc(datalen);
- if (data == NULL) {
- fclose(file);
- return NSERROR_NOMEM;
- }
- }
-
- LOG(("Reading %d bytes into %p from file", datalen, data));
- if (fread(data, datalen, 1, file) != 1) {
- LOG(("did not return 1"));
- fclose(file);
- if ((*data_out) == NULL) {
- free(data);
- }
- return NSERROR_NOT_FOUND;
- }
-
- fclose(file);
-
- *data_out = data;
- *datalen_out = datalen;
-
- return NSERROR_OK;
-}
-
-
-/**
- * Invalidate a source object from the backing store.
- *
- * The entry (if present in the backing store) must no longer
- * be returned as a result to the fetch or meta operations.
- *
- * @param url The url is used as the unique primary key to invalidate.
- * @return NSERROR_OK on success or error code on faliure.
- */
-static nserror
-invalidate(nsurl *url)
-{
- char *fname;
- fname = storestate->store_fname(url, LLCACHE_STORE_META);
- if (fname == NULL) {
- return NSERROR_NOMEM;
- }
- unlink(fname);
- free(fname);
-
- fname = storestate->store_fname(url, LLCACHE_STORE_NONE);
- if (fname == NULL) {
- return NSERROR_NOMEM;
- }
- unlink(fname);
- free(fname);
-
- return NSERROR_OK;
-}
-
-
-static struct gui_llcache_table llcache_table = {
- .initialise = initialise,
- .finalise = finalise,
- .store = store,
- .fetch = fetch,
- .invalidate = invalidate,
-};
-
-struct gui_llcache_table *nsgtk_llcache_table = &llcache_table;
diff --git a/gtk/llcache.h b/gtk/llcache.h
deleted file mode 100644
index 6afdfe9..0000000
--- a/gtk/llcache.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GTK_LLCACHE_H
-#define GTK_LLCACHE_H
-
-extern struct gui_llcache_table* nsgtk_llcache_table;
-
-#endif
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=0107e222270a5a56c37...
commit 0107e222270a5a56c37857a33d193169e7d6d83d
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
move config to parameters
diff --git a/content/llcache.c b/content/llcache.c
index 5c6a560..63fb14e 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -52,7 +52,6 @@
#include "utils/messages.h"
#include "utils/nsurl.h"
#include "utils/utils.h"
-#include "utils/schedule.h"
#include "desktop/gui_factory.h"
#include "content/fetch.h"
@@ -212,7 +211,17 @@ struct llcache_s {
/** Head of the low-level uncached object list */
llcache_object *uncached_objects;
+ /** The target upper bound for the RAM cache size */
uint32_t limit;
+
+ /** The minimum lifetime to consider sending objects to
+ * backing store.
+ */
+ int minimum_lifetime;
+
+ /** The maximum bandwidth to allow the backing store to use. */
+ size_t bandwidth;
+
};
/** low level cache state */
@@ -2108,10 +2117,10 @@ static nserror llcache_fetch_ssl_error(llcache_object *object)
*
* The list contains fresh cacheable objects held in RAM with no
* pending fetches. Any objects with a remaining lifetime less than
- * LLCACHE_MIN_DISC_LIFETIME time are simply not considered, they will
+ * the configured minimum lifetime are simply not considered, they will
* become stale before pushing to backing store is worth the cost.
*
- * \todo calculate useful cost metrics to improve sorting
+ * \todo calculate useful cost metrics to improve sorting.
*
*/
static nserror
@@ -2139,7 +2148,7 @@ build_candidate_list(struct llcache_object ***lst_out, int *lst_len_out)
(object->fetch.fetch == NULL) &&
(object->fetch.outstanding_query == false) &&
(object->store_state == LLCACHE_STATE_RAM) &&
- (remaining_lifetime > LLCACHE_MIN_DISC_LIFETIME)) {
+ (remaining_lifetime > llcache->minimum_lifetime)) {
lst[lst_len] = object;
lst_len++;
if (lst_len == 512)
@@ -2229,11 +2238,11 @@ static void llcache_persist(void *p)
}
total_written += size_written;
- if (total_written > LLCACHE_MAX_DISC_BANDWIDTH) {
+ if (total_written > llcache->bandwidth) {
/* The bandwidth limit has been reached.
* Writeout scheduled for the remaining objects
*/
- schedule(100, llcache_persist, NULL);
+ guit->browser->schedule(1000, llcache_persist, NULL);
break;
}
}
@@ -2346,7 +2355,7 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
/* record when the fetch finished */
object->cache.fin_time = time(NULL);
- schedule(500, llcache_persist, NULL);
+ guit->browser->schedule(5000, llcache_persist, NULL);
}
break;
@@ -2913,6 +2922,8 @@ llcache_initialise(const struct llcache_parameters *prm)
llcache->query_cb = prm->cb;
llcache->query_cb_pw = prm->cb_ctx;
llcache->limit = prm->limit;
+ llcache->minimum_lifetime = prm->minimum_lifetime;
+ llcache->bandwidth = prm->bandwidth;
LOG(("llcache initialised with a limit of %d bytes", llcache->limit));
diff --git a/content/llcache.h b/content/llcache.h
index e562083..286e20e 100644
--- a/content/llcache.h
+++ b/content/llcache.h
@@ -184,6 +184,14 @@ struct llcache_parameters {
size_t limit; /**< The target upper bound for the RAM cache size */
size_t hysteresis; /**< The hysteresis around the target size */
+ int minimum_lifetime; /**< The minimum lifetime to consider
+ * sending objects to backing store.
+ */
+
+ size_t bandwidth; /**< The maximum bandwidth to allow the
+ * backing store to use.
+ */
+
struct llcache_store_parameters store;
};
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index 1f5bc59..51de982 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -67,12 +67,18 @@
*/
#define SPECULATE_SMALL 4096
-/** the time between image cache clean runs in ms */
+/** the time between image cache clean runs in ms. */
#define IMAGE_CACHE_CLEAN_TIME (10 * 1000)
-/** default time between content cache cleans */
+/** default time between content cache cleans. */
#define HL_CACHE_CLEAN_TIME (2 * IMAGE_CACHE_CLEAN_TIME)
+/** default minimum object time before object is pushed to backing store. */
+#define LLCACHE_MIN_DISC_LIFETIME (60 * 30)
+
+/** default maximum bandwidth for backing store writeout. */
+#define LLCACHE_MAX_DISC_BANDWIDTH (128 * 1024)
+
/** ensure there is a minimal amount of memory for source objetcs and
* decoded bitmaps.
*/
@@ -126,6 +132,8 @@ nserror netsurf_init(const char *messages, struct gui_table *gt)
.bg_clean_time = HL_CACHE_CLEAN_TIME,
.llcache = {
.cb = netsurf_llcache_query_handler,
+ .minimum_lifetime = LLCACHE_MIN_DISC_LIFETIME,
+ .bandwidth = LLCACHE_MAX_DISC_BANDWIDTH,
.store = {
.hashsize = 160,
}
-----------------------------------------------------------------------
Summary of changes:
content/Makefile | 2 +-
gtk/llcache.c => content/backing_store.c | 46 +++++++++++++++++-
content/{llcache_private.h => backing_store.h} | 2 +
content/llcache.c | 27 ++++++++---
content/llcache.h | 8 +++
desktop/gui.h | 3 +-
desktop/gui_factory.c | 58 ++---------------------
desktop/netsurf.c | 12 ++++-
gtk/Makefile.target | 2 +-
gtk/gui.c | 18 +++----
gtk/llcache.h | 24 ----------
11 files changed, 99 insertions(+), 103 deletions(-)
rename gtk/llcache.c => content/backing_store.c (93%)
rename content/{llcache_private.h => backing_store.h} (98%)
delete mode 100644 gtk/llcache.h
diff --git a/content/Makefile b/content/Makefile
index 557e6c7..38b0b49 100644
--- a/content/Makefile
+++ b/content/Makefile
@@ -1,6 +1,6 @@
# Content sources
S_CONTENT := content.c content_factory.c dirlist.c fetch.c hlcache.c \
- llcache.c mimesniff.c urldb.c
+ llcache.c mimesniff.c urldb.c backing_store.c
S_CONTENT := $(addprefix content/,$(S_CONTENT))
\ No newline at end of file
diff --git a/gtk/llcache.c b/content/backing_store.c
similarity index 93%
rename from gtk/llcache.c
rename to content/backing_store.c
index 7c6f961..65e74fe 100644
--- a/gtk/llcache.c
+++ b/content/backing_store.c
@@ -30,9 +30,12 @@
#include "utils/utils.h"
#include "utils/sha1.h"
#include "desktop/gui.h"
-#include "content/llcache_private.h"
-#include "gtk/llcache.h"
+#include "content/backing_store.h"
+
+#ifdef BACKING_STORE_FILE
+
+/* file based backing store */
struct llcache_store_state {
/** parameters controlling the backing store */
@@ -502,6 +505,43 @@ invalidate(nsurl *url)
return NSERROR_OK;
}
+#else
+
+/* default to disabled backing store */
+static nserror initialise(const struct llcache_store_parameters *parameters)
+{
+ return NSERROR_OK;
+}
+
+static nserror finalise(void)
+{
+ return NSERROR_OK;
+}
+
+static nserror store(nsurl *url,
+ enum llcache_store_flags flags,
+ const uint8_t *data,
+ const size_t datalen)
+{
+ return NSERROR_SAVE_FAILED;
+}
+
+static nserror fetch(nsurl *url,
+ enum llcache_store_flags *flags,
+ uint8_t **data_out,
+ size_t *datalen_out)
+{
+ return NSERROR_NOT_FOUND;
+}
+
+static nserror invalidate(nsurl *url)
+{
+ return NSERROR_NOT_FOUND;
+}
+
+
+#endif
+
static struct gui_llcache_table llcache_table = {
.initialise = initialise,
@@ -511,4 +551,4 @@ static struct gui_llcache_table llcache_table = {
.invalidate = invalidate,
};
-struct gui_llcache_table *nsgtk_llcache_table = &llcache_table;
+struct gui_llcache_table *default_llcache_table = &llcache_table;
diff --git a/content/llcache_private.h b/content/backing_store.h
similarity index 98%
rename from content/llcache_private.h
rename to content/backing_store.h
index ae1b3da..33f711e 100644
--- a/content/llcache_private.h
+++ b/content/backing_store.h
@@ -94,4 +94,6 @@ struct gui_llcache_table {
nserror (*invalidate)(struct nsurl *url);
};
+extern struct gui_llcache_table* default_llcache_table;
+
#endif
diff --git a/content/llcache.c b/content/llcache.c
index 5c6a560..77d0335 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -52,11 +52,10 @@
#include "utils/messages.h"
#include "utils/nsurl.h"
#include "utils/utils.h"
-#include "utils/schedule.h"
#include "desktop/gui_factory.h"
#include "content/fetch.h"
-#include "content/llcache_private.h"
+#include "content/backing_store.h"
#include "content/urldb.h"
/** Define to enable tracing of llcache operations. */
@@ -212,7 +211,17 @@ struct llcache_s {
/** Head of the low-level uncached object list */
llcache_object *uncached_objects;
+ /** The target upper bound for the RAM cache size */
uint32_t limit;
+
+ /** The minimum lifetime to consider sending objects to
+ * backing store.
+ */
+ int minimum_lifetime;
+
+ /** The maximum bandwidth to allow the backing store to use. */
+ size_t bandwidth;
+
};
/** low level cache state */
@@ -2108,10 +2117,10 @@ static nserror llcache_fetch_ssl_error(llcache_object *object)
*
* The list contains fresh cacheable objects held in RAM with no
* pending fetches. Any objects with a remaining lifetime less than
- * LLCACHE_MIN_DISC_LIFETIME time are simply not considered, they will
+ * the configured minimum lifetime are simply not considered, they will
* become stale before pushing to backing store is worth the cost.
*
- * \todo calculate useful cost metrics to improve sorting
+ * \todo calculate useful cost metrics to improve sorting.
*
*/
static nserror
@@ -2139,7 +2148,7 @@ build_candidate_list(struct llcache_object ***lst_out, int *lst_len_out)
(object->fetch.fetch == NULL) &&
(object->fetch.outstanding_query == false) &&
(object->store_state == LLCACHE_STATE_RAM) &&
- (remaining_lifetime > LLCACHE_MIN_DISC_LIFETIME)) {
+ (remaining_lifetime > llcache->minimum_lifetime)) {
lst[lst_len] = object;
lst_len++;
if (lst_len == 512)
@@ -2229,11 +2238,11 @@ static void llcache_persist(void *p)
}
total_written += size_written;
- if (total_written > LLCACHE_MAX_DISC_BANDWIDTH) {
+ if (total_written > llcache->bandwidth) {
/* The bandwidth limit has been reached.
* Writeout scheduled for the remaining objects
*/
- schedule(100, llcache_persist, NULL);
+ guit->browser->schedule(1000, llcache_persist, NULL);
break;
}
}
@@ -2346,7 +2355,7 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
/* record when the fetch finished */
object->cache.fin_time = time(NULL);
- schedule(500, llcache_persist, NULL);
+ guit->browser->schedule(5000, llcache_persist, NULL);
}
break;
@@ -2913,6 +2922,8 @@ llcache_initialise(const struct llcache_parameters *prm)
llcache->query_cb = prm->cb;
llcache->query_cb_pw = prm->cb_ctx;
llcache->limit = prm->limit;
+ llcache->minimum_lifetime = prm->minimum_lifetime;
+ llcache->bandwidth = prm->bandwidth;
LOG(("llcache initialised with a limit of %d bytes", llcache->limit));
diff --git a/content/llcache.h b/content/llcache.h
index e562083..286e20e 100644
--- a/content/llcache.h
+++ b/content/llcache.h
@@ -184,6 +184,14 @@ struct llcache_parameters {
size_t limit; /**< The target upper bound for the RAM cache size */
size_t hysteresis; /**< The hysteresis around the target size */
+ int minimum_lifetime; /**< The minimum lifetime to consider
+ * sending objects to backing store.
+ */
+
+ size_t bandwidth; /**< The maximum bandwidth to allow the
+ * backing store to use.
+ */
+
struct llcache_store_parameters store;
};
diff --git a/desktop/gui.h b/desktop/gui.h
index 0eddf12..93775ca 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -531,7 +531,8 @@ struct gui_table {
*/
struct gui_utf8_table *utf8;
- /** Low level cache table
+ /**
+ * Low level cache table
*
* Used by the low level cache to push objects to persistant
* storage. The table is optional and may be NULL which
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index d91371d..df51392 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -17,7 +17,7 @@
*/
#include "content/hlcache.h"
-#include "content/llcache_private.h"
+#include "content/backing_store.h"
#include "desktop/download.h"
#include "desktop/gui_factory.h"
@@ -26,7 +26,6 @@
struct gui_table *guit = NULL;
-
static void gui_default_window_set_title(struct gui_window *g, const char *title)
{
}
@@ -345,51 +344,6 @@ static nserror verify_utf8_register(struct gui_utf8_table *gut)
return NSERROR_OK;
}
-static nserror
-gui_default_initialise(const struct llcache_store_parameters *parameters)
-{
- return NSERROR_OK;
-}
-
-static nserror
-gui_default_finalise(void)
-{
- return NSERROR_OK;
-}
-
-static nserror
-gui_default_store(nsurl *url,
- enum llcache_store_flags flags,
- const uint8_t *data,
- const size_t datalen)
-{
- return NSERROR_SAVE_FAILED;
-}
-
-static nserror
-gui_default_fetch(nsurl *url,
- enum llcache_store_flags *flags,
- uint8_t **data_out,
- size_t *datalen_out)
-{
- return NSERROR_NOT_FOUND;
-}
-
-static nserror
-gui_default_invalidate(nsurl *url)
-{
- return NSERROR_NOT_FOUND;
-}
-
-
-static struct gui_llcache_table default_llcache_table = {
- .initialise = gui_default_initialise,
- .finalise = gui_default_finalise,
- .store = gui_default_store,
- .fetch = gui_default_fetch,
- .invalidate = gui_default_invalidate,
-};
-
/** verify clipboard table is valid */
static nserror verify_llcache_register(struct gui_llcache_table *glt)
{
@@ -408,13 +362,11 @@ static nserror verify_llcache_register(struct gui_llcache_table *glt)
if (glt->invalidate == NULL) {
return NSERROR_BAD_PARAMETER;
}
-
- /* fill in the optional entries with defaults */
if (glt->initialise == NULL) {
- glt->initialise = gui_default_initialise;
+ return NSERROR_BAD_PARAMETER;
}
if (glt->finalise == NULL) {
- glt->finalise = gui_default_finalise;
+ return NSERROR_BAD_PARAMETER;
}
return NSERROR_OK;
@@ -613,8 +565,8 @@ nserror gui_factory_register(struct gui_table *gt)
/* llcache table */
if (gt->llcache == NULL) {
- /* set default clipboard table */
- gt->llcache = &default_llcache_table;
+ /* set default backing store table */
+ gt->llcache = default_llcache_table;
}
err = verify_llcache_register(gt->llcache);
if (err != NSERROR_OK) {
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index 1f5bc59..51de982 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -67,12 +67,18 @@
*/
#define SPECULATE_SMALL 4096
-/** the time between image cache clean runs in ms */
+/** the time between image cache clean runs in ms. */
#define IMAGE_CACHE_CLEAN_TIME (10 * 1000)
-/** default time between content cache cleans */
+/** default time between content cache cleans. */
#define HL_CACHE_CLEAN_TIME (2 * IMAGE_CACHE_CLEAN_TIME)
+/** default minimum object time before object is pushed to backing store. */
+#define LLCACHE_MIN_DISC_LIFETIME (60 * 30)
+
+/** default maximum bandwidth for backing store writeout. */
+#define LLCACHE_MAX_DISC_BANDWIDTH (128 * 1024)
+
/** ensure there is a minimal amount of memory for source objetcs and
* decoded bitmaps.
*/
@@ -126,6 +132,8 @@ nserror netsurf_init(const char *messages, struct gui_table *gt)
.bg_clean_time = HL_CACHE_CLEAN_TIME,
.llcache = {
.cb = netsurf_llcache_query_handler,
+ .minimum_lifetime = LLCACHE_MIN_DISC_LIFETIME,
+ .bandwidth = LLCACHE_MAX_DISC_BANDWIDTH,
.store = {
.hashsize = 160,
}
diff --git a/gtk/Makefile.target b/gtk/Makefile.target
index df9ac73..ec19d1b 100644
--- a/gtk/Makefile.target
+++ b/gtk/Makefile.target
@@ -110,7 +110,7 @@ S_GTK := font_pango.c bitmap.c gui.c schedule.c thumbnail.c plotters.c \
treeview.c scaffolding.c gdk.c completion.c login.c throbber.c \
selection.c history.c window.c fetch.c download.c menu.c \
print.c search.c tabs.c theme.c toolbar.c gettext.c \
- compat.c cookies.c hotlist.c llcache.c \
+ compat.c cookies.c hotlist.c \
$(addprefix dialogs/,preferences.c about.c source.c)
S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c)
diff --git a/gtk/gui.c b/gtk/gui.c
index 1e6ff4c..cf584c3 100644
--- a/gtk/gui.c
+++ b/gtk/gui.c
@@ -56,6 +56,14 @@
#include "desktop/tree.h"
#include "css/utils.h"
+#include "render/form.h"
+#include "utils/filepath.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/url.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+
#include "gtk/compat.h"
#include "gtk/completion.h"
#include "gtk/cookies.h"
@@ -69,15 +77,6 @@
#include "gtk/window.h"
#include "gtk/schedule.h"
#include "gtk/selection.h"
-#include "gtk/llcache.h"
-
-#include "render/form.h"
-#include "utils/filepath.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/url.h"
-#include "utils/utf8.h"
-#include "utils/utils.h"
char *options_file_location;
char *toolbar_indices_file_location;
@@ -1016,7 +1015,6 @@ int main(int argc, char** argv)
.clipboard = nsgtk_clipboard_table,
.download = nsgtk_download_table,
.fetch = nsgtk_fetch_table,
- .llcache = nsgtk_llcache_table,
};
/* check home directory is available */
diff --git a/gtk/llcache.h b/gtk/llcache.h
deleted file mode 100644
index 6afdfe9..0000000
--- a/gtk/llcache.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GTK_LLCACHE_H
-#define GTK_LLCACHE_H
-
-extern struct gui_llcache_table* nsgtk_llcache_table;
-
-#endif
--
NetSurf Browser
8 years, 11 months
netsurf: branch vince/llcache created. release/3.0-1147-ga0a5433
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/a0a5433b995a13eda8d6c...
...commit http://git.netsurf-browser.org/netsurf.git/commit/a0a5433b995a13eda8d6cce...
...tree http://git.netsurf-browser.org/netsurf.git/tree/a0a5433b995a13eda8d6cce2a...
The branch, vince/llcache has been created
at a0a5433b995a13eda8d6cce2afb9ee364de473ba (commit)
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=a0a5433b995a13eda8d...
commit a0a5433b995a13eda8d6cce2afb9ee364de473ba
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
add basic persistant storage implementation
diff --git a/gtk/Makefile.target b/gtk/Makefile.target
index ec19d1b..df9ac73 100644
--- a/gtk/Makefile.target
+++ b/gtk/Makefile.target
@@ -110,7 +110,7 @@ S_GTK := font_pango.c bitmap.c gui.c schedule.c thumbnail.c plotters.c \
treeview.c scaffolding.c gdk.c completion.c login.c throbber.c \
selection.c history.c window.c fetch.c download.c menu.c \
print.c search.c tabs.c theme.c toolbar.c gettext.c \
- compat.c cookies.c hotlist.c \
+ compat.c cookies.c hotlist.c llcache.c \
$(addprefix dialogs/,preferences.c about.c source.c)
S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c)
diff --git a/gtk/gui.c b/gtk/gui.c
index 40c2ad6..1e6ff4c 100644
--- a/gtk/gui.c
+++ b/gtk/gui.c
@@ -69,6 +69,7 @@
#include "gtk/window.h"
#include "gtk/schedule.h"
#include "gtk/selection.h"
+#include "gtk/llcache.h"
#include "render/form.h"
#include "utils/filepath.h"
@@ -1015,6 +1016,7 @@ int main(int argc, char** argv)
.clipboard = nsgtk_clipboard_table,
.download = nsgtk_download_table,
.fetch = nsgtk_fetch_table,
+ .llcache = nsgtk_llcache_table,
};
/* check home directory is available */
diff --git a/gtk/llcache.c b/gtk/llcache.c
new file mode 100644
index 0000000..7c6f961
--- /dev/null
+++ b/gtk/llcache.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Low-level resource cache persistant storage implementation.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "utils/nsurl.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "utils/sha1.h"
+#include "desktop/gui.h"
+#include "content/llcache_private.h"
+
+#include "gtk/llcache.h"
+
+struct llcache_store_state {
+ /** parameters controlling the backing store */
+ struct llcache_store_parameters params;
+
+ /** key to filename conversion */
+ char *(*store_fname)(nsurl *url, enum llcache_store_flags flags);
+};
+
+struct llcache_store_state *storestate;
+
+
+static uint8_t encoding_table[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '-', '_'
+};
+static unsigned int mod_table[] = {0, 2, 1};
+
+
+static uint8_t *
+base64url_encode(const char *data,
+ size_t input_length,
+ size_t *output_length)
+{
+ uint8_t *encoded_data;
+ size_t i;
+ size_t j;
+
+ *output_length = 4 * ((input_length + 2) / 3);
+
+ encoded_data = malloc(*output_length + 1);
+ if (encoded_data == NULL) {
+ return NULL;
+ }
+
+ for (i = 0, j = 0; i < input_length;) {
+
+ uint32_t octet_a = i < input_length ? data[i++] : 0;
+ uint32_t octet_b = i < input_length ? data[i++] : 0;
+ uint32_t octet_c = i < input_length ? data[i++] : 0;
+
+ uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+ encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
+ }
+
+ for (i = 0; i < mod_table[input_length % 3]; i++) {
+ encoded_data[*output_length - 1 - i] = 0;
+ (*output_length)--;
+ }
+
+ return encoded_data;
+}
+
+/**
+ * create filename from url and flags
+ *
+ * This uses 160bit sha1 and a bit from the from flags which is then
+ * base64 encoded. This yeilds a 28 character base64 encoded string
+ * (168 bits is minimum byte representation of 161 bits) where the
+ * last character can be discarded (27*6 is 162 bits)
+ */
+static char *
+b64_store_fname_sha1(nsurl *url, enum llcache_store_flags flags)
+{
+ uint8_t hash[NSSHA1_DIGEST_SIZE + 1];
+ int fname_len;
+ char *fname;
+ uint8_t *b64u;
+ size_t b64ulen;
+
+ NSSHA1((uint8_t *)nsurl_access(url), nsurl_length(url), hash);
+
+ if ((flags & LLCACHE_STORE_META) != 0) {
+ hash[NSSHA1_DIGEST_SIZE] = 0xff;
+ } else {
+ hash[NSSHA1_DIGEST_SIZE] = 0;
+ }
+
+ b64u = base64url_encode((char *)hash, NSSHA1_DIGEST_SIZE + 1, &b64ulen);
+ if (b64u == NULL) {
+ return NULL;
+ }
+ b64u[27] = 0;
+ LOG(("b64u len:%d from %d with \"%s\"", b64ulen, NSSHA1_DIGEST_SIZE + 1, b64u));
+ fname_len = strlen(storestate->params.path) + 31;
+ fname = calloc(1, fname_len);
+ if (fname == NULL) {
+ free(b64u);
+ return NULL;
+ }
+
+ snprintf(fname,
+ fname_len,
+ "%s/%c%c/%s",
+ storestate->params.path,
+ b64u[0], b64u[1], b64u + 2 );
+ free(b64u);
+
+ return fname;
+}
+
+/**
+ * Create filename from url and flags
+ *
+ * This uses 17bits from the fnv url hash and one bit from the
+ * flags. Yeilding data in 3 bytes which is base64 encoded, the fourth
+ * character (last 6 bits) of the base 64 encoding is not used as it is
+ * empty.
+ */
+static char *
+b64_store_fname_fnv(nsurl *url, enum llcache_store_flags flags)
+{
+ uint32_t hash;
+ char *hashp;
+ int fname_len;
+ char *fname;
+ uint8_t *b64u;
+ size_t b64ulen;
+
+ hash = nsurl_hash(url);
+
+ hashp = (char *)&hash;
+
+ hashp[2] = hashp[2] & 0x80;
+
+ if ((flags & LLCACHE_STORE_META) != 0) {
+ hashp[2] = hashp[2] | 0x40;
+ }
+
+ b64u = base64url_encode(hashp, 3, &b64ulen);
+ if (b64u == NULL) {
+ return NULL;
+ }
+
+ fname_len = strlen(storestate->params.path) + 7;
+ fname = calloc(1, fname_len);
+ if (fname == NULL) {
+ free(b64u);
+ return NULL;
+ }
+
+ snprintf(fname,
+ fname_len,
+ "%s/%c/%c/%c",
+ storestate->params.path,
+ b64u[0], b64u[1], b64u[2]);
+ free(b64u);
+
+ return fname;
+}
+
+/**
+ * create filename from url and flags
+ *
+ * no hashing, just base64 encode the url
+ */
+static char *
+b64_store_fname(nsurl *url, enum llcache_store_flags flags)
+{
+ char *fname;
+ uint8_t *b64u;
+ size_t b64ulen;
+ char sep;
+
+ b64u = base64url_encode(nsurl_access(url),
+ strlen(nsurl_access(url)),
+ &b64ulen);
+ if (b64u == NULL) {
+ return NULL;
+ }
+
+ fname = malloc(strlen(storestate->params.path) +
+ SLEN("/x") + b64ulen + 1);
+ if (fname == NULL) {
+ free(b64u);
+ return NULL;
+ }
+
+ if ((flags & LLCACHE_STORE_META) == 0) {
+ sep ='d';
+ } else {
+ sep ='i';
+ }
+
+ snprintf(fname,
+ (strlen(storestate->params.path) + SLEN("/x") + b64ulen + 1),
+ "%s/%s%c",
+ storestate->params.path,
+ b64u,
+ sep);
+ free(b64u);
+
+ return fname;
+}
+
+/* backing store implementation */
+
+/**
+ * Initialise the backing store.
+ *
+ * @param parameters to configure backing store.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+initialise(const struct llcache_store_parameters *parameters)
+{
+ /* check backing store is not already initialised */
+ if (storestate != NULL) {
+ return NSERROR_INIT_FAILED;
+ }
+
+ storestate = calloc(1, sizeof(struct llcache_store_state));
+ if (storestate == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ memcpy(&storestate->params,
+ parameters,
+ sizeof(struct llcache_store_parameters));
+
+ if (storestate->params.hashsize == 0) {
+ storestate->store_fname = b64_store_fname;
+ } else if (storestate->params.hashsize < 32) {
+ storestate->store_fname = b64_store_fname_fnv;
+ } else {
+ storestate->store_fname = b64_store_fname_sha1;
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * Finalise the backing store.
+ *
+ * @return NSERROR_OK on success.
+ */
+static nserror
+finalise(void)
+{
+ if (storestate != NULL) {
+ free(storestate);
+ storestate = NULL;
+ }
+ return NSERROR_OK;
+}
+
+/* ensure that all directory elements needed to store a filename exist */
+static nserror mkfilepath(const char *fname)
+{
+ char *dname;
+ char *sep;
+ struct stat sb;
+
+ dname = strdup(fname);
+
+ sep = strrchr(dname, '/');
+ if (sep == NULL) {
+ /* no directory separator path is just filename so its ok */
+ free(dname);
+ return NSERROR_OK;
+ }
+
+ *sep = 0; /* null terminate directory path */
+
+ if (stat(dname, &sb) == 0) {
+ free(dname);
+ if (S_ISDIR(sb.st_mode)) {
+ /* path to file exists and is a directory */
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_FOUND;
+ }
+ *sep = '/'; /* restore separator */
+
+ sep = dname;
+ while (*sep == '/') {
+ sep++;
+ }
+ while ((sep = strchr(sep, '/')) != NULL) {
+ *sep = 0;
+ if (stat(dname, &sb) != 0) {
+ if (mkdir(dname, 0700) != 0) {
+ /* could not create path element */
+ free(dname);
+ return NSERROR_NOT_FOUND;
+ }
+ } else {
+ if (! S_ISDIR(sb.st_mode)) {
+ /* path element not a directory */
+ free(dname);
+ return NSERROR_NOT_FOUND;
+ }
+ }
+ *sep = '/'; /* restore separator */
+ /* skip directory separators */
+ while (*sep == '/') {
+ sep++;
+ }
+ }
+
+ free(dname);
+ return NSERROR_OK;
+}
+
+/**
+ * Place a source object and its metadata in the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the object is stored.
+ * @param data The objects source data.
+ * @param datalen The length of the \a data.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+store(nsurl *url,
+ enum llcache_store_flags flags,
+ const uint8_t *data,
+ const size_t datalen)
+{
+ char *fname;
+ FILE *file;
+ nserror ret;
+
+ LOG(("Writing object for url:%s", nsurl_access(url)));
+ fname = storestate->store_fname(url, flags);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* ensure path to file is usable */
+ ret = mkfilepath(fname);
+ if (ret != NSERROR_OK) {
+ LOG(("file path \"%s\" could not be created", fname));
+ free(fname);
+ return ret;
+ }
+
+ LOG(("Opening data file %s", fname));
+ file = fopen(fname, "wb");
+ free(fname);
+ if (file == NULL) {
+ return NSERROR_SAVE_FAILED;
+ }
+
+ LOG(("Writing %d bytes from %p", datalen, data));
+ if (fwrite(data, datalen, 1, file) != 1) {
+ LOG(("did not return 1"));
+ fclose(file);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ fclose(file);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Retrive an object from the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the object is stored.
+ * @param data The objects data.
+ * @param datalen The length of the \a data retrieved.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+fetch(nsurl *url,
+ enum llcache_store_flags *flags,
+ uint8_t **data_out,
+ size_t *datalen_out)
+{
+ char *fname;
+ FILE *file;
+ uint8_t *data;
+ size_t datalen;
+
+ data = *data_out;
+ datalen = *datalen_out;
+
+ LOG(("retriving cache file for url:%s", nsurl_access(url)));
+
+ fname = storestate->store_fname(url, *flags);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ LOG(("Opening file %s",fname));
+
+ file = fopen(fname, "rb");
+ free(fname);
+ if (file == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* need to deal with buffers */
+ if (data == NULL) {
+ if (datalen == 0) {
+ /* caller did not know the files length */
+ fseek(file, 0L, SEEK_END);
+ datalen = ftell(file);
+ fseek(file, 0L, SEEK_SET);
+ }
+
+ data = malloc(datalen);
+ if (data == NULL) {
+ fclose(file);
+ return NSERROR_NOMEM;
+ }
+ }
+
+ LOG(("Reading %d bytes into %p from file", datalen, data));
+ if (fread(data, datalen, 1, file) != 1) {
+ LOG(("did not return 1"));
+ fclose(file);
+ if ((*data_out) == NULL) {
+ free(data);
+ }
+ return NSERROR_NOT_FOUND;
+ }
+
+ fclose(file);
+
+ *data_out = data;
+ *datalen_out = datalen;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Invalidate a source object from the backing store.
+ *
+ * The entry (if present in the backing store) must no longer
+ * be returned as a result to the fetch or meta operations.
+ *
+ * @param url The url is used as the unique primary key to invalidate.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+static nserror
+invalidate(nsurl *url)
+{
+ char *fname;
+ fname = storestate->store_fname(url, LLCACHE_STORE_META);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ unlink(fname);
+ free(fname);
+
+ fname = storestate->store_fname(url, LLCACHE_STORE_NONE);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ unlink(fname);
+ free(fname);
+
+ return NSERROR_OK;
+}
+
+
+static struct gui_llcache_table llcache_table = {
+ .initialise = initialise,
+ .finalise = finalise,
+ .store = store,
+ .fetch = fetch,
+ .invalidate = invalidate,
+};
+
+struct gui_llcache_table *nsgtk_llcache_table = &llcache_table;
diff --git a/gtk/llcache.h b/gtk/llcache.h
new file mode 100644
index 0000000..6afdfe9
--- /dev/null
+++ b/gtk/llcache.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTK_LLCACHE_H
+#define GTK_LLCACHE_H
+
+extern struct gui_llcache_table* nsgtk_llcache_table;
+
+#endif
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=a9dd342d4b96c2d5902...
commit a9dd342d4b96c2d59023b343d7a4b4489756918e
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
add sha1 implementation and tests
diff --git a/test/Makefile b/test/Makefile
index acf9d4e..825b582 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,6 +2,7 @@ CFLAGS := -std=c99 -g -O0 -D_BSD_SOURCE -D_POSIX_C_SOURCE -I.. \
$(shell pkg-config --cflags libcurl)
LDFLAGS := $(shell pkg-config --libs libcurl) -lz
+
llcache_CFLAGS := $(shell pkg-config --cflags libparserutils libwapcaplet libdom) -O2
llcache_LDFLAGS := $(shell pkg-config --libs libparserutils libwapcaplet libdom)
@@ -14,6 +15,7 @@ llcache_SRCS := content/fetch.c content/fetchers/curl.c \
utils/log.c utils/nsurl.c utils/messages.c utils/url.c \
utils/useragent.c utils/utils.c test/llcache.c
+
urldbtest_SRCS := content/urldb.c utils/url.c utils/utils.c utils/log.c \
desktop/options.c utils/messages.c utils/hashtable.c \
utils/filename.c utils/nsurl.c utils/corestrings.c \
@@ -22,16 +24,22 @@ urldbtest_SRCS := content/urldb.c utils/url.c utils/utils.c utils/log.c \
urldbtest_CFLAGS := $(shell pkg-config --cflags libwapcaplet libdom) -O2
urldbtest_LDFLAGS := $(shell pkg-config --libs libwapcaplet libdom)
+
nsurl_SRCS := utils/corestrings.c utils/log.c utils/nsurl.c test/nsurl.c
nsurl_CFLAGS := $(shell pkg-config --cflags libwapcaplet libdom)
nsurl_LDFLAGS := $(shell pkg-config --libs libwapcaplet libdom)
+
nsoption_SRCS := utils/log.c utils/nsoption.c test/nsoption.c
nsoption_CFLAGS := -Dnsgtk
+sha1_SRCS := utils/sha1.c utils/log.c test/sha1.c
+sha1_CFLAGS :=
+sha1_LDFLAGS :=
+
.PHONY: all
-all: llcache urldbtest nsurl nsoption
+all: llcache urldbtest nsurl nsoption sha1
llcache: $(addprefix ../,$(llcache_SRCS))
$(CC) $(CFLAGS) $(llcache_CFLAGS) $^ -o $@ $(LDFLAGS) $(llcache_LDFLAGS)
@@ -45,6 +53,9 @@ nsurl: $(addprefix ../,$(nsurl_SRCS))
nsoption: $(addprefix ../,$(nsoption_SRCS))
$(CC) $(CFLAGS) $(nsoption_CFLAGS) $^ -o $@ $(LDFLAGS) $(nsoption_LDFLAGS)
+sha1: $(addprefix ../,$(sha1_SRCS))
+ $(CC) $(CFLAGS) $(sha1_CFLAGS) $^ -o $@ $(LDFLAGS) $(sha1_LDFLAGS)
+
.PHONY: clean
clean:
diff --git a/test/sha1.c b/test/sha1.c
new file mode 100644
index 0000000..be31836
--- /dev/null
+++ b/test/sha1.c
@@ -0,0 +1,55 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "utils/log.h"
+#include "utils/sha1.h"
+
+
+struct {
+ const char *text;
+ const uint8_t hash[NSSHA1_DIGEST_SIZE];
+} checks[] = {
+ {
+ "The quick brown fox jumps over the lazy dog",
+ { 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84,
+ 0x9e, 0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12 }
+ },
+ {
+ "The quick brown fox jumps over the lazy cog",
+ { 0xde, 0x9f, 0x2c, 0x7f, 0xd2, 0x5e, 0x1b, 0x3a, 0xfa, 0xd3,
+ 0xe8, 0x5a, 0x0b, 0xd1, 0x7d, 0x9b, 0x10, 0x0d, 0xb4, 0xb3 }
+ },
+ {
+ "",
+ { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
+ 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 }
+ },
+ {
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
+ { 0x29, 0xb0, 0xe7, 0x87, 0x82, 0x71, 0x64, 0x5f, 0xff, 0xb7,
+ 0xee, 0xc7, 0xdb, 0x4a, 0x74, 0x73, 0xa1, 0xc0, 0x0b, 0xc1 }
+ },
+ { NULL, {0} },
+};
+
+int main(int argc, char **argv)
+{
+ uint8_t res[NSSHA1_DIGEST_SIZE];
+ int chk_loop = 0;
+
+ verbose_log = true;
+
+ while (checks[chk_loop].text != NULL) {
+
+ NSSHA1(checks[chk_loop].text, strlen(checks[chk_loop].text), res);
+ if (memcmp(res, &checks[chk_loop].hash, NSSHA1_DIGEST_SIZE) == 0) {
+ LOG(("Test %d: PASS", chk_loop));
+ } else {
+ LOG(("Test %d: FAIL", chk_loop));
+ }
+ chk_loop++;
+ }
+}
diff --git a/utils/Makefile b/utils/Makefile
index aef5799..48bba98 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -2,6 +2,6 @@
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
- utf8.c utils.c useragent.c bloom.c nsoption.c
+ utf8.c utils.c useragent.c bloom.c nsoption.c sha1.c
S_UTILS := $(addprefix utils/,$(S_UTILS))
diff --git a/utils/sha1.c b/utils/sha1.c
new file mode 100644
index 0000000..e59c8ed
--- /dev/null
+++ b/utils/sha1.c
@@ -0,0 +1,267 @@
+/*
+ SHA-1 in C
+ By Steve Reid <sreid(a)sea-to-sky.net>
+ 100% Public Domain
+
+ -----------------
+ Modified 7/98
+ By James H. Brown <jbrown(a)burgoyne.com>
+ Still 100% Public Domain
+
+ Corrected a problem which generated improper hash values on 16 bit machines
+ Routine SHA1Update changed from
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+ len)
+ to
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+ long len)
+
+ The 'len' parameter was declared an int which works fine on 32 bit machines.
+ However, on 16 bit machines an int is too small for the shifts being done
+ against
+ it. This caused the hash function to generate incorrect values if len was
+ greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+ Since the file IO in main() reads 16K at a time, any file 8K or larger would
+ be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+ "a"s).
+
+ I also changed the declaration of variables i & j in SHA1Update to
+ unsigned long from unsigned int for the same reason.
+
+ These changes should make no difference to any 32 bit implementations since
+ an
+ int and a long are the same size in those environments.
+
+ --
+ I also corrected a few compiler warnings generated by Borland C.
+ 1. Added #include <process.h> for exit() prototype
+ 2. Removed unused variable 'j' in SHA1Final
+ 3. Changed exit(0) to return(0) at end of main.
+
+ ALL changes I made can be located by searching for comments containing 'JHB'
+ -----------------
+ Modified 8/98
+ By Steve Reid <sreid(a)sea-to-sky.net>
+ Still 100% public domain
+
+ 1- Removed #include <process.h> and used return() instead of exit()
+ 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+ 3- Changed email address from steve(a)edmweb.com to sreid(a)sea-to-sky.net
+
+ -----------------
+ Modified 4/01
+ By Saul Kravitz <Saul.Kravitz(a)celera.com>
+ Still 100% PD
+ Modified to run on Compaq Alpha hardware.
+
+ -----------------
+ Modified 07/2002
+ By Ralph Giles <giles(a)ghostscript.com>
+ Still 100% public domain
+ modified for use with stdint types, autoconf
+ code cleanup, removed attribution comments
+ switched SHA1Final() argument order for consistency
+ use SHA1_ prefix for public api
+ move public api to sha1.h
+*/
+
+/** \file
+ * steve reid's public domain SHA-1 implementation.
+ *
+ * Modified by Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This is a sligly modified version of this public domain
+ * implementation changes were made to:
+ * - introduce suitable prefixes to avoid namespace conflicts.
+ * - make the context structure self contained.
+ * - make the function signatures more suitable for this use case
+ */
+
+
+/* see https://en.wikipedia.org/wiki/SHA-1 */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/sha1.h"
+
+struct nssha1_ctx {
+ uint32_t state[5];
+ uint32_t count[2];
+ uint8_t buffer[64];
+} ;
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+/* FIXME: can we do this in an endian-proof way? */
+#ifdef WORDS_BIGENDIAN
+#define blk0(i) block->l[i]
+#else
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
+{
+ uint32_t a, b, c, d, e;
+
+ typedef union {
+ uint8_t c[64];
+ uint32_t l[16];
+ } CHAR64LONG16;
+ CHAR64LONG16* block;
+
+ static uint8_t workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+nserror
+NSSHA1_Init(struct nssha1_ctx **ret_ctx)
+{
+ struct nssha1_ctx *context;
+
+ context = calloc(1, sizeof(struct nssha1_ctx));
+ if (context == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+
+ *ret_ctx = context;
+
+ return NSERROR_OK;
+}
+
+
+/* Run your data through this. */
+nserror
+NSSHA1_Update(struct nssha1_ctx *context, const uint8_t *data, const size_t len)
+{
+ size_t i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) {
+ context->count[1]++;
+ }
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1_Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1_Transform(context->state, data + i);
+ }
+ j = 0;
+ } else {
+ i = 0;
+ }
+ memcpy(&context->buffer[j], &data[i], len - i);
+
+ return NSERROR_OK;
+}
+
+
+/* Add padding and return the message digest. */
+nserror
+NSSHA1_Final(struct nssha1_ctx *context, uint8_t digest[NSSHA1_DIGEST_SIZE])
+{
+ uint32_t i;
+ uint8_t finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ NSSHA1_Update(context, (uint8_t *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ NSSHA1_Update(context, (uint8_t *)"\0", 1);
+ }
+ NSSHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
+ for (i = 0; i < NSSHA1_DIGEST_SIZE; i++) {
+ digest[i] = (uint8_t)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+
+ free(context);
+
+ return NSERROR_OK;
+}
+
+nserror
+NSSHA1(const uint8_t *data, const size_t len, uint8_t digest[NSSHA1_DIGEST_SIZE])
+{
+ struct nssha1_ctx *context;
+ nserror error;
+
+ error = NSSHA1_Init(&context);
+ if (error != NSERROR_OK)
+ return error;
+ NSSHA1_Update(context, data, len);
+ NSSHA1_Final(context, digest);
+
+ return NSERROR_OK;
+}
diff --git a/utils/sha1.h b/utils/sha1.h
new file mode 100644
index 0000000..e9f930c
--- /dev/null
+++ b/utils/sha1.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * interface for steve reid's public domain SHA-1 implementation.
+ *
+ * The exposed API makes only minimal changes to the public domain
+ * implementation, mainly adding a prefix so this implementation is
+ * not confused with any other similarly named version that might be
+ * linked.
+ */
+
+#ifndef _NETSURF_UTILS_SHA1_H_
+#define _NETSURF_UTILS_SHA1_H_
+
+struct nssha1_ctx;
+
+#define NSSHA1_DIGEST_SIZE 20
+
+/**
+ * Initialise a SHA1 context ready to take updates
+ *
+ * The context is allocated by this routine and destroyed by the finaliser.
+ *
+ * @param context receives an initialised SHA1 context.
+ * @return NSERROR_OK and \a context updated on sucess or
+ * NSERROR_NOMEM on memory exhaustion.
+ */
+nserror NSSHA1_Init(struct nssha1_ctx **context);
+
+/**
+ * Update an SHA1 context with additional data.
+ *
+ * @param context The context created by NSSHA1_Init
+ * @param data The data to hash.
+ * @param len The length of data to hash.
+ * @return NSERROR_OK
+ */
+nserror NSSHA1_Update(struct nssha1_ctx *context, const uint8_t *data, const size_t len);
+
+/**
+ * Finalise a SHA1 hash.
+ *
+ * Frees the context.
+ *
+ * @param context The context created by NSSHA1_Init
+ * @param digest a buffer to store the results in.
+ * @return NSERROR_OK
+ */
+nserror NSSHA1_Final(struct nssha1_ctx *context, uint8_t digest[NSSHA1_DIGEST_SIZE]);
+
+/**
+ * Generate SHA1 of some data
+ */
+nserror NSSHA1(const uint8_t *data, const size_t len, uint8_t digest[NSSHA1_DIGEST_SIZE]);
+
+#endif
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=7ef5e920c4be328fabd...
commit 7ef5e920c4be328fabda9dfc7e8ae2c7e6fb4ab9
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
Extend low level source data cache with persistant storage
diff --git a/content/hlcache.c b/content/hlcache.c
index 16f9697..86d5113 100644
--- a/content/hlcache.c
+++ b/content/hlcache.c
@@ -339,9 +339,10 @@ static nserror hlcache_migrate_ctx(hlcache_retrieval_ctx *ctx,
ctx->migrate_target = true;
- if (effective_type != NULL &&
- hlcache_type_is_acceptable(effective_type,
- ctx->accepted_types, &type)) {
+ if ((effective_type != NULL) &&
+ hlcache_type_is_acceptable(effective_type,
+ ctx->accepted_types,
+ &type)) {
error = hlcache_find_content(ctx, effective_type);
if (error != NSERROR_OK && error != NSERROR_NEED_DATA) {
if (ctx->handle->cb != NULL) {
@@ -524,9 +525,7 @@ hlcache_initialise(const struct hlcache_parameters *hlcache_parameters)
return NSERROR_NOMEM;
}
- ret = llcache_initialise(hlcache_parameters->cb,
- hlcache_parameters->cb_ctx,
- hlcache_parameters->limit);
+ ret = llcache_initialise(&hlcache_parameters->llcache);
if (ret != NSERROR_OK) {
free(hlcache);
hlcache = NULL;
diff --git a/content/hlcache.h b/content/hlcache.h
index 41f1ed6..746b3c8 100644
--- a/content/hlcache.h
+++ b/content/hlcache.h
@@ -23,11 +23,12 @@
#ifndef NETSURF_CONTENT_HLCACHE_H_
#define NETSURF_CONTENT_HLCACHE_H_
-#include "content/content.h"
-#include "content/llcache.h"
#include "utils/errors.h"
#include "utils/nsurl.h"
+#include "content/content.h"
+#include "content/llcache.h"
+
/** High-level cache handle */
typedef struct hlcache_handle hlcache_handle;
@@ -44,18 +45,10 @@ typedef struct {
} hlcache_event;
struct hlcache_parameters {
- llcache_query_callback cb; /**< Query handler for llcache */
- void *cb_ctx; /**< Pointer to llcache query handler data */
-
/** How frequently the background cache clean process is run (ms) */
unsigned int bg_clean_time;
- /** The target upper bound for the cache size */
- size_t limit;
-
- /** The hysteresis allowed round the target size */
- size_t hysteresis;
-
+ struct llcache_parameters llcache;
};
/**
@@ -67,13 +60,13 @@ struct hlcache_parameters {
* \return NSERROR_OK on success, appropriate error otherwise.
*/
typedef nserror (*hlcache_handle_callback)(hlcache_handle *handle,
- const hlcache_event *event, void *pw);
+ const hlcache_event *event, void *pw);
/** Flags for high-level cache object retrieval */
enum hlcache_retrieve_flag {
- /* Note: low-level cache retrieval flags occupy the bottom 16 bits of
- * the flags word. High-level cache flags occupy the top 16 bits.
- * To avoid confusion, high-level flags are allocated from bit 31 down.
+ /* Note: low-level cache retrieval flags occupy the bottom 16 bits of
+ * the flags word. High-level cache flags occupy the top 16 bits.
+ * To avoid confusion, high-level flags are allocated from bit 31 down.
*/
/** It's permitted to convert this request into a download */
HLCACHE_RETRIEVE_MAY_DOWNLOAD = (1 << 31),
@@ -84,7 +77,7 @@ enum hlcache_retrieve_flag {
/**
* Initialise the high-level cache, preparing the llcache also.
*
- * \param hlcache_parameters Settings to initialise cache with
+ * \param hlcache_parameters Settings to initialise cache with
* \return NSERROR_OK on success, appropriate error otherwise.
*/
nserror hlcache_initialise(const struct hlcache_parameters *hlcache_parameters);
@@ -133,7 +126,7 @@ nserror hlcache_poll(void);
nserror hlcache_handle_retrieve(nsurl *url, uint32_t flags,
nsurl *referer, llcache_post_data *post,
hlcache_handle_callback cb, void *pw,
- hlcache_child_context *child,
+ hlcache_child_context *child,
content_type accepted_types, hlcache_handle **result);
/**
@@ -169,13 +162,13 @@ nserror hlcache_handle_replace_callback(hlcache_handle *handle,
* \param handle Cache handle to dereference
* \return Pointer to content object, or NULL if there is none
*
- * \todo This may not be correct. Ideally, the client should never need to
- * directly access a content object. It may, therefore, be better to provide a
- * bunch of veneers here that take a hlcache_handle and invoke the
+ * \todo This may not be correct. Ideally, the client should never need to
+ * directly access a content object. It may, therefore, be better to provide a
+ * bunch of veneers here that take a hlcache_handle and invoke the
* corresponding content_ API. If there's no content object associated with the
- * hlcache_handle (e.g. because the source data is still being fetched, so it
- * doesn't exist yet), then these veneers would behave as a NOP. The important
- * thing being that the client need not care about this possibility and can
+ * hlcache_handle (e.g. because the source data is still being fetched, so it
+ * doesn't exist yet), then these veneers would behave as a NOP. The important
+ * thing being that the client need not care about this possibility and can
* just call the functions with impugnity.
*/
struct content *hlcache_handle_get_content(const hlcache_handle *handle);
diff --git a/content/llcache.c b/content/llcache.c
index 112a7fa..5c6a560 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -17,26 +17,51 @@
*/
/** \file
- * Low-level resource cache (implementation)
+ * Low-level resource cache implementation
+ *
+ * This is the implementation of the low level cache. This cache
+ * stores source objects in memory and may use a persistant backing
+ * store to extend their lifetime.
+ *
+ * \todo fix writeout conditions and ordering.
+ *
+ * \todo support mmaped retrieve
+ *
+ * \todo instrument and (auto)tune
+ *
+ * \todo turn llcache debugging off
+ *
+ * \todo implement expiry from backing store of objects not currently
+ * in cache lists.
+ *
+ * \todo make backing store size bounded by configuration
+ *
+ * \todo make backing store have an index to improve performance
+ *
+ * \todo make backing store have a more efficient metadata store.
+ *
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
-
#include <curl/curl.h>
-#include "content/fetch.h"
-#include "content/llcache.h"
-#include "content/urldb.h"
#include "utils/corestrings.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsurl.h"
#include "utils/utils.h"
+#include "utils/schedule.h"
+#include "desktop/gui_factory.h"
+
+#include "content/fetch.h"
+#include "content/llcache_private.h"
+#include "content/urldb.h"
/** Define to enable tracing of llcache operations. */
-#undef LLCACHE_TRACE
+//#undef LLCACHE_TRACE
+#define LLCACHE_TRACE 1
#ifdef LLCACHE_TRACE
#define LLCACHE_LOG(x) LOG(x)
@@ -44,6 +69,9 @@
#define LLCACHE_LOG(x)
#endif
+#define LLCACHE_MIN_DISC_LIFETIME 3600
+#define LLCACHE_MAX_DISC_BANDWIDTH (512*1024)
+
/** State of a low-level cache object fetch */
typedef enum {
LLCACHE_FETCH_INIT, /**< Initial state, before fetch */
@@ -96,19 +124,23 @@ typedef struct {
bool outstanding_query; /**< Waiting for a query response */
} llcache_fetch_ctx;
+/** validation control */
typedef enum {
LLCACHE_VALIDATE_FRESH, /**< Only revalidate if not fresh */
LLCACHE_VALIDATE_ALWAYS, /**< Always revalidate */
LLCACHE_VALIDATE_ONCE /**< Revalidate once only */
} llcache_validate;
+/** cache control value for invalid age */
+#define INVALID_AGE -1
+
/** Cache control data */
typedef struct {
time_t req_time; /**< Time of request */
time_t res_time; /**< Time of response */
+ time_t fin_time; /**< Time of request completion */
time_t date; /**< Date: response header */
time_t expires; /**< Expires: response header */
-#define INVALID_AGE -1
int age; /**< Age: response header */
int max_age; /**< Max-Age Cache-control parameter */
llcache_validate no_cache; /**< No-Cache Cache-control parameter */
@@ -122,31 +154,49 @@ typedef struct {
char *value; /**< Header value */
} llcache_header;
+/** Current status of objects data */
+typedef enum {
+ LLCACHE_STATE_RAM = 0, /**< source data is stored in RAM only */
+ LLCACHE_STATE_MMAP, /**< source data is mmaped (implies on disc too) */
+ LLCACHE_STATE_DISC, /**< source data is stored on disc */
+} llcache_store_state;
+
/** Low-level cache object */
/** \todo Consider whether a list is a sane container */
struct llcache_object {
- llcache_object *prev; /**< Previous in list */
- llcache_object *next; /**< Next in list */
+ llcache_object *prev; /**< Previous in list */
+ llcache_object *next; /**< Next in list */
- nsurl *url; /**< Post-redirect URL for object */
+ nsurl *url; /**< Post-redirect URL for object */
/** \todo We need a generic dynamic buffer object */
- uint8_t *source_data; /**< Source data for object */
- size_t source_len; /**< Byte length of source data */
- size_t source_alloc; /**< Allocated size of source buffer */
+ uint8_t *source_data; /**< Source data for object */
+ size_t source_len; /**< Byte length of source data */
+ size_t source_alloc; /**< Allocated size of source buffer */
+
+ llcache_store_state store_state; /**< where the data for the object is stored */
- llcache_object_user *users; /**< List of users */
+ llcache_object_user *users; /**< List of users */
- llcache_fetch_ctx fetch; /**< Fetch context for object */
+ llcache_fetch_ctx fetch; /**< Fetch context for object */
- llcache_cache_control cache; /**< Cache control data for object */
- llcache_object *candidate; /**< Object to use, if fetch determines
- * that it is still fresh */
- uint32_t candidate_count; /**< Count of objects this is a
- * candidate for */
+ llcache_cache_control cache; /**< Cache control data for object */
+ llcache_object *candidate; /**< Object to use, if fetch determines
+ * that it is still fresh
+ */
+ uint32_t candidate_count; /**< Count of objects this is a
+ * candidate for
+ */
- llcache_header *headers; /**< Fetch headers */
- size_t num_headers; /**< Number of fetch headers */
+ llcache_header *headers; /**< Fetch headers */
+ size_t num_headers; /**< Number of fetch headers */
+
+ /* Instrumentation. These elemnts are strictly for information
+ * to improve the cache performance and to provide performace
+ * metrics. The values are non-authorative and must not be used to
+ * determine object lifetime etc.
+ */
+ time_t last_used; /**< time the last user was removed from the object */
};
struct llcache_s {
@@ -261,6 +311,11 @@ static nserror llcache_object_remove_user(llcache_object *object,
user->next = user->prev = NULL;
+ /* record the time the last user was removed from the object */
+ if (object->users == NULL) {
+ object->last_used = time(NULL);
+ }
+
LLCACHE_LOG(("Removing user %p from %p", user, object));
return NSERROR_OK;
@@ -711,6 +766,7 @@ static nserror llcache_object_refetch(llcache_object *object)
/* Reset cache control data */
llcache_invalidate_cache_control_data(object);
object->cache.req_time = time(NULL);
+ object->cache.fin_time = object->cache.req_time;
/* Reset fetch state */
object->fetch.state = LLCACHE_FETCH_INIT;
@@ -957,6 +1013,7 @@ static nserror llcache_object_clone_cache_data(llcache_object *source,
destination->cache.req_time = source->cache.req_time;
destination->cache.res_time = source->cache.res_time;
+ destination->cache.fin_time = source->cache.fin_time;
if (source->cache.date != 0)
destination->cache.date = source->cache.date;
@@ -980,6 +1037,360 @@ static nserror llcache_object_clone_cache_data(llcache_object *source,
}
/**
+ * Remove a low-level cache object from a cache list
+ *
+ * \param object Object to remove
+ * \param list List to remove from
+ * \return NSERROR_OK
+ */
+static nserror
+llcache_object_remove_from_list(llcache_object *object, llcache_object **list)
+{
+ if (object == *list)
+ *list = object->next;
+ else
+ object->prev->next = object->next;
+
+ if (object->next != NULL)
+ object->next->prev = object->prev;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Retrieve source data for an object from persistant store if necessary.
+ *
+ * If an objects source data has been placed in the persistant store
+ * and the in memory copy freed this will attempt to retrive the
+ * source data.
+ *
+ * @param object the object to operate on.
+ * @return apropriate error code.
+ */
+static nserror llcache_persist_retrieve(llcache_object *object)
+{
+ enum llcache_store_flags flags = LLCACHE_STORE_NONE;
+
+ /* ensure the source data is present if necessary */
+ if ((object->source_data != NULL) ||
+ (object->store_state != LLCACHE_STATE_DISC)) {
+ /* source data does not require retriving from
+ * persistant store.
+ */
+ return NSERROR_OK;
+ }
+
+ /* Source data for the object may be in the persiatant store */
+ return guit->llcache->fetch(object->url,
+ &flags,
+ &object->source_data,
+ &object->source_len);
+}
+
+/**
+ * Generate a serialised version of an objects metadata
+ *
+ * metadata includes object headers
+ */
+static nserror
+llcache_serialise_metadata(llcache_object *object,
+ uint8_t **data_out,
+ size_t *datasize_out)
+{
+ size_t allocsize;
+ int datasize;
+ uint8_t *data;
+ char *op;
+ unsigned int hloop;
+ int use;
+ struct tm *ltm;
+
+ allocsize = 10 + 1; /* object length */
+
+ allocsize += 10 + 1; /* request time */
+
+ allocsize += 10 + 1; /* response time */
+
+ allocsize += 10 + 1; /* completion time */
+
+ allocsize += 10 + 1; /* space for number of header entries */
+
+ allocsize += nsurl_length(object->url) + 1;
+
+ for (hloop = 0 ; hloop < object->num_headers ; hloop++) {
+ allocsize += strlen(object->headers[hloop].name) + 1;
+ allocsize += strlen(object->headers[hloop].value) + 1;
+ }
+
+ data = malloc(allocsize);
+ if (data == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ op = (char *)data;
+ datasize = allocsize;
+
+ /* the url, used for checking for collisions */
+ use = snprintf(op, datasize, "%s%c", nsurl_access(object->url), 0);
+ if (use > datasize)
+ goto overflow;
+ op += use;
+ datasize -= use;
+
+ /* object size */
+ use = snprintf(op, datasize, "%zu%c", object->source_len, 0);
+ if (use > datasize)
+ goto overflow;
+ op += use;
+ datasize -= use;
+
+ /* Time of request */
+ ltm = localtime(&object->cache.req_time);
+ use = strftime(op, datasize, "%s", ltm);
+ if (use == 0)
+ goto overflow;
+ use++; /* does not count the null */
+ op += use;
+ datasize -= use;
+
+ /* Time of response */
+ ltm = localtime(&object->cache.res_time);
+ use = strftime(op, datasize, "%s", ltm);
+ if (use == 0)
+ goto overflow;
+ use++; /* does not count the null */
+ op += use;
+ datasize -= use;
+
+ /* Time of completion */
+ ltm = localtime(&object->cache.fin_time);
+ use = strftime(op, datasize, "%s", ltm);
+ if (use == 0)
+ goto overflow;
+ use++; /* does not count the null */
+ op += use;
+ datasize -= use;
+
+ /* number of headers */
+ use = snprintf(op, datasize, "%zu%c", object->num_headers, 0);
+ if (use > datasize)
+ goto overflow;
+ op += use;
+ datasize -= use;
+
+ /* headers */
+ for (hloop = 0 ; hloop < object->num_headers ; hloop++) {
+ use = snprintf(op, datasize,
+ "%s:%s%c",
+ object->headers[hloop].name,
+ object->headers[hloop].value,
+ 0);
+ if (use > datasize)
+ goto overflow;
+ op += use;
+ datasize -= use;
+ }
+
+ LLCACHE_LOG(("Filled buffer with %d spare", datasize));
+
+ *data_out = data;
+ *datasize_out = allocsize - datasize;
+
+ return NSERROR_OK;
+
+overflow:
+ /* somehow we overflowed the buffer - hth? */
+ LOG(("Overflowed metadata buffer"));
+ free(data);
+ return NSERROR_INVALID;
+}
+
+/**
+ * un-serialise an objects metadata.
+ */
+static nserror
+llcache_process_metadata(llcache_object *object)
+{
+ nserror res;
+ uint8_t *metadata = NULL;
+ size_t metadatalen = 0;
+ nsurl *metadataurl;
+ unsigned int line;
+ uint8_t *end;
+ char *ln;
+ int lnsize;
+ size_t num_headers;
+ size_t hloop;
+ struct tm ltm;
+ enum llcache_store_flags flags = LLCACHE_STORE_META;
+
+ /* attempt to retrieve object metadata from the cache */
+ res = guit->llcache->fetch(object->url,
+ &flags,
+ &metadata,
+ &metadatalen);
+ if (res != NSERROR_OK)
+ return res;
+
+ end = metadata + metadatalen;
+
+ /* metadata line 1 is the url the metadata referrs to */
+ line = 1;
+ ln = (char *)metadata;
+ lnsize = strlen(ln);
+
+ if (lnsize < 7)
+ goto format_error;
+
+ res = nsurl_create(ln, &metadataurl);
+ if (res != NSERROR_OK) {
+ free(metadata);
+ return res;
+ }
+
+ if (nsurl_compare(object->url, metadataurl, NSURL_COMPLETE) != true) {
+ /* backing store returned the wrong object for the
+ * request. This may occour if the backing store had
+ * a collision in its stoage method. We cope with this
+ * by simply skipping caching of this object.
+ */
+
+ LOG(("Got metadata for %s instead of %s",
+ nsurl_access(metadataurl),
+ nsurl_access(object->url)));
+
+ nsurl_unref(metadataurl);
+
+ free(metadata);
+
+ return NSERROR_BAD_URL;
+ }
+ nsurl_unref(metadataurl);
+
+
+ /* metadata line 2 is the objects length */
+ line = 2;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+
+ if ((lnsize < 1) ||
+ (sscanf(ln, "%zu", &object->source_len) != 1))
+ goto format_error;
+ object->source_alloc = metadatalen;
+
+ /* metadata line 3 is the time of request */
+ line = 3;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+
+ if ((lnsize < 1) ||
+ (strptime(ln, "%s", <m) == NULL))
+ goto format_error;
+ object->cache.req_time = mktime(<m);
+
+ /* metadata line 4 is the time of response */
+ line = 4;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+
+ if ((lnsize < 1) ||
+ (strptime(ln, "%s", <m) == NULL))
+ goto format_error;
+ object->cache.res_time = mktime(<m);
+
+ /* metadata line 5 is the time of request completion */
+ line = 5;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+
+ if ((lnsize < 1) ||
+ (strptime(ln, "%s", <m) == NULL))
+ goto format_error;
+ object->cache.fin_time = mktime(<m);
+
+
+ /* metadata line 6 is the number of headers */
+ line = 6;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+
+ if ((lnsize < 1) ||
+ (sscanf(ln, "%zu", &num_headers) != 1))
+ goto format_error;
+
+
+ /* read headers */
+ for (hloop = 0 ; hloop < num_headers; hloop++) {
+ line++;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+
+ res = llcache_fetch_process_header(object, (uint8_t *)ln, lnsize);
+ if (res != NSERROR_OK) {
+ free(metadata);
+ return res;
+ }
+ }
+
+ free(metadata);
+
+ /* object stored in backing store */
+ object->store_state = LLCACHE_STATE_DISC;
+
+ return NSERROR_OK;
+
+format_error:
+ LOG(("metadata error on line %d\n", line));
+ free(metadata);
+ return NSERROR_INVALID;
+
+}
+
+/**
+ * attempt to retrieve an object from persistant storage.
+ */
+static nserror
+llcache_object_fetch_persistant(llcache_object *object,
+ uint32_t flags,
+ nsurl *referer,
+ const llcache_post_data *post,
+ uint32_t redirect_count)
+{
+ nserror error;
+ nsurl *referer_clone = NULL;
+ llcache_post_data *post_clone = NULL;
+
+ object->cache.req_time = time(NULL);
+ object->cache.fin_time = object->cache.req_time;
+
+ /* retrieve and process metadata */
+ error = llcache_process_metadata(object);
+ if (error != NSERROR_OK)
+ return error;
+
+ /* entry came out of cache - need to setup object state */
+ if (post != NULL) {
+ error = llcache_post_data_clone(post, &post_clone);
+ if (error != NSERROR_OK)
+ return error;
+ }
+
+ if (referer != NULL)
+ referer_clone = nsurl_ref(referer);
+
+ object->fetch.flags = flags;
+ object->fetch.referer = referer_clone;
+ object->fetch.post = post_clone;
+ object->fetch.redirect_count = redirect_count;
+
+ /* fetch is "finished" */
+ object->fetch.state = LLCACHE_FETCH_COMPLETE;
+ object->fetch.fetch = NULL;
+
+ return NSERROR_OK;
+}
+
+/**
* Retrieve a potentially cached object
*
* \param url URL of object to retrieve
@@ -990,89 +1401,156 @@ static nserror llcache_object_clone_cache_data(llcache_object *source,
* \param result Pointer to location to recieve retrieved object
* \return NSERROR_OK on success, appropriate error otherwise
*/
-static nserror llcache_object_retrieve_from_cache(nsurl *url, uint32_t flags,
- nsurl *referer, const llcache_post_data *post,
- uint32_t redirect_count, llcache_object **result)
+static nserror
+llcache_object_retrieve_from_cache(nsurl *url,
+ uint32_t flags,
+ nsurl *referer,
+ const llcache_post_data *post,
+ uint32_t redirect_count,
+ llcache_object **result)
{
nserror error;
llcache_object *obj, *newest = NULL;
- LLCACHE_LOG(("Searching cache for %s (%x %p %p)",
- nsurl_access(url), flags, referer, post));
+ LLCACHE_LOG(("Searching cache for %s flags:%x referer:%s post:%p",
+ nsurl_access(url), flags, referer==NULL?"":nsurl_access(referer), post));
/* Search for the most recently fetched matching object */
for (obj = llcache->cached_objects; obj != NULL; obj = obj->next) {
if ((newest == NULL ||
- obj->cache.req_time > newest->cache.req_time) &&
- nsurl_compare(obj->url, url,
- NSURL_COMPLETE) == true) {
+ obj->cache.req_time > newest->cache.req_time) &&
+ nsurl_compare(obj->url, url,
+ NSURL_COMPLETE) == true) {
newest = obj;
}
}
- if (newest != NULL && llcache_object_is_fresh(newest)) {
- /* Found a suitable object, and it's still fresh, so use it */
- obj = newest;
+ /* No viable object found in cache create one and attempt to
+ * pull from persistant store.
+ */
+ if (newest == NULL) {
+ LLCACHE_LOG(("No viable object found in cache"));
+
+ error = llcache_object_new(url, &obj);
+ if (error != NSERROR_OK)
+ return error;
+
+ /* attempt to retrieve object from persistant store */
+ error = llcache_object_fetch_persistant(obj, flags, referer, post, redirect_count);
+ if (error == NSERROR_OK) {
+ /* set object from persistant store as newest */
+ newest = obj;
- LLCACHE_LOG(("Found fresh %p", obj));
+ /* Add new object to cached object list */
+ llcache_object_add_to_list(obj, &llcache->cached_objects);
+
+ }
+ /* else no object found and unretrivable from cache,
+ * fall through to start fetch
+ */
+ }
+
+ if ((newest != NULL) && (llcache_object_is_fresh(newest))) {
+ /* Found a suitable object, and it's still fresh */
+ LLCACHE_LOG(("Found fresh %p", newest));
/* The client needs to catch up with the object's state.
* This will occur the next time that llcache_poll is called.
*/
- } else if (newest != NULL) {
- /* Found a candidate object but it needs freshness validation */
- /* Create a new object */
- error = llcache_object_new(url, &obj);
- if (error != NSERROR_OK)
- return error;
+ /* ensure the source data is present */
+ error = llcache_persist_retrieve(newest);
+ if (error == NSERROR_OK) {
+ /* source data was sucessfully retrived from
+ * persistant store
+ */
+ *result = newest;
+
+ return NSERROR_OK;
+ }
+
+ /* retrival of source data from persistant store
+ * failed, destroy cache object and fall though to
+ * cache miss to re-retch
+ */
+ LLCACHE_LOG(("Persistant retrival failed for %p", newest));
- LLCACHE_LOG(("Found candidate %p (%p)", obj, newest));
+ llcache_object_remove_from_list(newest, &llcache->cached_objects);
+ llcache_object_destroy(newest);
- /* Clone candidate's cache data */
- error = llcache_object_clone_cache_data(newest, obj, true);
+ error = llcache_object_new(url, &obj);
if (error != NSERROR_OK) {
- llcache_object_destroy(obj);
return error;
}
+ } else if (newest != NULL) {
+ /* Found a candidate object but it needs freshness validation */
- /* Record candidate, so we can fall back if it is still fresh */
- newest->candidate_count++;
- obj->candidate = newest;
+ /* ensure the source data is present */
+ error = llcache_persist_retrieve(newest);
+ if (error == NSERROR_OK) {
- /* Attempt to kick-off fetch */
- error = llcache_object_fetch(obj, flags, referer, post,
- redirect_count);
- if (error != NSERROR_OK) {
- newest->candidate_count--;
- llcache_object_destroy(obj);
- return error;
+ /* Create a new object */
+ error = llcache_object_new(url, &obj);
+ if (error != NSERROR_OK)
+ return error;
+
+ LLCACHE_LOG(("Found candidate %p (%p)", obj, newest));
+
+ /* Clone candidate's cache data */
+ error = llcache_object_clone_cache_data(newest, obj, true);
+ if (error != NSERROR_OK) {
+ llcache_object_destroy(obj);
+ return error;
+ }
+
+ /* Record candidate, so we can fall back if it is still fresh */
+ newest->candidate_count++;
+ obj->candidate = newest;
+
+ /* Attempt to kick-off fetch */
+ error = llcache_object_fetch(obj, flags, referer, post,
+ redirect_count);
+ if (error != NSERROR_OK) {
+ newest->candidate_count--;
+ llcache_object_destroy(obj);
+ return error;
+ }
+
+ /* Add new object to cache */
+ llcache_object_add_to_list(obj, &llcache->cached_objects);
+
+ *result = obj;
+
+ return NSERROR_OK;
}
- /* Add new object to cache */
- llcache_object_add_to_list(obj, &llcache->cached_objects);
- } else {
- /* No object found; create a new one */
- /* Create new object */
- error = llcache_object_new(url, &obj);
- if (error != NSERROR_OK)
- return error;
+ LLCACHE_LOG(("Persistant retrival failed for %p", newest));
- LLCACHE_LOG(("Not found %p", obj));
+ /* retrival of source data from persistant store
+ * failed, destroy cache object and fall though to
+ * cache miss to re-retch
+ */
+ llcache_object_remove_from_list(newest,
+ &llcache->cached_objects);
+ llcache_object_destroy(newest);
- /* Attempt to kick-off fetch */
- error = llcache_object_fetch(obj, flags, referer, post,
- redirect_count);
+ error = llcache_object_new(url, &obj);
if (error != NSERROR_OK) {
- llcache_object_destroy(obj);
return error;
}
+ }
- /* Add new object to cache */
- llcache_object_add_to_list(obj, &llcache->cached_objects);
+ /* Attempt to kick-off fetch */
+ error = llcache_object_fetch(obj, flags, referer, post, redirect_count);
+ if (error != NSERROR_OK) {
+ llcache_object_destroy(obj);
+ return error;
}
+ /* Add new object to cache */
+ llcache_object_add_to_list(obj, &llcache->cached_objects);
+
*result = obj;
return NSERROR_OK;
@@ -1098,8 +1576,8 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
nsurl *defragmented_url;
bool uncachable = false;
- LLCACHE_LOG(("Retrieve %s (%x, %p, %p)",
- nsurl_access(url), flags, referer, post));
+ LLCACHE_LOG(("Retrieve %s (%x, %s, %p)", nsurl_access(url), flags,
+ referer==NULL?"":nsurl_access(referer), post));
/* Get rid of any url fragment */
@@ -1626,6 +2104,146 @@ static nserror llcache_fetch_ssl_error(llcache_object *object)
}
/**
+ * construct a sorted list of objects available for writeout operation
+ *
+ * The list contains fresh cacheable objects held in RAM with no
+ * pending fetches. Any objects with a remaining lifetime less than
+ * LLCACHE_MIN_DISC_LIFETIME time are simply not considered, they will
+ * become stale before pushing to backing store is worth the cost.
+ *
+ * \todo calculate useful cost metrics to improve sorting
+ *
+ */
+static nserror
+build_candidate_list(struct llcache_object ***lst_out, int *lst_len_out)
+{
+ llcache_object *object, *next;
+ struct llcache_object **lst;
+ int lst_len = 0;
+ int remaining_lifetime;
+
+ lst = calloc(512, sizeof(struct llcache_object *));
+ if (lst == NULL)
+ return NSERROR_NOMEM;
+
+ for (object = llcache->cached_objects; object != NULL; object = next) {
+ next = object->next;
+
+ remaining_lifetime = llcache_object_rfc2616_remaining_lifetime(&object->cache);
+
+ /* cacehable objects with no pending fetches, not
+ * already on disc and with sufficient lifetime to
+ * make disc cache worthwile
+ */
+ if ((object->candidate_count == 0) &&
+ (object->fetch.fetch == NULL) &&
+ (object->fetch.outstanding_query == false) &&
+ (object->store_state == LLCACHE_STATE_RAM) &&
+ (remaining_lifetime > LLCACHE_MIN_DISC_LIFETIME)) {
+ lst[lst_len] = object;
+ lst_len++;
+ if (lst_len == 512)
+ break;
+ }
+ }
+
+ if (lst_len == 0) {
+ free(lst);
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* sort list here */
+
+ *lst_len_out = lst_len;
+ *lst_out = lst;
+
+ return NSERROR_OK;
+}
+
+static nserror
+write_backing_store(struct llcache_object *object, size_t *written_out)
+{
+ nserror ret;
+ uint8_t *metadata;
+ size_t metadatasize;
+
+ /* put object data in backing store */
+ ret = guit->llcache->store(object->url,
+ LLCACHE_STORE_NONE,
+ object->source_data,
+ object->source_len);
+ if (ret != NSERROR_OK) {
+ /* unable to put source data in backing store */
+ return ret;
+ }
+
+ ret = llcache_serialise_metadata(object, &metadata, &metadatasize);
+ if (ret != NSERROR_OK) {
+ /* There has been a metadata serialisation error. Ensure the
+ * already written data object is invalidated.
+ */
+ guit->llcache->invalidate(object->url);
+ return ret;
+ }
+
+ ret = guit->llcache->store(object->url,
+ LLCACHE_STORE_META,
+ metadata,
+ metadatasize);
+ free(metadata);
+ if (ret != NSERROR_OK) {
+ /* There has been an error putting the metadata in the
+ * backing store. Ensure the data object is invalidated.
+ */
+ guit->llcache->invalidate(object->url);
+ return ret;
+ }
+ object->store_state = LLCACHE_STATE_DISC;
+
+ *written_out = object->source_len + metadatasize;
+
+ return NSERROR_OK;
+}
+
+/**
+ * possibly write objects data to backing store.
+ */
+static void llcache_persist(void *p)
+{
+ nserror ret;
+ size_t size_written;
+ size_t total_written = 0;
+ struct llcache_object **lst;
+ int lst_count;
+ int idx;
+
+ ret = build_candidate_list(&lst, &lst_count);
+ if (ret == NSERROR_OK) {
+ /* obtained a candidate list, make each object
+ * persistant in turn
+ */
+ for (idx = 0; idx < lst_count; idx++) {
+ ret = write_backing_store(lst[idx], &size_written);
+ if (ret != NSERROR_OK) {
+ break;
+ }
+ total_written += size_written;
+
+ if (total_written > LLCACHE_MAX_DISC_BANDWIDTH) {
+ /* The bandwidth limit has been reached.
+ * Writeout scheduled for the remaining objects
+ */
+ schedule(100, llcache_persist, NULL);
+ break;
+ }
+ }
+
+ free(lst);
+ }
+}
+
+
+/**
* Handler for fetch events
*
* \param msg Fetch event
@@ -1724,6 +2342,11 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
}
llcache_object_cache_update(object);
+
+ /* record when the fetch finished */
+ object->cache.fin_time = time(NULL);
+
+ schedule(500, llcache_persist, NULL);
}
break;
@@ -1833,26 +2456,6 @@ static llcache_object_user *llcache_object_find_user(const llcache_handle *handl
return user;
}
-/**
- * Remove a low-level cache object from a cache list
- *
- * \param object Object to remove
- * \param list List to remove from
- * \return NSERROR_OK
- */
-static nserror llcache_object_remove_from_list(llcache_object *object,
- llcache_object **list)
-{
- if (object == *list)
- *list = object->next;
- else
- object->prev->next = object->next;
-
- if (object->next != NULL)
- object->next->prev = object->prev;
-
- return NSERROR_OK;
-}
/**
* Determine if a low-level cache object resides in a given list
@@ -2110,8 +2713,8 @@ static nserror llcache_object_notify_users(llcache_object *object)
* \param snapshot Pointer to receive snapshot of \a object
* \return NSERROR_OK on success, appropriate error otherwise
*/
-static nserror llcache_object_snapshot(llcache_object *object,
- llcache_object **snapshot)
+static nserror
+llcache_object_snapshot(llcache_object *object, llcache_object **snapshot)
{
llcache_object *newobj;
nserror error;
@@ -2162,7 +2765,6 @@ static nserror llcache_object_snapshot(llcache_object *object,
return NSERROR_OK;
}
-
/******************************************************************************
* Public API *
******************************************************************************/
@@ -2179,15 +2781,10 @@ void llcache_clean(void)
LLCACHE_LOG(("Attempting cache clean"));
- /* Candidates for cleaning are (in order of priority):
- *
- * 1) Uncacheable objects with no users
- * 2) Stale cacheable objects with no users or pending fetches
- * 3) Fresh cacheable objects with no users or pending fetches
- */
-
- /* 1) Uncacheable objects with no users or fetches */
- for (object = llcache->uncached_objects; object != NULL; object = next) {
+ /* Uncacheable objects with no users or fetches */
+ for (object = llcache->uncached_objects;
+ object != NULL;
+ object = next) {
next = object->next;
/* The candidate count of uncacheable objects is always 0 */
@@ -2205,8 +2802,11 @@ void llcache_clean(void)
}
}
- /* 2) Stale cacheable objects with no users or pending fetches */
- for (object = llcache->cached_objects; object != NULL; object = next) {
+
+ /* Stale cacheable objects with no users or pending fetches */
+ for (object = llcache->cached_objects;
+ object != NULL;
+ object = next) {
next = object->next;
remaining_lifetime = llcache_object_rfc2616_remaining_lifetime(&object->cache);
@@ -2218,41 +2818,83 @@ void llcache_clean(void)
if (remaining_lifetime > 0) {
/* object is fresh */
- llcache_size += object->source_len + sizeof(*object);
+ llcache_size += sizeof(*object);
+ if (object->source_data != NULL) {
+ llcache_size += object->source_len;
+ }
} else {
/* object is not fresh */
LLCACHE_LOG(("Found stale cacheable object (%p) with no users or pending fetches", object));
llcache_object_remove_from_list(object,
&llcache->cached_objects);
+
+ if (object->store_state == LLCACHE_STATE_DISC) {
+ guit->llcache->invalidate(object->url);
+ }
+
llcache_object_destroy(object);
}
} else {
+ /* object has users */
llcache_size += object->source_len + sizeof(*object);
}
}
- /* 3) Fresh cacheable objects with no users or pending
- * fetches, only if the cache exceeds the configured size.
+ /* if the cache limit is exceeded try to make some objects
+ * persistant so their RAM can be reclaimed in the next
+ * step
*/
- if (llcache->limit < llcache_size) {
- for (object = llcache->cached_objects; object != NULL;
- object = next) {
- next = object->next;
+ if (llcache->limit < llcache_size) {
+ llcache_persist(NULL);
+ }
+
+ /* Fresh cacheable objects with no users, no pending fetches
+ * and pushed to persistant store while the cache exceeds
+ * the configured size.
+ */
+ for (object = llcache->cached_objects;
+ ((llcache->limit < llcache_size) && (object != NULL));
+ object = next) {
+ next = object->next;
+ if ((object->users == NULL) &&
+ (object->candidate_count == 0) &&
+ (object->fetch.fetch == NULL) &&
+ (object->fetch.outstanding_query == false) &&
+ (object->store_state == LLCACHE_STATE_DISC)) {
+ free(object->source_data);
+ object->source_data = NULL;
- if ((object->users == NULL) &&
- (object->candidate_count == 0) &&
- (object->fetch.fetch == NULL) &&
- (object->fetch.outstanding_query == false)) {
- LLCACHE_LOG(("Found victim %p", object));
+ llcache_size -= object->source_len;
+
+ LLCACHE_LOG(("Freeing source data for %p len:%d",
+ object,
+ object->source_len));
+ }
+ }
- llcache_size -=
- object->source_len + sizeof(*object);
+ /* Fresh cacheable objects with no users or pending
+ * fetches while the cache exceeds the configured size.
+ */
+ for (object = llcache->cached_objects;
+ ((llcache->limit < llcache_size) && (object != NULL));
+ object = next) {
+ next = object->next;
- llcache_object_remove_from_list(object,
+ if ((object->users == NULL) &&
+ (object->candidate_count == 0) &&
+ (object->fetch.fetch == NULL) &&
+ (object->fetch.outstanding_query == false) &&
+ (object->store_state == LLCACHE_STATE_RAM)) {
+ LLCACHE_LOG(("discarding object:%p len:%d age:%d",
+ object,
+ object->source_len,
+ time(NULL) - object->last_used));
+ llcache_size -= object->source_len + sizeof(*object);
+
+ llcache_object_remove_from_list(object,
&llcache->cached_objects);
- llcache_object_destroy(object);
- }
+ llcache_object_destroy(object);
}
}
@@ -2261,20 +2903,21 @@ void llcache_clean(void)
/* See llcache.h for documentation */
nserror
-llcache_initialise(llcache_query_callback cb, void *pw, uint32_t llcache_limit)
+llcache_initialise(const struct llcache_parameters *prm)
{
llcache = calloc(1, sizeof(struct llcache_s));
if (llcache == NULL) {
return NSERROR_NOMEM;
}
- llcache->query_cb = cb;
- llcache->query_cb_pw = pw;
- llcache->limit = llcache_limit;
+ llcache->query_cb = prm->cb;
+ llcache->query_cb_pw = prm->cb_ctx;
+ llcache->limit = prm->limit;
- LOG(("llcache initialised with a limit of %d bytes", llcache_limit));
+ LOG(("llcache initialised with a limit of %d bytes", llcache->limit));
- return NSERROR_OK;
+ /* backing store initialisation */
+ return guit->llcache->initialise(&prm->store);
}
/* See llcache.h for documentation */
@@ -2324,6 +2967,9 @@ void llcache_finalise(void)
llcache_object_destroy(object);
}
+ /* backing store finalisation */
+ guit->llcache->finalise();
+
free(llcache);
llcache = NULL;
}
diff --git a/content/llcache.h b/content/llcache.h
index 3d8232c..e562083 100644
--- a/content/llcache.h
+++ b/content/llcache.h
@@ -76,7 +76,7 @@ typedef struct {
} data; /**< Event data */
} llcache_event;
-/**
+/**
* Client callback for low-level cache events
*
* \param handle Handle for which event is issued
@@ -84,18 +84,18 @@ typedef struct {
* \param pw Pointer to client-specific data
* \return NSERROR_OK on success, appropriate error otherwise.
*/
-typedef nserror (*llcache_handle_callback)(llcache_handle *handle,
+typedef nserror (*llcache_handle_callback)(llcache_handle *handle,
const llcache_event *event, void *pw);
/** Flags for low-level cache object retrieval */
enum llcache_retrieve_flag {
/* Note: We're permitted a maximum of 16 flags which must reside in the
- * bottom 16 bits of the flags word. See hlcache.h for further details.
+ * bottom 16 bits of the flags word. See hlcache.h for further details.
*/
/** Force a new fetch */
- LLCACHE_RETRIEVE_FORCE_FETCH = (1 << 0),
+ LLCACHE_RETRIEVE_FORCE_FETCH = (1 << 0),
/** Requested URL was verified */
- LLCACHE_RETRIEVE_VERIFIABLE = (1 << 1),
+ LLCACHE_RETRIEVE_VERIFIABLE = (1 << 1),
/**< No error pages */
LLCACHE_RETRIEVE_NO_ERROR_PAGES = (1 << 2),
/**< Stream data (implies that object is not cacheable) */
@@ -149,21 +149,52 @@ typedef nserror (*llcache_query_response)(bool proceed, void *cbpw);
* \param cbpw Opaque value to pass into \a cb
* \return NSERROR_OK on success, appropriate error otherwise
*
- * \note This callback should return immediately. Once a suitable answer to
- * the query has been obtained, the provided response callback should be
+ * \note This callback should return immediately. Once a suitable answer to
+ * the query has been obtained, the provided response callback should be
* called. This is intended to be an entirely asynchronous process.
*/
typedef nserror (*llcache_query_callback)(const llcache_query *query, void *pw,
llcache_query_response cb, void *cbpw);
/**
+ * Parameters to configure the low level cache backing store.
+ */
+struct llcache_store_parameters {
+ const char *path; /**< The path to the backing store */
+
+ size_t limit; /**< The backing store upper bound target size */
+ size_t hysteresis; /**< The hysteresis around the target size */
+
+ /** number of bits to use for hash in filename mapping.
+ *
+ * 0 indicates use no hash. (variable length filenames)
+ * 23 is a reasonable compromise for RISC OS.
+ * 160 uses sha1 in a manner similar to git.
+ */
+ int hashsize;
+};
+
+/**
+ * Parameters to configure the low level cache.
+ */
+struct llcache_parameters {
+ llcache_query_callback cb; /**< Query handler for llcache */
+ void *cb_ctx; /**< Pointer to llcache query handler data */
+
+ size_t limit; /**< The target upper bound for the RAM cache size */
+ size_t hysteresis; /**< The hysteresis around the target size */
+
+ struct llcache_store_parameters store;
+};
+
+/**
* Initialise the low-level cache
*
* \param cb Query handler
* \param pw Pointer to query handler data
* \return NSERROR_OK on success, appropriate error otherwise.
*/
-nserror llcache_initialise(llcache_query_callback cb, void *pw, uint32_t llcache_limit);
+nserror llcache_initialise(const struct llcache_parameters *parameters);
/**
* Finalise the low-level cache
@@ -280,12 +311,12 @@ const uint8_t *llcache_handle_get_source_data(const llcache_handle *handle,
* \return Header value, or NULL if header does not exist
*
* \todo Make the key an enumeration, to avoid needless string comparisons
- * \todo Forcing the client to parse the header value seems wrong.
- * Better would be to return the actual value part and an array of
+ * \todo Forcing the client to parse the header value seems wrong.
+ * Better would be to return the actual value part and an array of
* key-value pairs for any additional parameters.
* \todo Deal with multiple headers of the same key (e.g. Set-Cookie)
*/
-const char *llcache_handle_get_header(const llcache_handle *handle,
+const char *llcache_handle_get_header(const llcache_handle *handle,
const char *key);
/**
@@ -295,7 +326,7 @@ const char *llcache_handle_get_header(const llcache_handle *handle,
* \param b Second handle
* \return True if handles reference the same object, false otherwise
*/
-bool llcache_handle_references_same_object(const llcache_handle *a,
+bool llcache_handle_references_same_object(const llcache_handle *a,
const llcache_handle *b);
#endif
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index c3653b5..1f5bc59 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -67,11 +67,17 @@
*/
#define SPECULATE_SMALL 4096
-/* the time between cache clean runs in ms */
+/** the time between image cache clean runs in ms */
#define IMAGE_CACHE_CLEAN_TIME (10 * 1000)
+/** default time between content cache cleans */
#define HL_CACHE_CLEAN_TIME (2 * IMAGE_CACHE_CLEAN_TIME)
+/** ensure there is a minimal amount of memory for source objetcs and
+ * decoded bitmaps.
+ */
+#define MINIMUM_MEMORY_CACHE_SIZE (2 * 1024 * 1024)
+
bool netsurf_quit = false;
static void netsurf_lwc_iterator(lwc_string *str, void *pw)
@@ -108,20 +114,22 @@ static nserror netsurf_llcache_query_handler(const llcache_query *query,
return NSERROR_OK;
}
-#define MINIMUM_MEMORY_CACHE_SIZE (2 * 1024 * 1024)
-
/**
* Initialise components used by gui NetSurf.
*/
nserror netsurf_init(const char *messages, struct gui_table *gt)
{
- nserror error;
+ nserror ret;
struct utsname utsname;
- nserror ret = NSERROR_OK;
struct hlcache_parameters hlcache_parameters = {
.bg_clean_time = HL_CACHE_CLEAN_TIME,
- .cb = netsurf_llcache_query_handler,
+ .llcache = {
+ .cb = netsurf_llcache_query_handler,
+ .store = {
+ .hashsize = 160,
+ }
+ }
};
struct image_cache_parameters image_cache_parameters = {
.bg_clean_time = IMAGE_CACHE_CLEAN_TIME,
@@ -149,82 +157,94 @@ nserror netsurf_init(const char *messages, struct gui_table *gt)
utsname.version, utsname.machine));
/* register the gui handlers */
- error = gui_factory_register(gt);
- if (error != NSERROR_OK)
- return error;
+ ret = gui_factory_register(gt);
+ if (ret != NSERROR_OK)
+ return ret;
messages_load(messages);
/* corestrings init */
- error = corestrings_init();
- if (error != NSERROR_OK)
- return error;
+ ret = corestrings_init();
+ if (ret != NSERROR_OK)
+ return ret;
/* set up cache limits based on the memory cache size option */
- hlcache_parameters.limit = nsoption_int(memory_cache_size);
+ hlcache_parameters.llcache.limit = nsoption_int(memory_cache_size);
- if (hlcache_parameters.limit < MINIMUM_MEMORY_CACHE_SIZE) {
- hlcache_parameters.limit = MINIMUM_MEMORY_CACHE_SIZE;
- LOG(("Setting minimum memory cache size to %d",
- hlcache_parameters.limit));
+ if (hlcache_parameters.llcache.limit < MINIMUM_MEMORY_CACHE_SIZE) {
+ hlcache_parameters.llcache.limit = MINIMUM_MEMORY_CACHE_SIZE;
+ LOG(("Setting minimum memory cache size %d",
+ hlcache_parameters.llcache.limit));
}
/* image cache is 25% of total memory cache size */
- image_cache_parameters.limit = (hlcache_parameters.limit * 25) / 100;
+ image_cache_parameters.limit = (hlcache_parameters.llcache.limit * 25) / 100;
/* image cache hysteresis is 20% of the image cache size */
image_cache_parameters.hysteresis = (image_cache_parameters.limit * 20) / 100;
/* account for image cache use from total */
- hlcache_parameters.limit -= image_cache_parameters.limit;
+ hlcache_parameters.llcache.limit -= image_cache_parameters.limit;
+
+ /* set backing store target limit */
+ hlcache_parameters.llcache.store.limit = nsoption_int(disc_cache_size);
+
+ /* set backing store hysterissi to 20% */
+ hlcache_parameters.llcache.store.hysteresis = (hlcache_parameters.llcache.store.limit * 20) / 100;;
+
+ /* set the path to the backing store */
+ /** \todo set the backing store path properly */
+ hlcache_parameters.llcache.store.path = "/tmp/ns";
/* image handler bitmap cache */
- error = image_cache_init(&image_cache_parameters);
- if (error != NSERROR_OK)
- return error;
+ ret = image_cache_init(&image_cache_parameters);
+ if (ret != NSERROR_OK)
+ return ret;
/* content handler initialisation */
- error = nscss_init();
- if (error != NSERROR_OK)
- return error;
+ ret = nscss_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = html_init();
- if (error != NSERROR_OK)
- return error;
+ ret = html_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = image_init();
- if (error != NSERROR_OK)
- return error;
+ ret = image_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = textplain_init();
- if (error != NSERROR_OK)
- return error;
+ ret = textplain_init();
+ if (ret != NSERROR_OK)
+ return ret;
- error = mimesniff_init();
- if (error != NSERROR_OK)
- return error;
+ ret = mimesniff_init();
+ if (ret != NSERROR_OK)
+ return ret;
url_init();
setlocale(LC_ALL, "C");
/* initialise the fetchers */
- error = fetch_init();
- if (error != NSERROR_OK)
- return error;
+ ret = fetch_init();
+ if (ret != NSERROR_OK)
+ return ret;
/* Initialise the hlcache and allow it to init the llcache for us */
- hlcache_initialise(&hlcache_parameters);
+ ret = hlcache_initialise(&hlcache_parameters);
+ if (ret != NSERROR_OK)
+ return ret;
/* Initialize system colours */
- error = ns_system_colour_init();
- if (error != NSERROR_OK)
- return error;
+ ret = ns_system_colour_init();
+ if (ret != NSERROR_OK)
+ return ret;
js_initialise();
- return ret;
+ return NSERROR_OK;
}
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=2d9e02ccc8dd8147bae...
commit 2d9e02ccc8dd8147baec0eede4e3e942f3e27b17
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
low level source data cache backing store interface.
diff --git a/content/llcache_private.h b/content/llcache_private.h
new file mode 100644
index 0000000..ae1b3da
--- /dev/null
+++ b/content/llcache_private.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Low-level source data cache backing store interface
+ */
+
+#ifndef NETSURF_CONTENT_LLCACHE_PRIVATE_H_
+#define NETSURF_CONTENT_LLCACHE_PRIVATE_H_
+
+#include "content/llcache.h"
+
+/** storage control flags */
+enum llcache_store_flags {
+ LLCACHE_STORE_NONE = 0, /**< no special processing */
+ LLCACHE_STORE_META = 1, /**< data is metadata */
+ LLCACHE_STORE_MMAP = 2, /**< when data is retrived this indicates the
+ * returned buffer may be memory mapped,
+ * flag must be cleared if the storage is
+ * allocated and is not memory mapped.
+ */
+};
+
+/** low level cache backing store operation table
+ *
+ * The low level cache (source objects) has the capability to make
+ * objects and their metadata (headers etc) persistant by writing to a
+ * backing store using these operations.
+ */
+struct gui_llcache_table {
+ /**
+ * Initialise the backing store.
+ *
+ * @param parameters to configure backing store.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*initialise)(const struct llcache_store_parameters *parameters);
+
+ /**
+ * Finalise the backing store.
+ *
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*finalise)(void);
+
+ /**
+ * Place an object in the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the obejct is stored.
+ * @param data The objects data.
+ * @param datalen The length of the \a data.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*store)(struct nsurl *url, enum llcache_store_flags flags,
+ const uint8_t *data, const size_t datalen);
+
+ /**
+ * Retrive an object from the backing store.
+ *
+ * @param url The url is used as the unique primary key for the data.
+ * @param flags The flags to control how the object is retrived.
+ * @param data The objects data.
+ * @param datalen The length of the \a data retrieved.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*fetch)(struct nsurl *url, enum llcache_store_flags *flags,
+ uint8_t **data, size_t *datalen);
+
+ /**
+ * Invalidate a source object from the backing store.
+ *
+ * The entry (if present in the backing store) must no longer
+ * be returned as a result to the fetch or meta operations.
+ *
+ * @param url The url is used as the unique primary key to invalidate.
+ * @return NSERROR_OK on success or error code on faliure.
+ */
+ nserror (*invalidate)(struct nsurl *url);
+};
+
+#endif
diff --git a/desktop/gui.h b/desktop/gui.h
index 361c6bd..0eddf12 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -494,6 +494,8 @@ struct gui_browser_table {
};
+struct gui_llcache_table;
+
/** Graphical user interface function table
*
* function table implementing GUI interface to browser core
@@ -528,6 +530,14 @@ struct gui_table {
* implies the local encoding is utf8.
*/
struct gui_utf8_table *utf8;
+
+ /** Low level cache table
+ *
+ * Used by the low level cache to push objects to persistant
+ * storage. The table is optional and may be NULL which
+ * disables persistant caching of objects
+ */
+ struct gui_llcache_table *llcache;
};
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index 638abfd..d91371d 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -17,6 +17,8 @@
*/
#include "content/hlcache.h"
+#include "content/llcache_private.h"
+
#include "desktop/download.h"
#include "desktop/gui_factory.h"
@@ -343,6 +345,82 @@ static nserror verify_utf8_register(struct gui_utf8_table *gut)
return NSERROR_OK;
}
+static nserror
+gui_default_initialise(const struct llcache_store_parameters *parameters)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+gui_default_finalise(void)
+{
+ return NSERROR_OK;
+}
+
+static nserror
+gui_default_store(nsurl *url,
+ enum llcache_store_flags flags,
+ const uint8_t *data,
+ const size_t datalen)
+{
+ return NSERROR_SAVE_FAILED;
+}
+
+static nserror
+gui_default_fetch(nsurl *url,
+ enum llcache_store_flags *flags,
+ uint8_t **data_out,
+ size_t *datalen_out)
+{
+ return NSERROR_NOT_FOUND;
+}
+
+static nserror
+gui_default_invalidate(nsurl *url)
+{
+ return NSERROR_NOT_FOUND;
+}
+
+
+static struct gui_llcache_table default_llcache_table = {
+ .initialise = gui_default_initialise,
+ .finalise = gui_default_finalise,
+ .store = gui_default_store,
+ .fetch = gui_default_fetch,
+ .invalidate = gui_default_invalidate,
+};
+
+/** verify clipboard table is valid */
+static nserror verify_llcache_register(struct gui_llcache_table *glt)
+{
+ /* check table is present */
+ if (glt == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* mandantory operations */
+ if (glt->store == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (glt->fetch == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if (glt->invalidate == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* fill in the optional entries with defaults */
+ if (glt->initialise == NULL) {
+ glt->initialise = gui_default_initialise;
+ }
+ if (glt->finalise == NULL) {
+ glt->finalise = gui_default_finalise;
+ }
+
+ return NSERROR_OK;
+}
+
+
static nsurl *gui_default_get_resource_url(const char *path)
{
return NULL;
@@ -533,6 +611,16 @@ nserror gui_factory_register(struct gui_table *gt)
return err;
}
+ /* llcache table */
+ if (gt->llcache == NULL) {
+ /* set default clipboard table */
+ gt->llcache = &default_llcache_table;
+ }
+ err = verify_llcache_register(gt->llcache);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
guit = gt;
return NSERROR_OK;
-----------------------------------------------------------------------
--
NetSurf Browser
8 years, 11 months
netsurf: branch master updated. release/3.0-1143-gda0b969
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/da0b969f2514df4e6d4fe...
...commit http://git.netsurf-browser.org/netsurf.git/commit/da0b969f2514df4e6d4febf...
...tree http://git.netsurf-browser.org/netsurf.git/tree/da0b969f2514df4e6d4febf78...
The branch, master has been updated
via da0b969f2514df4e6d4febf78c54c8b4c34dcb9a (commit)
via 25ce52ee64126caac0550d7086abb79b10e1a951 (commit)
via 8d883978c6d31915f63325b1bc27659ca140bf43 (commit)
via 20b3c408167b2093f1d2d68792550ff6ec44aabd (commit)
from 5c6a0eda3b42d98f7f7aeab94b96021128c298c4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=da0b969f2514df4e6d4...
commit da0b969f2514df4e6d4febf78c54c8b4c34dcb9a
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
Improve llcache header processing
By skipping empty headers and correctly dealing with whitespace around
header names we store fewer entries with better adherance to allowed
values in http responses.
diff --git a/content/llcache.c b/content/llcache.c
index 7d6e6b6..112a7fa 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -382,11 +382,25 @@ static nserror llcache_fetch_split_header(const uint8_t *data, size_t len,
char *n, *v;
const uint8_t *colon;
+ /* Strip leading whitespace from name */
+ while (data[0] == ' ' || data[0] == '\t' ||
+ data[0] == '\r' || data[0] == '\n') {
+ data++;
+ }
+
/* Find colon */
colon = (const uint8_t *) strchr((const char *) data, ':');
if (colon == NULL) {
/* Failed, assume a key with no value */
- n = strdup((const char *) data);
+ colon = data + strlen((const char *)data);
+
+ /* Strip trailing whitespace from name */
+ while ((colon > data) &&
+ (colon[-1] == ' ' || colon[-1] == '\t' ||
+ colon[-1] == '\r' || colon[-1] == '\n')) {
+ colon--;
+ }
+ n = strndup((const char *) data, colon - data);
if (n == NULL)
return NSERROR_NOMEM;
@@ -398,12 +412,6 @@ static nserror llcache_fetch_split_header(const uint8_t *data, size_t len,
} else {
/* Split header into name & value */
- /* Strip leading whitespace from name */
- while (data[0] == ' ' || data[0] == '\t' ||
- data[0] == '\r' || data[0] == '\n') {
- data++;
- }
-
/* Strip trailing whitespace from name */
while (colon > data && (colon[-1] == ' ' ||
colon[-1] == '\t' || colon[-1] == '\r' ||
@@ -613,6 +621,13 @@ static nserror llcache_fetch_process_header(llcache_object *object,
return error;
}
+ /* deal with empty header */
+ if (name[0] == 0) {
+ free(name);
+ free(value);
+ return NSERROR_OK;
+ }
+
/* Append header data to the object's headers array */
temp = realloc(object->headers, (object->num_headers + 1) *
sizeof(llcache_header));
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=25ce52ee64126caac05...
commit 25ce52ee64126caac0550d7086abb79b10e1a951
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
only try and cache http and https urls
diff --git a/content/llcache.c b/content/llcache.c
index fc77575..7d6e6b6 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -1081,23 +1081,44 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
nserror error;
llcache_object *obj;
nsurl *defragmented_url;
+ bool uncachable = false;
LLCACHE_LOG(("Retrieve %s (%x, %p, %p)",
nsurl_access(url), flags, referer, post));
- /**
- * Caching Rules:
- *
- * 1) Forced fetches are never cached
- * 2) POST requests are never cached
- */
/* Get rid of any url fragment */
error = nsurl_defragment(url, &defragmented_url);
if (error != NSERROR_OK)
return error;
- if (flags & LLCACHE_RETRIEVE_FORCE_FETCH || post != NULL) {
+ /* determine if content is cachable */
+ if ((flags & LLCACHE_RETRIEVE_FORCE_FETCH) != 0) {
+ /* Forced fetches are never cached */
+ uncachable = true;
+ } else if (post != NULL) {
+ /* POST requests are never cached */
+ uncachable = true;
+ } else {
+ /* only http and https schemes are cached */
+ lwc_string *scheme;
+ bool match;
+
+ scheme = nsurl_get_component(defragmented_url, NSURL_SCHEME);
+
+ if (lwc_string_caseless_isequal(scheme, corestring_lwc_http,
+ &match) == lwc_error_ok &&
+ (match == false)) {
+ if (lwc_string_caseless_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok &&
+ (match == false)) {
+ uncachable = true;
+ }
+ }
+ }
+
+
+ if (uncachable) {
/* Create new object */
error = llcache_object_new(defragmented_url, &obj);
if (error != NSERROR_OK) {
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=8d883978c6d31915f63...
commit 8d883978c6d31915f63325b1bc27659ca140bf43
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
remove unnecessary caching of whether a url has a query element
diff --git a/content/llcache.c b/content/llcache.c
index a6e46bf..fc77575 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -129,7 +129,6 @@ struct llcache_object {
llcache_object *next; /**< Next in list */
nsurl *url; /**< Post-redirect URL for object */
- bool has_query; /**< URL has a query segment */
/** \todo We need a generic dynamic buffer object */
uint8_t *source_data; /**< Source data for object */
@@ -1081,7 +1080,6 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
{
nserror error;
llcache_object *obj;
- bool has_query;
nsurl *defragmented_url;
LLCACHE_LOG(("Retrieve %s (%x, %p, %p)",
@@ -1094,9 +1092,6 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
* 2) POST requests are never cached
*/
- /* Look for a query segment */
- has_query = nsurl_has_component(url, NSURL_QUERY);
-
/* Get rid of any url fragment */
error = nsurl_defragment(url, &defragmented_url);
if (error != NSERROR_OK)
@@ -1132,8 +1127,6 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
/* Returned object is already in the cached list */
}
- obj->has_query = has_query;
-
LLCACHE_LOG(("Retrieved %p", obj));
*result = obj;
@@ -1657,7 +1650,7 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
long http_code = fetch_http_code(object->fetch.fetch);
if ((http_code != 200 && http_code != 203) ||
- (object->has_query &&
+ (nsurl_has_component(object->url, NSURL_QUERY) &&
(object->cache.max_age == INVALID_AGE &&
object->cache.expires == 0))) {
/* Invalidate cache control data */
@@ -2092,8 +2085,6 @@ static nserror llcache_object_snapshot(llcache_object *object,
if (error != NSERROR_OK)
return error;
- newobj->has_query = object->has_query;
-
newobj->source_alloc = newobj->source_len = object->source_len;
if (object->source_len > 0) {
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=20b3c408167b2093f1d...
commit 20b3c408167b2093f1d2d68792550ff6ec44aabd
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
make nsurl_defragment() API more obvious and remove duplicated parameter checking
diff --git a/content/llcache.c b/content/llcache.c
index bd7ae93..a6e46bf 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -1098,13 +1098,9 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
has_query = nsurl_has_component(url, NSURL_QUERY);
/* Get rid of any url fragment */
- if (nsurl_has_component(url, NSURL_FRAGMENT)) {
- error = nsurl_defragment(url, &defragmented_url);
- if (error != NSERROR_OK)
- return error;
- } else {
- defragmented_url = nsurl_ref(url);
- }
+ error = nsurl_defragment(url, &defragmented_url);
+ if (error != NSERROR_OK)
+ return error;
if (flags & LLCACHE_RETRIEVE_FORCE_FETCH || post != NULL) {
/* Create new object */
diff --git a/content/urldb.c b/content/urldb.c
index f55a1c2..1e17ac5 100644
--- a/content/urldb.c
+++ b/content/urldb.c
@@ -1806,14 +1806,9 @@ struct path_data *urldb_add_path(lwc_string *scheme, unsigned int port,
free(path_query);
if (d && !d->url) {
- /* Insert URL */
- if (nsurl_has_component(url, NSURL_FRAGMENT)) {
- nserror err = nsurl_defragment(url, &d->url);
- if (err != NSERROR_OK)
- return NULL;
- } else {
- d->url = nsurl_ref(url);
- }
+ /* Insert defragmented URL */
+ if (nsurl_defragment(url, &d->url) != NSERROR_OK)
+ return NULL;
}
return d;
@@ -2728,12 +2723,8 @@ bool urldb_set_cookie(const char *header, nsurl *url, nsurl *referer)
assert(url && header);
/* Get defragmented URL, as 'urlt' */
- if (nsurl_has_component(url, NSURL_FRAGMENT)) {
- if (nsurl_defragment(url, &urlt) != NSERROR_OK)
- return NULL;
- } else {
- urlt = nsurl_ref(url);
- }
+ if (nsurl_defragment(url, &urlt) != NSERROR_OK)
+ return NULL;
scheme = nsurl_get_component(url, NSURL_SCHEME);
if (scheme == NULL) {
diff --git a/utils/nsurl.c b/utils/nsurl.c
index ae0c482..c99b0d3 100644
--- a/utils/nsurl.c
+++ b/utils/nsurl.c
@@ -1911,6 +1911,15 @@ nserror nsurl_defragment(const nsurl *url, nsurl **no_frag)
size_t length;
char *pos;
+ /* check for source url having no fragment already */
+ if (url->components.fragment == NULL) {
+ *no_frag = (nsurl *)url;
+
+ (*no_frag)->count++;
+
+ return NSERROR_OK;
+ }
+
/* Find the change in length from url to new_url */
length = url->length;
if (url->components.fragment != NULL) {
-----------------------------------------------------------------------
Summary of changes:
content/llcache.c | 81 ++++++++++++++++++++++++++++++++++-------------------
content/urldb.c | 19 +++---------
utils/nsurl.c | 9 ++++++
3 files changed, 66 insertions(+), 43 deletions(-)
diff --git a/content/llcache.c b/content/llcache.c
index bd7ae93..112a7fa 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -129,7 +129,6 @@ struct llcache_object {
llcache_object *next; /**< Next in list */
nsurl *url; /**< Post-redirect URL for object */
- bool has_query; /**< URL has a query segment */
/** \todo We need a generic dynamic buffer object */
uint8_t *source_data; /**< Source data for object */
@@ -383,11 +382,25 @@ static nserror llcache_fetch_split_header(const uint8_t *data, size_t len,
char *n, *v;
const uint8_t *colon;
+ /* Strip leading whitespace from name */
+ while (data[0] == ' ' || data[0] == '\t' ||
+ data[0] == '\r' || data[0] == '\n') {
+ data++;
+ }
+
/* Find colon */
colon = (const uint8_t *) strchr((const char *) data, ':');
if (colon == NULL) {
/* Failed, assume a key with no value */
- n = strdup((const char *) data);
+ colon = data + strlen((const char *)data);
+
+ /* Strip trailing whitespace from name */
+ while ((colon > data) &&
+ (colon[-1] == ' ' || colon[-1] == '\t' ||
+ colon[-1] == '\r' || colon[-1] == '\n')) {
+ colon--;
+ }
+ n = strndup((const char *) data, colon - data);
if (n == NULL)
return NSERROR_NOMEM;
@@ -399,12 +412,6 @@ static nserror llcache_fetch_split_header(const uint8_t *data, size_t len,
} else {
/* Split header into name & value */
- /* Strip leading whitespace from name */
- while (data[0] == ' ' || data[0] == '\t' ||
- data[0] == '\r' || data[0] == '\n') {
- data++;
- }
-
/* Strip trailing whitespace from name */
while (colon > data && (colon[-1] == ' ' ||
colon[-1] == '\t' || colon[-1] == '\r' ||
@@ -614,6 +621,13 @@ static nserror llcache_fetch_process_header(llcache_object *object,
return error;
}
+ /* deal with empty header */
+ if (name[0] == 0) {
+ free(name);
+ free(value);
+ return NSERROR_OK;
+ }
+
/* Append header data to the object's headers array */
temp = realloc(object->headers, (object->num_headers + 1) *
sizeof(llcache_header));
@@ -1081,32 +1095,45 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
{
nserror error;
llcache_object *obj;
- bool has_query;
nsurl *defragmented_url;
+ bool uncachable = false;
LLCACHE_LOG(("Retrieve %s (%x, %p, %p)",
nsurl_access(url), flags, referer, post));
- /**
- * Caching Rules:
- *
- * 1) Forced fetches are never cached
- * 2) POST requests are never cached
- */
-
- /* Look for a query segment */
- has_query = nsurl_has_component(url, NSURL_QUERY);
/* Get rid of any url fragment */
- if (nsurl_has_component(url, NSURL_FRAGMENT)) {
- error = nsurl_defragment(url, &defragmented_url);
- if (error != NSERROR_OK)
- return error;
+ error = nsurl_defragment(url, &defragmented_url);
+ if (error != NSERROR_OK)
+ return error;
+
+ /* determine if content is cachable */
+ if ((flags & LLCACHE_RETRIEVE_FORCE_FETCH) != 0) {
+ /* Forced fetches are never cached */
+ uncachable = true;
+ } else if (post != NULL) {
+ /* POST requests are never cached */
+ uncachable = true;
} else {
- defragmented_url = nsurl_ref(url);
+ /* only http and https schemes are cached */
+ lwc_string *scheme;
+ bool match;
+
+ scheme = nsurl_get_component(defragmented_url, NSURL_SCHEME);
+
+ if (lwc_string_caseless_isequal(scheme, corestring_lwc_http,
+ &match) == lwc_error_ok &&
+ (match == false)) {
+ if (lwc_string_caseless_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok &&
+ (match == false)) {
+ uncachable = true;
+ }
+ }
}
- if (flags & LLCACHE_RETRIEVE_FORCE_FETCH || post != NULL) {
+
+ if (uncachable) {
/* Create new object */
error = llcache_object_new(defragmented_url, &obj);
if (error != NSERROR_OK) {
@@ -1136,8 +1163,6 @@ static nserror llcache_object_retrieve(nsurl *url, uint32_t flags,
/* Returned object is already in the cached list */
}
- obj->has_query = has_query;
-
LLCACHE_LOG(("Retrieved %p", obj));
*result = obj;
@@ -1661,7 +1686,7 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
long http_code = fetch_http_code(object->fetch.fetch);
if ((http_code != 200 && http_code != 203) ||
- (object->has_query &&
+ (nsurl_has_component(object->url, NSURL_QUERY) &&
(object->cache.max_age == INVALID_AGE &&
object->cache.expires == 0))) {
/* Invalidate cache control data */
@@ -2096,8 +2121,6 @@ static nserror llcache_object_snapshot(llcache_object *object,
if (error != NSERROR_OK)
return error;
- newobj->has_query = object->has_query;
-
newobj->source_alloc = newobj->source_len = object->source_len;
if (object->source_len > 0) {
diff --git a/content/urldb.c b/content/urldb.c
index f55a1c2..1e17ac5 100644
--- a/content/urldb.c
+++ b/content/urldb.c
@@ -1806,14 +1806,9 @@ struct path_data *urldb_add_path(lwc_string *scheme, unsigned int port,
free(path_query);
if (d && !d->url) {
- /* Insert URL */
- if (nsurl_has_component(url, NSURL_FRAGMENT)) {
- nserror err = nsurl_defragment(url, &d->url);
- if (err != NSERROR_OK)
- return NULL;
- } else {
- d->url = nsurl_ref(url);
- }
+ /* Insert defragmented URL */
+ if (nsurl_defragment(url, &d->url) != NSERROR_OK)
+ return NULL;
}
return d;
@@ -2728,12 +2723,8 @@ bool urldb_set_cookie(const char *header, nsurl *url, nsurl *referer)
assert(url && header);
/* Get defragmented URL, as 'urlt' */
- if (nsurl_has_component(url, NSURL_FRAGMENT)) {
- if (nsurl_defragment(url, &urlt) != NSERROR_OK)
- return NULL;
- } else {
- urlt = nsurl_ref(url);
- }
+ if (nsurl_defragment(url, &urlt) != NSERROR_OK)
+ return NULL;
scheme = nsurl_get_component(url, NSURL_SCHEME);
if (scheme == NULL) {
diff --git a/utils/nsurl.c b/utils/nsurl.c
index ae0c482..c99b0d3 100644
--- a/utils/nsurl.c
+++ b/utils/nsurl.c
@@ -1911,6 +1911,15 @@ nserror nsurl_defragment(const nsurl *url, nsurl **no_frag)
size_t length;
char *pos;
+ /* check for source url having no fragment already */
+ if (url->components.fragment == NULL) {
+ *no_frag = (nsurl *)url;
+
+ (*no_frag)->count++;
+
+ return NSERROR_OK;
+ }
+
/* Find the change in length from url to new_url */
length = url->length;
if (url->components.fragment != NULL) {
--
NetSurf Browser
8 years, 11 months
netsurf: branch master updated. release/3.0-1139-g5c6a0ed
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/5c6a0eda3b42d98f7f7ae...
...commit http://git.netsurf-browser.org/netsurf.git/commit/5c6a0eda3b42d98f7f7aeab...
...tree http://git.netsurf-browser.org/netsurf.git/tree/5c6a0eda3b42d98f7f7aeab94...
The branch, master has been updated
via 5c6a0eda3b42d98f7f7aeab94b96021128c298c4 (commit)
from 87f6314dabdc2067a19e01f8b29f9ecc38ed825b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=5c6a0eda3b42d98f7f7...
commit 5c6a0eda3b42d98f7f7aeab94b96021128c298c4
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
fixup missing includes from schedule changes
diff --git a/amiga/menu.c b/amiga/menu.c
index 9cb857e..13b9c9c 100644
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -484,7 +484,7 @@ struct NewMenu *ami_create_menu(struct gui_window_2 *gwin)
if(nsoption_int(menu_refresh) > 0)
{
ami_schedule(nsoption_int(menu_refresh) * 10,
- ami_menu_refresh,
+ (void *)ami_menu_refresh,
gwin);
}
diff --git a/amiga/schedule.c b/amiga/schedule.c
index 4ec9df7..9aa7488 100755
--- a/amiga/schedule.c
+++ b/amiga/schedule.c
@@ -17,7 +17,6 @@
*/
#include "amiga/os3support.h"
-#include "amiga/schedule.h"
#include <proto/exec.h>
#include <proto/timer.h>
@@ -26,6 +25,10 @@
#include <stdbool.h>
#include <pbl.h>
+#include "utils/errors.h"
+
+#include "amiga/schedule.h"
+
struct nscallback
{
struct TimeVal tv;
diff --git a/amiga/tree.c b/amiga/tree.c
index fa12528..df6ac9b 100644
--- a/amiga/tree.c
+++ b/amiga/tree.c
@@ -1396,5 +1396,5 @@ void ami_tree_redraw_request(int x, int y, int width, int height, void *data)
if(nsoption_bool(direct_render) == false)
ami_schedule(0, ami_tree_redraw_req, atrr_data);
else
- am_schedule(0, ami_tree_redraw_req_dr, atrr_data);
+ ami_schedule(0, ami_tree_redraw_req_dr, atrr_data);
}
diff --git a/atari/schedule.c b/atari/schedule.c
index 02a3762..3bef573 100755
--- a/atari/schedule.c
+++ b/atari/schedule.c
@@ -22,6 +22,8 @@
#include <sys/time.h>
#include <time.h>
+#include "utils/errors.h"
+
#include "atari/schedule.h"
#ifdef DEBUG_SCHEDULER
diff --git a/cocoa/schedule.m b/cocoa/schedule.m
index 2dd9a81..f0896bd 100644
--- a/cocoa/schedule.m
+++ b/cocoa/schedule.m
@@ -18,6 +18,8 @@
#import <Cocoa/Cocoa.h>
+#import "utils/errors.h"
+
#import "cocoa/schedule.h"
@interface ScheduledCallback : NSObject {
diff --git a/windows/schedule.c b/windows/schedule.c
index f819918..4aac981 100644
--- a/windows/schedule.c
+++ b/windows/schedule.c
@@ -19,10 +19,11 @@
#include <sys/time.h>
#include <time.h>
-#include "windows/schedule.h"
-
#include "utils/log.h"
#include "utils/utils.h"
+#include "utils/errors.h"
+
+#include "windows/schedule.h"
#ifdef DEBUG_SCHEDULER
#define SRLOG(x) LOG(x)
@@ -110,7 +111,7 @@ nserror win32_schedule(int ival, void (*callback)(void *p), void *p)
}
tv.tv_sec = ival / 1000; /* miliseconds to seconds */
- tv.tv_usec = (cs_ival % 1000) * 1000; /* remainder to microseconds */
+ tv.tv_usec = (ival % 1000) * 1000; /* remainder to microseconds */
nscb = calloc(1, sizeof(struct nscallback));
if (nscb == NULL) {
-----------------------------------------------------------------------
Summary of changes:
amiga/menu.c | 2 +-
amiga/schedule.c | 5 ++++-
amiga/tree.c | 2 +-
atari/schedule.c | 2 ++
cocoa/schedule.m | 2 ++
windows/schedule.c | 7 ++++---
6 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/amiga/menu.c b/amiga/menu.c
index 9cb857e..13b9c9c 100644
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -484,7 +484,7 @@ struct NewMenu *ami_create_menu(struct gui_window_2 *gwin)
if(nsoption_int(menu_refresh) > 0)
{
ami_schedule(nsoption_int(menu_refresh) * 10,
- ami_menu_refresh,
+ (void *)ami_menu_refresh,
gwin);
}
diff --git a/amiga/schedule.c b/amiga/schedule.c
index 4ec9df7..9aa7488 100755
--- a/amiga/schedule.c
+++ b/amiga/schedule.c
@@ -17,7 +17,6 @@
*/
#include "amiga/os3support.h"
-#include "amiga/schedule.h"
#include <proto/exec.h>
#include <proto/timer.h>
@@ -26,6 +25,10 @@
#include <stdbool.h>
#include <pbl.h>
+#include "utils/errors.h"
+
+#include "amiga/schedule.h"
+
struct nscallback
{
struct TimeVal tv;
diff --git a/amiga/tree.c b/amiga/tree.c
index fa12528..df6ac9b 100644
--- a/amiga/tree.c
+++ b/amiga/tree.c
@@ -1396,5 +1396,5 @@ void ami_tree_redraw_request(int x, int y, int width, int height, void *data)
if(nsoption_bool(direct_render) == false)
ami_schedule(0, ami_tree_redraw_req, atrr_data);
else
- am_schedule(0, ami_tree_redraw_req_dr, atrr_data);
+ ami_schedule(0, ami_tree_redraw_req_dr, atrr_data);
}
diff --git a/atari/schedule.c b/atari/schedule.c
index 02a3762..3bef573 100755
--- a/atari/schedule.c
+++ b/atari/schedule.c
@@ -22,6 +22,8 @@
#include <sys/time.h>
#include <time.h>
+#include "utils/errors.h"
+
#include "atari/schedule.h"
#ifdef DEBUG_SCHEDULER
diff --git a/cocoa/schedule.m b/cocoa/schedule.m
index 2dd9a81..f0896bd 100644
--- a/cocoa/schedule.m
+++ b/cocoa/schedule.m
@@ -18,6 +18,8 @@
#import <Cocoa/Cocoa.h>
+#import "utils/errors.h"
+
#import "cocoa/schedule.h"
@interface ScheduledCallback : NSObject {
diff --git a/windows/schedule.c b/windows/schedule.c
index f819918..4aac981 100644
--- a/windows/schedule.c
+++ b/windows/schedule.c
@@ -19,10 +19,11 @@
#include <sys/time.h>
#include <time.h>
-#include "windows/schedule.h"
-
#include "utils/log.h"
#include "utils/utils.h"
+#include "utils/errors.h"
+
+#include "windows/schedule.h"
#ifdef DEBUG_SCHEDULER
#define SRLOG(x) LOG(x)
@@ -110,7 +111,7 @@ nserror win32_schedule(int ival, void (*callback)(void *p), void *p)
}
tv.tv_sec = ival / 1000; /* miliseconds to seconds */
- tv.tv_usec = (cs_ival % 1000) * 1000; /* remainder to microseconds */
+ tv.tv_usec = (ival % 1000) * 1000; /* remainder to microseconds */
nscb = calloc(1, sizeof(struct nscallback));
if (nscb == NULL) {
--
NetSurf Browser
8 years, 11 months
netsurf: branch master updated. release/3.0-1138-g87f6314
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/87f6314dabdc2067a19e0...
...commit http://git.netsurf-browser.org/netsurf.git/commit/87f6314dabdc2067a19e01f...
...tree http://git.netsurf-browser.org/netsurf.git/tree/87f6314dabdc2067a19e01f8b...
The branch, master has been updated
via 87f6314dabdc2067a19e01f8b29f9ecc38ed825b (commit)
from fb9b171e325488dc9792ee0f3062f15d8ec597ee (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=87f6314dabdc2067a19...
commit 87f6314dabdc2067a19e01f8b29f9ecc38ed825b
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
move scheduleing into browser operation table
diff --git a/amiga/font.c b/amiga/font.c
index 3430a4e..df4a188 100755
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -23,12 +23,12 @@
#include "amiga/gui.h"
#include "amiga/utf8.h"
#include "amiga/object.h"
+#include "amiga/schedule.h"
#include "utils/nsoption.h"
#include "css/css.h"
#include "css/utils.h"
#include "render/font.h"
#include "utils/log.h"
-#include "utils/schedule.h"
#include "utils/utf8.h"
#include "utils/utils.h"
@@ -831,7 +831,7 @@ void ami_init_fonts(void)
NewList(&ami_diskfontlib_list);
/* run first cleanup in ten minutes */
- schedule(60000, (schedule_callback_fn)ami_font_cleanup, ami_font_list);
+ ami_schedule(600000, ami_font_cleanup, ami_font_list);
}
void ami_close_fonts(void)
@@ -875,7 +875,7 @@ static void ami_font_cleanup(struct MinList *ami_font_list)
}while(node=nnode);
/* reschedule to run in five minutes */
- schedule(30000, (schedule_callback_fn)ami_font_cleanup, ami_font_list);
+ ami_schedule(300000, ami_font_cleanup, ami_font_list);
}
void ami_font_setdevicedpi(int id)
diff --git a/amiga/gui.c b/amiga/gui.c
index aedb26c..84e9dc9 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -2538,7 +2538,7 @@ static void ami_gui_fetch_callback(void *p)
static void gui_poll(bool active)
{
- if(active) schedule(0, ami_gui_fetch_callback, NULL);
+ if(active) ami_schedule(0, ami_gui_fetch_callback, NULL);
ami_get_msg();
}
@@ -4050,19 +4050,19 @@ static void ami_redraw_callback(void *p)
*/
void ami_schedule_redraw(struct gui_window_2 *gwin, bool full_redraw)
{
- int cs = 0;
+ int ms = 0;
if(full_redraw) gwin->redraw_required = true;
if(gwin->redraw_scheduled == true) return;
- if(gwin->bw->reformat_pending) cs = nsoption_int(reformat_delay);
- schedule(cs, ami_redraw_callback, gwin);
+ if(gwin->bw->reformat_pending) ms = nsoption_int(reformat_delay) * 10;
+ ami_schedule(ms, ami_redraw_callback, gwin);
gwin->redraw_scheduled = true;
}
static void ami_schedule_redraw_remove(struct gui_window_2 *gwin)
{
- schedule_remove(ami_redraw_callback, gwin);
+ ami_schedule(-1, ami_redraw_callback, gwin);
}
static void ami_do_redraw_tiled(struct gui_window_2 *gwin, bool busy,
@@ -5133,6 +5133,7 @@ static struct gui_fetch_table amiga_fetch_table = {
static struct gui_browser_table amiga_browser_table = {
.poll = gui_poll,
+ .schedule = ami_schedule,
.quit = gui_quit,
.set_search_ico = gui_set_search_ico,
diff --git a/amiga/menu.c b/amiga/menu.c
index 2c019bd..9cb857e 100644
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -58,12 +58,13 @@
#include "amiga/theme.h"
#include "amiga/tree.h"
#include "amiga/utf8.h"
+#include "amiga/schedule.h"
#include "desktop/hotlist.h"
#include "desktop/browser_private.h"
#include "desktop/gui.h"
#include "desktop/textinput.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
+
enum {
NSA_GLYPH_SUBMENU,
@@ -481,7 +482,11 @@ struct NewMenu *ami_create_menu(struct gui_window_2 *gwin)
/* Set up scheduler to refresh the hotlist menu */
if(nsoption_int(menu_refresh) > 0)
- schedule(nsoption_int(menu_refresh), (void *)ami_menu_refresh, gwin);
+ {
+ ami_schedule(nsoption_int(menu_refresh) * 10,
+ ami_menu_refresh,
+ gwin);
+ }
return(gwin->menu);
}
diff --git a/amiga/schedule.c b/amiga/schedule.c
index d4b35a5..4ec9df7 100755
--- a/amiga/schedule.c
+++ b/amiga/schedule.c
@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "utils/schedule.h"
#include "amiga/os3support.h"
#include "amiga/schedule.h"
@@ -37,51 +36,18 @@ struct nscallback
PblHeap *schedule_list;
-void ami_remove_timer_event(struct nscallback *nscb);
-
-/**
- * Schedule a callback.
- *
- * \param t interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-
-void schedule(int t, void (*callback)(void *p), void *p)
+static void ami_remove_timer_event(struct nscallback *nscb)
{
- struct nscallback *nscb;
- struct TimeVal tv;
- ULONG time_us = 0;
-
- if(schedule_list == NULL) return;
-
- nscb = AllocVecTagList(sizeof(struct nscallback), NULL);
if(!nscb) return;
- time_us = t*10000; /* t converted to �s */
-
- nscb->tv.Seconds = time_us / 1000000;
- nscb->tv.Microseconds = time_us % 1000000;
-
- GetSysTime(&tv);
- AddTime(&nscb->tv,&tv); // now contains time when event occurs
-
- if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL))
+ if(nscb->treq)
{
- *nscb->treq = *tioreq;
- nscb->treq->Request.io_Command=TR_ADDREQUEST;
- nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs
- nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro
- SendIO((struct IORequest *)nscb->treq);
- }
-
- nscb->callback = callback;
- nscb->p = p;
+ if(CheckIO((struct IORequest *)nscb->treq)==NULL)
+ AbortIO((struct IORequest *)nscb->treq);
- pblHeapInsert(schedule_list, nscb);
+ WaitIO((struct IORequest *)nscb->treq);
+ FreeVec(nscb->treq);
+ }
}
/**
@@ -93,14 +59,22 @@ void schedule(int t, void (*callback)(void *p), void *p)
* All scheduled callbacks matching both callback and p are removed.
*/
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
PblIterator *iterator;
struct nscallback *nscb;
bool restoreheap = false;
- if(schedule_list == NULL) return;
- if(pblHeapIsEmpty(schedule_list)) return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL)
+ {
+ return NSERROR_OK;
+ }
+
+ if(pblHeapIsEmpty(schedule_list))
+ {
+ return NSERROR_OK;
+ }
iterator = pblHeapIterator(schedule_list);
@@ -117,10 +91,15 @@ void schedule_remove(void (*callback)(void *p), void *p)
pblIteratorFree(iterator);
- if(restoreheap) pblHeapConstruct(schedule_list);
+ if(restoreheap)
+ {
+ pblHeapConstruct(schedule_list);
+ }
+
+ return NSERROR_OK;
}
-void schedule_remove_all(void)
+static void schedule_remove_all(void)
{
PblIterator *iterator;
struct nscallback *nscb;
@@ -139,13 +118,16 @@ void schedule_remove_all(void)
pblIteratorFree(iterator);
}
-/**
- * Process events up to current time.
- * This implementation only takes the top entry off the heap, it does not
- * venture to later scheduled events until the next time it is called -
- * immediately afterwards, if we're in a timer signalled loop.
- */
+static int ami_schedule_compare(const void *prev, const void *next)
+{
+ struct nscallback *nscb1 = *(struct nscallback **)prev;
+ struct nscallback *nscb2 = *(struct nscallback **)next;
+
+ return CmpTime(&nscb1->tv, &nscb2->tv);
+}
+
+/* exported function documented in amiga/schedule.h */
void schedule_run(BOOL poll)
{
struct nscallback *nscb;
@@ -176,28 +158,7 @@ void schedule_run(BOOL poll)
callback(p);
}
-void ami_remove_timer_event(struct nscallback *nscb)
-{
- if(!nscb) return;
-
- if(nscb->treq)
- {
- if(CheckIO((struct IORequest *)nscb->treq)==NULL)
- AbortIO((struct IORequest *)nscb->treq);
-
- WaitIO((struct IORequest *)nscb->treq);
- FreeVec(nscb->treq);
- }
-}
-
-int ami_schedule_compare(const void *prev, const void *next)
-{
- struct nscallback *nscb1 = *(struct nscallback **)prev;
- struct nscallback *nscb2 = *(struct nscallback **)next;
-
- return CmpTime(&nscb1->tv, &nscb2->tv);
-}
-
+/* exported function documented in amiga/schedule.h */
BOOL ami_schedule_create(void)
{
schedule_list = pblHeapNew();
@@ -206,6 +167,7 @@ BOOL ami_schedule_create(void)
pblHeapSetCompareFunction(schedule_list, ami_schedule_compare);
}
+/* exported function documented in amiga/schedule.h */
void ami_schedule_free(void)
{
schedule_remove_all();
@@ -213,6 +175,7 @@ void ami_schedule_free(void)
schedule_list = NULL;
}
+/* exported function documented in amiga/schedule.h */
void ami_schedule_open_timer(void)
{
msgport = AllocSysObjectTags(ASOT_PORT,
@@ -231,6 +194,7 @@ void ami_schedule_open_timer(void)
ITimer = (struct TimerIFace *)GetInterface((struct Library *)TimerBase,"main",1,NULL);
}
+/* exported function documented in amiga/schedule.h */
void ami_schedule_close_timer(void)
{
if(ITimer)
@@ -242,3 +206,51 @@ void ami_schedule_close_timer(void)
FreeSysObject(ASOT_IOREQUEST,tioreq);
FreeSysObject(ASOT_PORT,msgport);
}
+
+/* exported function documented in amiga/schedule.h */
+nserror ami_schedule(int t, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct TimeVal tv;
+ ULONG time_us = 0;
+
+ if(schedule_list == NULL)
+ {
+ return NSERROR_INIT_FAILED;
+ }
+
+ if(t < 0)
+ {
+ return schedule_remove(callback, p);
+ }
+
+ nscb = AllocVecTagList(sizeof(struct nscallback), NULL);
+ if(!nscb)
+ {
+ return NSERROR_NOMEM;
+ }
+
+ time_us = t * 1000; /* t converted to �s */
+
+ nscb->tv.Seconds = time_us / 1000000;
+ nscb->tv.Microseconds = time_us % 1000000;
+
+ GetSysTime(&tv);
+ AddTime(&nscb->tv,&tv); // now contains time when event occurs
+
+ if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL))
+ {
+ *nscb->treq = *tioreq;
+ nscb->treq->Request.io_Command=TR_ADDREQUEST;
+ nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs
+ nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro
+ SendIO((struct IORequest *)nscb->treq);
+ }
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ pblHeapInsert(schedule_list, nscb);
+
+ return NSERROR_OK;
+}
diff --git a/amiga/schedule.h b/amiga/schedule.h
index 3eddc89..6592306 100755
--- a/amiga/schedule.h
+++ b/amiga/schedule.h
@@ -19,7 +19,6 @@
#ifndef AMIGA_SCHEDULE_H
#define AMIGA_SCHEDULE_H
#include <proto/timer.h>
-#include "utils/schedule.h"
#include "amiga/os3support.h"
struct Device *TimerBase;
@@ -28,9 +27,42 @@ struct TimerIFace *ITimer;
struct TimeRequest *tioreq;
struct MsgPort *msgport;
-void ami_schedule_open_timer(void);
-void ami_schedule_close_timer(void);
+/**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made / ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ * \return NSERROR_OK on sucess or appropriate error on faliure
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror ami_schedule(int t, void (*callback)(void *p), void *p);
+
+/**
+ * Initialise amiga scheduler
+ *
+ * /return true if initialised ok or false on error.
+ */
BOOL ami_schedule_create(void);
+
+/**
+ * Finalise amiga scheduler
+ *
+ */
void ami_schedule_free(void);
+
+/**
+ * Process events up to current time.
+ *
+ * This implementation only takes the top entry off the heap, it does not
+ * venture to later scheduled events until the next time it is called -
+ * immediately afterwards, if we're in a timer signalled loop.
+ */
void schedule_run(BOOL poll);
+
+void ami_schedule_open_timer(void);
+void ami_schedule_close_timer(void);
+
#endif
diff --git a/amiga/tree.c b/amiga/tree.c
index 8cffdb2..fa12528 100644
--- a/amiga/tree.c
+++ b/amiga/tree.c
@@ -1390,11 +1390,11 @@ void ami_tree_redraw_request(int x, int y, int width, int height, void *data)
atrr_data->height = height;
atrr_data->twin = (struct treeview_window *)data;
- /**TODO: Queue these requests properly like the main browser code does
+ /** /todo Queue these requests properly like the main browser code does
**/
if(nsoption_bool(direct_render) == false)
- schedule(0, ami_tree_redraw_req, atrr_data);
+ ami_schedule(0, ami_tree_redraw_req, atrr_data);
else
- schedule(0, ami_tree_redraw_req_dr, atrr_data);
+ am_schedule(0, ami_tree_redraw_req_dr, atrr_data);
}
diff --git a/atari/gui.c b/atari/gui.c
index df02973..d838644 100644
--- a/atari/gui.c
+++ b/atari/gui.c
@@ -30,7 +30,6 @@
#include <stdbool.h>
#include <hubbub/hubbub.h>
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/log.h"
#include "utils/messages.h"
@@ -597,7 +596,7 @@ static void throbber_advance( void * data )
return;
toolbar_throbber_progress(gw->root->toolbar);
- schedule(100, throbber_advance, gw );
+ atari_schedule(1000, throbber_advance, gw );
}
static void gui_window_start_throbber(struct gui_window *w)
@@ -607,7 +606,7 @@ static void gui_window_start_throbber(struct gui_window *w)
return;
toolbar_set_throbber_state(w->root->toolbar, true);
- schedule(100, throbber_advance, w );
+ atari_schedule(1000, throbber_advance, w );
rendering = true;
}
@@ -618,7 +617,7 @@ static void gui_window_stop_throbber(struct gui_window *w)
if (w->root->toolbar->throbber.running == false)
return;
- schedule_remove(throbber_advance, w);
+ atari_schedule(-1, throbber_advance, w);
toolbar_set_throbber_state(w->root->toolbar, false);
@@ -1084,6 +1083,7 @@ static struct gui_fetch_table atari_fetch_table = {
static struct gui_browser_table atari_browser_table = {
.poll = gui_poll,
+ .schedule = atari_schedule,
.quit = gui_quit,
.cert_verify = gui_cert_verify,
diff --git a/atari/schedule.c b/atari/schedule.c
index a91c510..02a3762 100755
--- a/atari/schedule.c
+++ b/atari/schedule.c
@@ -22,12 +22,15 @@
#include <sys/time.h>
#include <time.h>
-#include "utils/schedule.h"
#include "atari/schedule.h"
+#ifdef DEBUG_SCHEDULER
#include "utils/log.h"
+#else
+#define LOG(X)
+#endif
-#define CS_NOW() ((clock() * 100) / CLOCKS_PER_SEC)
+#define MS_NOW() ((clock() * 1000) / CLOCKS_PER_SEC)
/* linked list of scheduled callbacks */
static struct nscallback *schedule_list = NULL;
@@ -47,45 +50,6 @@ static int max_scheduled;
static int cur_scheduled;
/**
- * Schedule a callback.
- *
- * \param tival interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-void schedule( int cs_ival, void (*callback)(void *p), void *p)
-{
- struct nscallback *nscb;
-
- /*
- remove any callback of this kind,
- other frontend do this, too. framebuffer frontend doesn't do it.
- */
- schedule_remove(callback, p);
-
- nscb = calloc(1, sizeof(struct nscallback));
-
- nscb->timeout = CS_NOW() + cs_ival;
-#ifdef DEBUG_SCHEDULER
- LOG(("adding callback %p for %p(%p) at %d cs", nscb, callback, p, nscb->timeout ));
-#endif
- nscb->callback = callback;
- nscb->p = p;
-
- /* add to list front */
- nscb->next = schedule_list;
- schedule_list = nscb;
- cur_scheduled++;
- if( cur_scheduled > max_scheduled )
- max_scheduled = cur_scheduled;
-}
-
-
-
-/**
* Unschedule a callback.
*
* \param callback callback function
@@ -94,18 +58,18 @@ void schedule( int cs_ival, void (*callback)(void *p), void *p)
* All scheduled callbacks matching both callback and p are removed.
*/
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- if (schedule_list == NULL)
- return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
-#ifdef DEBUG_SCHEDULER
LOG(("removing %p, %p", callback, p));
-#endif
cur_nscb = schedule_list;
prev_nscb = NULL;
@@ -114,9 +78,8 @@ void schedule_remove(void (*callback)(void *p), void *p)
if ((cur_nscb->callback == callback) &&
(cur_nscb->p == p)) {
/* item to remove */
-#ifdef DEBUG_SCHEDULER
- LOG(("callback entry %p removing %p(%p)", cur_nscb, cur_nscb->callback, cur_nscb->p));
-#endif
+ LOG(("callback entry %p removing %p(%p)",
+ cur_nscb, cur_nscb->callback, cur_nscb->p));
/* remove callback */
unlnk_nscb = cur_nscb;
@@ -135,20 +98,51 @@ void schedule_remove(void (*callback)(void *p), void *p)
cur_nscb = prev_nscb->next;
}
}
+ return NSERROR_OK;
+}
+
+/* exported function documented in atari/schedule.h */
+nserror atari_schedule(int ival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ nserror ret;
+
+ /* remove any existing callback of this kind */
+ ret = schedule_remove(callback, p);
+ if ((ival < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ nscb = calloc(1, sizeof(struct nscallback));
+
+ nscb->timeout = MS_NOW() + ival;
+
+ LOG(("adding callback %p for %p(%p) at %d ms",
+ nscb, callback, p, nscb->timeout ));
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+ cur_scheduled++;
+ if( cur_scheduled > max_scheduled ) {
+ max_scheduled = cur_scheduled;
+ }
+
+ return NSERROR_OK;
}
-/**
- * Process events up to current time.
- */
-int
-schedule_run(void)
+/* exported function documented in atari/schedule.h */
+int schedule_run(void)
{
unsigned long nexttime;
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- unsigned long now = CS_NOW();
+ unsigned long now = MS_NOW();
if (schedule_list == NULL)
return -1;
@@ -170,9 +164,9 @@ schedule_run(void)
prev_nscb->next = unlnk_nscb->next;
}
-#ifdef DEBUG_SCHEDULER
- LOG(("callback entry %p running %p(%p)", unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
-#endif
+ LOG(("callback entry %p running %p(%p)",
+ unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
+
/* call callback */
unlnk_nscb->callback(unlnk_nscb->p);
free(unlnk_nscb);
@@ -180,9 +174,8 @@ schedule_run(void)
/* need to deal with callback modifying the list. */
if (schedule_list == NULL) {
-#ifdef DEBUG_SCHEDULER
LOG(("schedule_list == NULL"));
-#endif
+
return -1; /* no more callbacks scheduled */
}
@@ -204,21 +197,22 @@ schedule_run(void)
}
/* make rettime relative to now and convert to ms */
- nexttime = (nexttime - now)*10;
-#ifdef DEBUG_SCHEDULER
+ nexttime = nexttime - now;
+
LOG(("returning time to next event as %ldms", nexttime ));
-#endif
+
/*return next event time in milliseconds (24days max wait) */
- return ( nexttime );
+ return nexttime;
}
+/* exported function documented in atari/schedule.h */
void list_schedule(void)
{
struct timeval tv;
struct nscallback *cur_nscb;
- LOG(("schedule list at cs clock %ld", CS_NOW() ));
+ LOG(("schedule list at ms clock %ld", MS_NOW() ));
cur_nscb = schedule_list;
while (cur_nscb != NULL) {
diff --git a/atari/schedule.h b/atari/schedule.h
index e21b759..47d8c2d 100755
--- a/atari/schedule.h
+++ b/atari/schedule.h
@@ -17,10 +17,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NS_SCHEDULE_H
-#define NS_SCHEDULE_H
+#ifndef NS_ATARI_SCHEDULE_H
+#define NS_ATARI_SCHEDULE_H
-void list_schedule(void);
+/**
+ * Process events up to current time.
+ */
int schedule_run(void);
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror atari_schedule(int cs_ival, void (*callback)(void *p), void *p);
+
+/**
+ * LOG all current scheduled events.
+ */
+void list_schedule(void);
+
#endif
diff --git a/beos/gui.cpp b/beos/gui.cpp
index 646356a..365a356 100644
--- a/beos/gui.cpp
+++ b/beos/gui.cpp
@@ -1049,6 +1049,7 @@ static struct gui_fetch_table beos_fetch_table = {
static struct gui_browser_table beos_browser_table = {
gui_poll,
+ beos_schedule,
gui_quit,
NULL, //set_search_ico
gui_launch_url,
diff --git a/beos/gui.h b/beos/gui.h
index 24223a1..642441f 100644
--- a/beos/gui.h
+++ b/beos/gui.h
@@ -51,9 +51,6 @@ virtual void AboutRequested();
virtual bool QuitRequested();
};
-
-extern void schedule_run(void);
-
extern BWindow *wndAbout;
extern BWindow *wndTooltip;
diff --git a/beos/scaffolding.cpp b/beos/scaffolding.cpp
index fa9549c..35153b3 100644
--- a/beos/scaffolding.cpp
+++ b/beos/scaffolding.cpp
@@ -62,7 +62,6 @@ extern "C" {
#include "render/font.h"
#include "render/form.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
#include "utils/log.h"
}
@@ -75,7 +74,7 @@ extern "C" {
//#include "beos/completion.h"
#include "beos/throbber.h"
#include "beos/window.h"
-//#include "beos/schedule.h"
+#include "beos/schedule.h"
//#include "beos/download.h"
#define TOOLBAR_HEIGHT 32
@@ -1324,7 +1323,7 @@ void nsbeos_throb(void *p)
g->top_view->UnlockLooper();
- schedule(10, nsbeos_throb, p);
+ beos_schedule(100, nsbeos_throb, p);
}
@@ -2190,7 +2189,7 @@ void gui_window_start_throbber(struct gui_window* _g)
nsbeos_window_update_back_forward(g);
- schedule(10, nsbeos_throb, g);
+ beos_schedule(100, nsbeos_throb, g);
}
void gui_window_stop_throbber(struct gui_window* _g)
@@ -2199,7 +2198,7 @@ void gui_window_stop_throbber(struct gui_window* _g)
nsbeos_window_update_back_forward(g);
- schedule_remove(nsbeos_throb, g);
+ beos_schedule(-1, nsbeos_throb, g);
if (!g->top_view->LockLooper())
return;
diff --git a/beos/schedule.cpp b/beos/schedule.cpp
index db0992e..75e3490 100644
--- a/beos/schedule.cpp
+++ b/beos/schedule.cpp
@@ -23,7 +23,7 @@
#include <List.h>
extern "C" {
-#include "utils/schedule.h"
+#include "beos/schedule.h"
#include "desktop/browser.h"
#ifdef DEBUG_BEOS_SCHEDULE
@@ -65,7 +65,7 @@ nsbeos_schedule_kill_callback(void *_target, void *_match)
return false;
}
-void
+static void
schedule_remove(void (*callback)(void *p), void *p)
{
LOG(("schedule_remove() for %p(%p)", cb->callback, cb->context));
@@ -75,22 +75,26 @@ schedule_remove(void (*callback)(void *p), void *p)
cb_match.callback = callback;
cb_match.context = p;
-
callbacks->DoForEach(nsbeos_schedule_kill_callback, &cb_match);
}
-void
-schedule(int t, void (*callback)(void *p), void *p)
+nserror beos_schedule(int t, void (*callback)(void *p), void *p)
{
- LOG(("schedule(%d, %p, %p)", t, cb->callback, cb->context));
- if (callbacks == NULL)
+ LOG(("t:%d cb:%p p:%p", t, cb->callback, cb->context));
+
+ if (callbacks == NULL) {
callbacks = new BList;
+ }
- bigtime_t timeout = system_time() + t * 10 * 1000LL;
- const int msec_timeout = t * 10;
- _nsbeos_callback_t *cb = (_nsbeos_callback_t *)malloc(sizeof(_nsbeos_callback_t));
/* Kill any pending schedule of this kind. */
schedule_remove(callback, p);
+
+ if (t < 0) {
+ return NSERROR_OK;
+ }
+
+ bigtime_t timeout = system_time() + t * 1000LL;
+ _nsbeos_callback_t *cb = (_nsbeos_callback_t *)malloc(sizeof(_nsbeos_callback_t));
cb->callback = callback;
cb->context = p;
cb->callback_killed = cb->callback_fired = false;
@@ -99,6 +103,8 @@ schedule(int t, void (*callback)(void *p), void *p)
earliest_callback_timeout = timeout;
}
callbacks->AddItem(cb);
+
+ return NSERROR_OK;
}
bool
diff --git a/beos/schedule.h b/beos/schedule.h
index 02205ba..a446156 100644
--- a/beos/schedule.h
+++ b/beos/schedule.h
@@ -19,8 +19,11 @@
#ifndef NETSURF_BEOS_CALLBACK_H
#define NETSURF_BEOS_CALLBACK_H 1
-typedef void (*beos_callback)(void *p);
-
extern bigtime_t earliest_callback_timeout;
+extern nserror beos_schedule(int t, void (*callback)(void *p), void *p);
+
+extern void schedule_run(void);
+
+
#endif /* NETSURF_BEOS_CALLBACK_H */
diff --git a/cocoa/apple_image.m b/cocoa/apple_image.m
index ab17f8a..c6f9df3 100644
--- a/cocoa/apple_image.m
+++ b/cocoa/apple_image.m
@@ -25,7 +25,8 @@
#include "image/bitmap.h"
#include "desktop/plotters.h"
#include "utils/utils.h"
-#include "utils/schedule.h"
+
+#include "cocoa/schedule.h"
typedef struct apple_image_content {
struct content base;
@@ -147,7 +148,7 @@ static void animate_image_cb( void *ptr )
data.redraw.object = &ai->base;
content_broadcast( &ai->base, CONTENT_MSG_REDRAW, data );
- schedule( ai->frameTimes[ai->currentFrame], animate_image_cb, ai );
+ cocoa_schedule(ai->frameTimes[ai->currentFrame], animate_image_cb, ai );
}
/**
@@ -190,10 +191,10 @@ bool apple_image_convert(struct content *c)
ai->frameTimes = calloc( ai->frames , sizeof(int));
for (NSUInteger i = 0; i < frames; i++) {
[image setProperty: NSImageCurrentFrame withValue: [NSNumber numberWithUnsignedInteger: i]];
- ai->frameTimes[i] = 100 * [[image valueForProperty: NSImageCurrentFrameDuration] floatValue];
+ ai->frameTimes[i] = 1000 * [[image valueForProperty: NSImageCurrentFrameDuration] floatValue];
}
[image setProperty: NSImageCurrentFrame withValue: [NSNumber numberWithUnsignedInteger: 0]];
- schedule( ai->frameTimes[0], animate_image_cb, ai );
+ cocoa_schedule( ai->frameTimes[0], animate_image_cb, ai );
}
return true;
@@ -206,7 +207,7 @@ void apple_image_destroy(struct content *c)
[(id)ai_c->bitmap release];
ai_c->bitmap = NULL;
- schedule_remove( animate_image_cb, c );
+ cocoa_schedule(-1, animate_image_cb, c );
}
diff --git a/cocoa/gui.m b/cocoa/gui.m
index eba3301..9ba6144 100644
--- a/cocoa/gui.m
+++ b/cocoa/gui.m
@@ -25,6 +25,7 @@
#import "cocoa/BrowserWindowController.h"
#import "cocoa/FormSelectMenu.h"
#import "cocoa/fetch.h"
+#import "cocoa/schedule.h"
#import "desktop/gui.h"
#import "desktop/netsurf.h"
@@ -294,6 +295,7 @@ struct gui_window_table *cocoa_window_table = &window_table;
static struct gui_browser_table browser_table = {
.poll = gui_poll,
+ .schedule = cocoa_schedule,
.launch_url = gui_launch_url,
.create_form_select_menu = gui_create_form_select_menu,
diff --git a/cocoa/schedule.h b/cocoa/schedule.h
new file mode 100644
index 0000000..43b2c14
--- /dev/null
+++ b/cocoa/schedule.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Sven Weidauer <sven.weidauer(a)gmail.com>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+nserror cocoa_schedule(int t, void (*callback)(void *p), void *p);
diff --git a/cocoa/schedule.m b/cocoa/schedule.m
index 1ad75b3..2dd9a81 100644
--- a/cocoa/schedule.m
+++ b/cocoa/schedule.m
@@ -17,7 +17,8 @@
*/
#import <Cocoa/Cocoa.h>
-#import "utils/schedule.h"
+
+#import "cocoa/schedule.h"
@interface ScheduledCallback : NSObject {
void (*callback)( void *userData );
@@ -73,18 +74,15 @@ static NSMutableSet *timerSet = nil;
@end
-/* In platform specific schedule.c. */
-void schedule(int t, void (*callback)(void *p), void *p)
-{
- ScheduledCallback *cb = [[ScheduledCallback alloc] initWithCallback: callback userData: p];
- [cb schedule: (NSTimeInterval)t / 100];
- [cb release];
-}
-
-void schedule_remove(void (*callback)(void *p), void *p)
+/* exported interface documented in cocoa/schedule.h */
+nserror cocoa_schedule(int t, void (*callback)(void *p), void *p)
{
ScheduledCallback *cb = [[ScheduledCallback alloc] initWithCallback: callback userData: p];
[timerSet removeObject: cb];
+ if (t >= 0) {
+ [cb schedule: (NSTimeInterval)t / 1000];
+ }
[cb release];
-}
+ return NSERROR_OK;
+}
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index d58b7d5..612b77d 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -36,25 +36,25 @@
#include <strings.h>
#include <time.h>
#include <sys/stat.h>
+#include <openssl/ssl.h>
#include <libwapcaplet/libwapcaplet.h>
#include "utils/config.h"
-#include <openssl/ssl.h>
-#include "content/fetch.h"
-#include "content/fetchers/curl.h"
-#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/gui_factory.h"
#include "utils/corestrings.h"
#include "utils/nsoption.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
#include "utils/ring.h"
#include "utils/useragent.h"
+#include "content/fetch.h"
+#include "content/fetchers/curl.h"
+#include "content/urldb.h"
+
/* uncomment this to use scheduler based calling
#define FETCHER_CURLL_SCHEDULED 1
*/
@@ -504,7 +504,7 @@ bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
codem = curl_multi_add_handle(fetch_curl_multi, fetch->curl_handle);
assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
- schedule(1, (schedule_callback_fn)fetch_curl_poll, NULL);
+ guit->browser->schedule(10, (void *)fetch_curl_poll, NULL);
return true;
}
@@ -837,7 +837,7 @@ void fetch_curl_poll(lwc_string *scheme_ignored)
#ifdef FETCHER_CURLL_SCHEDULED
if (running != 0) {
- schedule(1, (schedule_callback_fn)fetch_curl_poll, fetch_curl_poll);
+ guit->browser->schedule(10, fetch_curl_poll, fetch_curl_poll);
}
#endif
}
diff --git a/content/hlcache.c b/content/hlcache.c
index 618f4fd..16f9697 100644
--- a/content/hlcache.c
+++ b/content/hlcache.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
+#include "desktop/gui_factory.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "content/mimesniff.h"
@@ -31,7 +32,6 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/ring.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/utils.h"
@@ -146,7 +146,7 @@ static void hlcache_clean(void *ignored)
llcache_clean();
/* Re-schedule ourselves */
- schedule(hlcache->params.bg_clean_time / 10, hlcache_clean, NULL);
+ guit->browser->schedule(hlcache->params.bg_clean_time, hlcache_clean, NULL);
}
/**
@@ -536,7 +536,7 @@ hlcache_initialise(const struct hlcache_parameters *hlcache_parameters)
hlcache->params = *hlcache_parameters;
/* Schedule the cache cleanup */
- schedule(hlcache->params.bg_clean_time / 10, hlcache_clean, NULL);
+ guit->browser->schedule(hlcache->params.bg_clean_time, hlcache_clean, NULL);
return NSERROR_OK;
}
@@ -545,7 +545,7 @@ hlcache_initialise(const struct hlcache_parameters *hlcache_parameters)
void hlcache_stop(void)
{
/* Remove the hlcache_clean schedule */
- schedule_remove(hlcache_clean, NULL);
+ guit->browser->schedule(-1, hlcache_clean, NULL);
}
/* See hlcache.h for documentation */
diff --git a/desktop/browser.c b/desktop/browser.c
index 03c7a8e..b1e4b75 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -63,7 +63,6 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsurl.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/utils.h"
#include "utils/utf8.h"
@@ -1327,9 +1326,10 @@ static nserror browser_window_callback(hlcache_handle *c,
browser_window_history_update(bw, c);
hotlist_update_url(hlcache_handle_get_url(c));
- if (bw->refresh_interval != -1)
- schedule(bw->refresh_interval,
+ if (bw->refresh_interval != -1) {
+ guit->browser->schedule(bw->refresh_interval * 10,
browser_window_refresh, bw);
+ }
break;
case CONTENT_MSG_ERRORCODE:
@@ -1620,10 +1620,11 @@ void browser_window_destroy_internal(struct browser_window *bw)
LOG(("Destroying window"));
- if (bw->children != NULL || bw->iframes != NULL)
+ if (bw->children != NULL || bw->iframes != NULL) {
browser_window_destroy_children(bw);
+ }
- schedule_remove(browser_window_refresh, bw);
+ guit->browser->schedule(-1, browser_window_refresh, bw);
/* If this brower window is not the root window, and has focus, unset
* the root browser window's focus pointer. */
@@ -2208,7 +2209,7 @@ void browser_window_stop(struct browser_window *bw)
assert(error == NSERROR_OK);
}
- schedule_remove(browser_window_refresh, bw);
+ guit->browser->schedule(-1, browser_window_refresh, bw);
if (bw->children) {
children = bw->rows * bw->cols;
diff --git a/desktop/gui.h b/desktop/gui.h
index 85f1265..361c6bd 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -75,7 +75,8 @@ typedef struct nsnsclipboard_styles {
plot_font_style_t style; /**< Style to give text run */
} nsclipboard_styles;
-/** Graphical user interface window function table
+/**
+ * Graphical user interface window function table.
*
* function table implementing window operations
*/
@@ -176,7 +177,9 @@ struct gui_window_table {
*/
void (*set_title)(struct gui_window *g, const char *title);
- /** set the navigation url. */
+ /**
+ * set the navigation url.
+ */
void (*set_url)(struct gui_window *g, const char *url);
/** set favicon */
@@ -209,7 +212,7 @@ struct gui_window_table {
/**
* Remove the caret, if present.
*
- * \param g window with caret
+ * \param g window with caret
*/
void (*remove_caret)(struct gui_window *g);
@@ -269,8 +272,9 @@ struct gui_window_table {
void (*start_selection)(struct gui_window *g);
};
+
/**
- * function table for download windows
+ * function table for download windows.
*/
struct gui_download_table {
struct gui_download_window *(*create)(struct download_context *ctx, struct gui_window *parent);
@@ -282,8 +286,9 @@ struct gui_download_table {
void (*done)(struct gui_download_window *dw);
};
+
/**
- * function table for clipboard operations
+ * function table for clipboard operations.
*/
struct gui_clipboard_table {
/**
@@ -305,6 +310,7 @@ struct gui_clipboard_table {
void (*set)(const char *buffer, size_t length, nsclipboard_styles styles[], int n_styles);
};
+
/**
* function table for fetcher operations
*/
@@ -390,8 +396,9 @@ struct gui_fetch_table {
};
+
/**
- * User interface utf8 characterset conversion routines
+ * User interface utf8 characterset conversion routines.
*/
struct gui_utf8_table {
/**
@@ -415,7 +422,9 @@ struct gui_utf8_table {
nserror (*local_to_utf8)(const char *string, size_t len, char **result);
};
-/** Graphical user interface browser misc function table
+
+/**
+ * Graphical user interface browser misc function table.
*
* function table implementing GUI interface to miscelaneous browser
* functionality
@@ -429,6 +438,23 @@ struct gui_browser_table {
*/
void (*poll)(bool active);
+ /**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made in ms or
+ * negative value to remove any existing callback.
+ * \param callback callback function
+ * \param p user parameter passed to callback function
+ * \return NSERROR_OK on sucess or appropriate error on faliure
+ *
+ * The callback function will be called as soon as possible
+ * after the timeout has elapsed.
+ *
+ * Additional calls with the same callback and user parameter will
+ * reset the callback time to the newly specified value.
+ *
+ */
+ nserror (*schedule)(int t, void (*callback)(void *p), void *p);
/* Optional entries */
@@ -474,7 +500,8 @@ struct gui_browser_table {
*/
struct gui_table {
- /** Browser table.
+ /**
+ * Browser table.
*
* Provides miscellaneous browser functionality. The table
* is mandantory and must be provided.
@@ -493,7 +520,8 @@ struct gui_table {
/** Fetcher table */
struct gui_fetch_table *fetch;
- /** UTF8 table
+ /**
+ * UTF8 table.
*
* Provides for conversion between the gui local character
* encoding and utf8. The table optional and may be NULL which
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index 8996ab5..638abfd 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -443,6 +443,10 @@ static nserror verify_browser_register(struct gui_browser_table *gbt)
return NSERROR_BAD_PARAMETER;
}
+ if (gbt->schedule == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
/* fill in the optional entries with defaults */
if (gbt->quit == NULL) {
gbt->quit = gui_default_quit;
diff --git a/framebuffer/gui.c b/framebuffer/gui.c
index cee58b9..7d3e95c 100644
--- a/framebuffer/gui.c
+++ b/framebuffer/gui.c
@@ -40,7 +40,6 @@
#include "utils/filepath.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/types.h"
#include "desktop/textinput.h"
#include "render/form.h"
@@ -557,7 +556,7 @@ static bool nslog_stream_configure(FILE *fptr)
-static void gui_poll(bool active)
+static void framebuffer_poll(bool active)
{
nsfb_event_t event;
int timeout; /* timeout in miliseconds */
@@ -1696,7 +1695,7 @@ throbber_advance(void *pw)
if (g->throbber_index >= 0) {
fbtk_set_bitmap(g->throbber, image);
- schedule(10, throbber_advance, g);
+ framebuffer_schedule(100, throbber_advance, g);
}
}
@@ -1704,7 +1703,7 @@ static void
gui_window_start_throbber(struct gui_window *g)
{
g->throbber_index = 0;
- schedule(10, throbber_advance, g);
+ framebuffer_schedule(100, throbber_advance, g);
}
static void
@@ -1785,7 +1784,8 @@ static struct gui_window_table framebuffer_window_table = {
static struct gui_browser_table framebuffer_browser_table = {
- .poll = gui_poll,
+ .poll = framebuffer_poll,
+ .schedule = framebuffer_schedule,
.quit = gui_quit,
};
diff --git a/framebuffer/schedule.c b/framebuffer/schedule.c
index 43f5318..151b6f9 100644
--- a/framebuffer/schedule.c
+++ b/framebuffer/schedule.c
@@ -20,10 +20,15 @@
#include <time.h>
#include <stdlib.h>
-#include "utils/schedule.h"
+#include "utils/log.h"
+
#include "framebuffer/schedule.h"
-#include "utils/log.h"
+#ifdef DEBUG_SCHEDULER
+#define SRLOG(x) LOG(x)
+#else
+#define SRLOG(x)
+#endif
/* linked list of scheduled callbacks */
static struct nscallback *schedule_list = NULL;
@@ -39,39 +44,6 @@ struct nscallback
void *p;
};
-
-/**
- * Schedule a callback.
- *
- * \param tival interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-
-void schedule(int cs_ival, void (*callback)(void *p), void *p)
-{
- struct nscallback *nscb;
- struct timeval tv;
-
- tv.tv_sec = cs_ival / 100; /* cs to seconds */
- tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */
-
- nscb = calloc(1, sizeof(struct nscallback));
-
- gettimeofday(&nscb->tv, NULL);
- timeradd(&nscb->tv, &tv, &nscb->tv);
-
- nscb->callback = callback;
- nscb->p = p;
-
- /* add to list front */
- nscb->next = schedule_list;
- schedule_list = nscb;
-}
-
/**
* Unschedule a callback.
*
@@ -80,17 +52,18 @@ void schedule(int cs_ival, void (*callback)(void *p), void *p)
*
* All scheduled callbacks matching both callback and p are removed.
*/
-
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- if (schedule_list == NULL)
- return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
- LOG(("removing %p, %p", callback, p));
+ SRLOG(("removing %p, %p", callback, p));
cur_nscb = schedule_list;
prev_nscb = NULL;
@@ -100,7 +73,7 @@ void schedule_remove(void (*callback)(void *p), void *p)
(cur_nscb->p == p)) {
/* item to remove */
- LOG(("callback entry %p removing %p(%p)",
+ SRLOG(("callback entry %p removing %p(%p)",
cur_nscb, cur_nscb->callback, cur_nscb->p));
/* remove callback */
@@ -119,16 +92,45 @@ void schedule_remove(void (*callback)(void *p), void *p)
cur_nscb = prev_nscb->next;
}
}
+
+ return NSERROR_OK;
}
-/**
- * Process scheduled callbacks up to current time.
- *
- * @return The number of milliseconds untill the next scheduled event
- * or -1 for no event.
- */
-int
-schedule_run(void)
+/* exported function documented in framebuffer/schedule.h */
+nserror framebuffer_schedule(int tival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+ nserror ret;
+
+ /* ensure uniqueness of the callback and context */
+ ret = schedule_remove(callback, p);
+ if ((tival < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ SRLOG(("Adding %p(%p) in %d", callback, p, tival));
+
+ tv.tv_sec = tival / 1000; /* miliseconds to seconds */
+ tv.tv_usec = (tival % 1000) * 1000; /* remainder to microseconds */
+
+ nscb = calloc(1, sizeof(struct nscallback));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in framebuffer/schedule.h */
+int schedule_run(void)
{
struct timeval tv;
struct timeval nexttime;
@@ -188,7 +190,8 @@ schedule_run(void)
/* make rettime relative to now */
timersub(&nexttime, &tv, &rettime);
- /*LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000))); */
+ SRLOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
+
/* return next event time in milliseconds (24days max wait) */
return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
}
diff --git a/framebuffer/schedule.h b/framebuffer/schedule.h
index 2c9b55f..4e94da6 100644
--- a/framebuffer/schedule.h
+++ b/framebuffer/schedule.h
@@ -19,7 +19,27 @@
#ifndef FRAMEBUFFER_SCHEDULE_H
#define FRAMEBUFFER_SCHEDULE_H
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+
+nserror framebuffer_schedule(int tival, void (*callback)(void *p), void *p);
+
+/**
+ * Process scheduled callbacks up to current time.
+ *
+ * @return The number of milliseconds untill the next scheduled event
+ * or -1 for no event.
+ */
int schedule_run(void);
+
void list_schedule(void);
#endif
diff --git a/gtk/gui.c b/gtk/gui.c
index a3bf57c..40c2ad6 100644
--- a/gtk/gui.c
+++ b/gtk/gui.c
@@ -522,7 +522,7 @@ static bool nslog_stream_configure(FILE *fptr)
-static void gui_poll(bool active)
+static void nsgtk_poll(bool active)
{
CURLMcode code;
fd_set read_fd_set, write_fd_set, exc_fd_set;
@@ -990,7 +990,8 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
static struct gui_browser_table nsgtk_browser_table = {
- .poll = gui_poll,
+ .poll = nsgtk_poll,
+ .schedule = nsgtk_schedule,
.quit = gui_quit,
.set_search_ico = gui_set_search_ico,
diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c
index 36ba13a..ffe6a22 100644
--- a/gtk/scaffolding.c
+++ b/gtk/scaffolding.c
@@ -26,7 +26,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/log.h"
#include "utils/nsoption.h"
@@ -70,7 +69,7 @@
#include "gtk/gdk.h"
#include "gtk/scaffolding.h"
#include "gtk/tabs.h"
-
+#include "gtk/schedule.h"
/** Macro to define a handler for menu, button and activate events. */
@@ -329,7 +328,7 @@ static void nsgtk_throb(void *p)
gtk_image_set_from_pixbuf(g->throbber, nsgtk_throbber->framedata[
g->throb_frame]);
- schedule(10, nsgtk_throb, p);
+ nsgtk_schedule(100, nsgtk_throb, p);
}
static guint nsgtk_scaffolding_update_edit_actions_sensitivity(
@@ -2175,7 +2174,7 @@ void gui_window_start_throbber(struct gui_window* _g)
nsgtk_window_update_back_forward(g);
- schedule(10, nsgtk_throb, g);
+ nsgtk_schedule(100, nsgtk_throb, g);
}
void gui_window_stop_throbber(struct gui_window* _g)
@@ -2184,7 +2183,7 @@ void gui_window_stop_throbber(struct gui_window* _g)
if (g == NULL)
return;
nsgtk_window_update_back_forward(g);
- schedule_remove(nsgtk_throb, g);
+ nsgtk_schedule(-1, nsgtk_throb, g);
if (g->buttons[STOP_BUTTON] != NULL)
g->buttons[STOP_BUTTON]->sensitivity = false;
if (g->buttons[RELOAD_BUTTON] != NULL)
diff --git a/gtk/schedule.c b/gtk/schedule.c
index 5b168b6..e28675a 100644
--- a/gtk/schedule.c
+++ b/gtk/schedule.c
@@ -20,7 +20,8 @@
#include <stdlib.h>
#include <stdbool.h>
-#include "utils/schedule.h"
+#include "utils/errors.h"
+
#include "gtk/schedule.h"
#ifdef DEBUG_GTK_SCHEDULE
@@ -71,7 +72,7 @@ nsgtk_schedule_kill_callback(void *_target, void *_match)
}
}
-void
+static void
schedule_remove(void (*callback)(void *p), void *p)
{
_nsgtk_callback_t cb_match = {
@@ -87,19 +88,27 @@ schedule_remove(void (*callback)(void *p), void *p)
nsgtk_schedule_kill_callback, &cb_match);
}
-void
-schedule(int t, void (*callback)(void *p), void *p)
+/* exported interface documented in gtk/schedule.h */
+nserror nsgtk_schedule(int t, void (*callback)(void *p), void *p)
{
- const int msec_timeout = t * 10;
- _nsgtk_callback_t *cb = malloc(sizeof(_nsgtk_callback_t));
+ _nsgtk_callback_t *cb;
+
/* Kill any pending schedule of this kind. */
schedule_remove(callback, p);
+
+ if (t < 0) {
+ return NSERROR_OK;
+ }
+
+ cb = malloc(sizeof(_nsgtk_callback_t));
cb->callback = callback;
cb->context = p;
cb->callback_killed = false;
/* Prepend is faster right now. */
queued_callbacks = g_list_prepend(queued_callbacks, cb);
- g_timeout_add(msec_timeout, nsgtk_schedule_generic_callback, cb);
+ g_timeout_add(t, nsgtk_schedule_generic_callback, cb);
+
+ return NSERROR_OK;
}
bool
diff --git a/gtk/schedule.h b/gtk/schedule.h
index c63215e..0a2d724 100644
--- a/gtk/schedule.h
+++ b/gtk/schedule.h
@@ -19,7 +19,8 @@
#ifndef NETSURF_GTK_CALLBACK_H
#define NETSURF_GTK_CALLBACK_H 1
-typedef void (*gtk_callback)(void *p);
+nserror nsgtk_schedule(int t, void (*callback)(void *p), void *p);
+
bool schedule_run(void);
#endif /* NETSURF_GTK_CALLBACK_H */
diff --git a/image/gif.c b/image/gif.c
index 4bd45c7..5c1b3ab 100644
--- a/image/gif.c
+++ b/image/gif.c
@@ -39,14 +39,15 @@
#include "content/hlcache.h"
#include "utils/nsoption.h"
#include "desktop/plotters.h"
-#include "image/image.h"
-#include "image/bitmap.h"
-#include "image/gif.h"
+#include "desktop/gui_factory.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
+#include "image/image.h"
+#include "image/bitmap.h"
+#include "image/gif.h"
+
typedef struct nsgif_content {
struct content base;
@@ -159,7 +160,7 @@ static void nsgif_animate(void *p)
delay = gif->gif->frames[gif->current_frame].frame_delay;
if (delay < nsoption_int(minimum_gif_delay))
delay = nsoption_int(minimum_gif_delay);
- schedule(delay, nsgif_animate, gif);
+ guit->browser->schedule(delay * 10, nsgif_animate, gif);
}
if ((!nsoption_bool(animate_images)) ||
@@ -292,7 +293,9 @@ static bool nsgif_convert(struct content *c)
/* Schedule the animation if we have one */
gif->current_frame = 0;
if (gif->gif->frame_count_partial > 1)
- schedule(gif->gif->frames[0].frame_delay, nsgif_animate, c);
+ guit->browser->schedule(gif->gif->frames[0].frame_delay * 10,
+ nsgif_animate,
+ c);
/* Exit as a success */
content_set_ready(c);
@@ -351,7 +354,7 @@ static void nsgif_destroy(struct content *c)
nsgif_content *gif = (nsgif_content *) c;
/* Free all the associated memory buffers */
- schedule_remove(nsgif_animate, c);
+ guit->browser->schedule(-1, nsgif_animate, c);
gif_finalise(gif->gif);
free(gif->gif);
}
diff --git a/image/image_cache.c b/image/image_cache.c
index c136908..0512439 100644
--- a/image/image_cache.c
+++ b/image/image_cache.c
@@ -22,7 +22,7 @@
#include <stdbool.h>
#include <string.h>
-#include "utils/schedule.h"
+#include "desktop/gui_factory.h"
#include "utils/log.h"
#include "content/content_protected.h"
@@ -290,9 +290,9 @@ static void image_cache__background_update(void *p)
image_cache__clean(icache);
- schedule((icache->params.bg_clean_time / 10),
- image_cache__background_update,
- icache);
+ guit->browser->schedule(icache->params.bg_clean_time,
+ image_cache__background_update,
+ icache);
}
/* exported interface documented in image_cache.h */
@@ -372,9 +372,9 @@ image_cache_init(const struct image_cache_parameters *image_cache_parameters)
image_cache->params = *image_cache_parameters;
- schedule((image_cache->params.bg_clean_time / 10),
- image_cache__background_update,
- image_cache);
+ guit->browser->schedule(image_cache->params.bg_clean_time,
+ image_cache__background_update,
+ image_cache);
LOG(("Image cache initilised with a limit of %d hysteresis of %d",
image_cache->params.limit, image_cache->params.hysteresis));
@@ -387,7 +387,7 @@ nserror image_cache_fini(void)
{
unsigned int op_count;
- schedule_remove(image_cache__background_update, image_cache);
+ guit->browser->schedule(-1, image_cache__background_update, image_cache);
LOG(("Size at finish %d (in %d)",
image_cache->total_bitmap_size,
diff --git a/monkey/main.c b/monkey/main.c
index 07ce7ee..96476d2 100644
--- a/monkey/main.c
+++ b/monkey/main.c
@@ -21,14 +21,6 @@
#include <stdlib.h>
#include "utils/nsoption.h"
-#include "monkey/poll.h"
-#include "monkey/dispatch.h"
-#include "monkey/browser.h"
-#include "monkey/cert.h"
-#include "monkey/401login.h"
-#include "monkey/filetype.h"
-#include "monkey/fetch.h"
-
#include "content/urldb.h"
#include "content/fetchers/resource.h"
#include "desktop/gui.h"
@@ -37,6 +29,15 @@
#include "utils/filepath.h"
#include "utils/url.h"
+#include "monkey/poll.h"
+#include "monkey/dispatch.h"
+#include "monkey/browser.h"
+#include "monkey/cert.h"
+#include "monkey/401login.h"
+#include "monkey/filetype.h"
+#include "monkey/fetch.h"
+#include "monkey/schedule.h"
+
char **respaths; /** resource search path vector */
/* Stolen from gtk/gui.c */
@@ -103,6 +104,7 @@ static bool nslog_stream_configure(FILE *fptr)
static struct gui_browser_table monkey_browser_table = {
.poll = monkey_poll,
+ .schedule = monkey_schedule,
.quit = monkey_quit,
.launch_url = gui_launch_url,
diff --git a/monkey/schedule.c b/monkey/schedule.c
index c4b1385..e8ec1c6 100644
--- a/monkey/schedule.c
+++ b/monkey/schedule.c
@@ -20,7 +20,7 @@
#include <stdlib.h>
#include <stdbool.h>
-#include "utils/schedule.h"
+#include "utils/errors.h"
#include "monkey/schedule.h"
@@ -75,7 +75,7 @@ nsgtk_schedule_kill_callback(void *_target, void *_match)
}
}
-void
+static void
schedule_remove(void (*callback)(void *p), void *p)
{
_nsgtk_callback_t cb_match = {
@@ -91,20 +91,27 @@ schedule_remove(void (*callback)(void *p), void *p)
nsgtk_schedule_kill_callback, &cb_match);
}
-void
-schedule(int t, void (*callback)(void *p), void *p)
+nserror monkey_schedule(int t, void (*callback)(void *p), void *p)
{
- const int msec_timeout = t * 10;
- _nsgtk_callback_t *cb = malloc(sizeof(_nsgtk_callback_t));
+ _nsgtk_callback_t *cb;
+
/* Kill any pending schedule of this kind. */
schedule_remove(callback, p);
+ if (t < 0) {
+ return NSERROR_OK;
+ }
+
+ cb = malloc(sizeof(_nsgtk_callback_t));
cb->callback = callback;
cb->context = p;
cb->callback_killed = false;
/* Prepend is faster right now. */
- LOG(("queued a callback to %p(%p) for %d msecs time", callback, p, msec_timeout));
+ LOG(("queued a callback to %p(%p) for %d msecs time", callback, p, t));
queued_callbacks = g_list_prepend(queued_callbacks, cb);
- g_timeout_add(msec_timeout, nsgtk_schedule_generic_callback, cb);
+ g_timeout_add(t, nsgtk_schedule_generic_callback, cb);
+
+ return NSERROR_OK;
+
}
bool
diff --git a/monkey/schedule.h b/monkey/schedule.h
index c63215e..44ef9bf 100644
--- a/monkey/schedule.h
+++ b/monkey/schedule.h
@@ -19,7 +19,8 @@
#ifndef NETSURF_GTK_CALLBACK_H
#define NETSURF_GTK_CALLBACK_H 1
-typedef void (*gtk_callback)(void *p);
+nserror monkey_schedule(int t, void (*callback)(void *p), void *p);
+
bool schedule_run(void);
#endif /* NETSURF_GTK_CALLBACK_H */
diff --git a/render/box_construct.c b/render/box_construct.c
index f5ef099..6991025 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -31,25 +31,27 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+
#include "utils/config.h"
#include "content/content_protected.h"
#include "css/css.h"
#include "css/utils.h"
#include "css/select.h"
+#include "desktop/gui_factory.h"
#include "utils/nsoption.h"
-#include "render/box.h"
-#include "render/box_textarea.h"
-#include "render/form.h"
-#include "render/html_internal.h"
#include "utils/corestrings.h"
#include "utils/locale.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/talloc.h"
#include "utils/url.h"
#include "utils/utils.h"
+#include "render/box.h"
+#include "render/box_textarea.h"
+#include "render/form.h"
+#include "render/html_internal.h"
+
/**
* Context for box tree construction
*/
@@ -183,9 +185,7 @@ nserror dom_to_box(dom_node *n, html_content *c, box_construct_complete_cb cb)
ctx->cb = cb;
ctx->bctx = c->bctx;
- schedule(0, (schedule_callback_fn) convert_xml_to_box, ctx);
-
- return NSERROR_OK;
+ return guit->browser->schedule(0, (void *)convert_xml_to_box, ctx);
}
/* mapping from CSS display to box type
@@ -446,7 +446,7 @@ void convert_xml_to_box(struct box_construct_ctx *ctx)
} while (++num_processed < max_processed_before_yield);
/* More work to do: schedule a continuation */
- schedule(0, (schedule_callback_fn) convert_xml_to_box, ctx);
+ guit->browser->schedule(0, (void *)convert_xml_to_box, ctx);
}
/**
diff --git a/render/html.c b/render/html.c
index e375e62..bb24e58 100644
--- a/render/html.c
+++ b/render/html.c
@@ -34,7 +34,6 @@
#include "utils/libdom.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/talloc.h"
#include "utils/url.h"
#include "utils/utf8.h"
@@ -591,6 +590,7 @@ void html_finish_conversion(html_content *c)
error = dom_to_box(html, c, html_box_convert_done);
if (error != NSERROR_OK) {
+ LOG(("box conversion failed"));
dom_node_unref(html);
html_object_free_objects(c);
content_broadcast_errorcode(&c->base, error);
diff --git a/render/html_css.c b/render/html_css.c
index ad24804..b4c25ba 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -28,12 +28,13 @@
#include <stdlib.h>
#include "content/hlcache.h"
+#include "desktop/gui_factory.h"
#include "utils/nsoption.h"
-#include "render/html_internal.h"
#include "utils/corestrings.h"
#include "utils/config.h"
#include "utils/log.h"
-#include "utils/schedule.h"
+
+#include "render/html_internal.h"
static nsurl *html_default_stylesheet_url;
static nsurl *html_adblock_stylesheet_url;
@@ -307,7 +308,7 @@ static void html_css_process_modified_styles(void *pw)
/* If we failed to process any sheet, schedule a retry */
if (all_done == false) {
- schedule(100, html_css_process_modified_styles, c);
+ guit->browser->schedule(1000, html_css_process_modified_styles, c);
}
}
@@ -332,7 +333,7 @@ bool html_css_update_style(html_content *c, dom_node *style)
s->modified = true;
- schedule(0, html_css_process_modified_styles, c);
+ guit->browser->schedule(0, html_css_process_modified_styles, c);
return true;
}
@@ -462,7 +463,7 @@ nserror html_css_free_stylesheets(html_content *html)
{
unsigned int i;
- schedule_remove(html_css_process_modified_styles, html);
+ guit->browser->schedule(-1, html_css_process_modified_styles, html);
for (i = 0; i != html->stylesheet_count; i++) {
if (html->stylesheets[i].sheet != NULL) {
diff --git a/render/html_object.c b/render/html_object.c
index e76919d..6499f24 100644
--- a/render/html_object.c
+++ b/render/html_object.c
@@ -31,12 +31,13 @@
#include "css/utils.h"
#include "utils/nsoption.h"
#include "desktop/scrollbar.h"
-#include "render/box.h"
-#include "render/html_internal.h"
+#include "desktop/gui_factory.h"
#include "utils/corestrings.h"
#include "utils/config.h"
#include "utils/log.h"
-#include "utils/schedule.h"
+
+#include "render/box.h"
+#include "render/html_internal.h"
/* break reference loop */
static void html_object_refresh(void *p);
@@ -335,7 +336,7 @@ html_object_callback(hlcache_handle *object,
case CONTENT_MSG_REFRESH:
if (content_get_type(object) == CONTENT_HTML) {
/* only for HTML objects */
- schedule(event->data.delay * 100,
+ guit->browser->schedule(event->data.delay * 1000,
html_object_refresh, o);
}
@@ -534,7 +535,7 @@ static bool html_replace_object(struct content_html_object *object, nsurl *url)
}
/**
- * schedule() callback for object refresh
+ * schedule callback for object refresh
*/
static void html_object_refresh(void *p)
@@ -630,8 +631,9 @@ nserror html_object_close_objects(html_content *html)
if (content_get_type(object->content) == CONTENT_NONE)
continue;
- if (content_get_type(object->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, object);
+ if (content_get_type(object->content) == CONTENT_HTML) {
+ guit->browser->schedule(-1, html_object_refresh, object);
+ }
content_close(object->content);
}
@@ -646,9 +648,9 @@ nserror html_object_free_objects(html_content *html)
if (victim->content != NULL) {
LOG(("object %p", victim->content));
- if (content_get_type(victim->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, victim);
-
+ if (content_get_type(victim->content) == CONTENT_HTML) {
+ guit->browser->schedule(-1, html_object_refresh, victim);
+ }
hlcache_handle_release(victim->content);
}
diff --git a/riscos/download.c b/riscos/download.c
index b10c6c1..804a664 100644
--- a/riscos/download.c
+++ b/riscos/download.c
@@ -33,7 +33,6 @@
#include <sys/time.h>
#include <time.h>
#include <curl/curl.h>
-
#include "oslib/mimemap.h"
#include "oslib/osargs.h"
#include "oslib/osfile.h"
@@ -42,22 +41,24 @@
#include "oslib/osgbpb.h"
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
+
#include "desktop/gui.h"
#include "desktop/netsurf.h"
#include "desktop/download.h"
-#include "riscos/dialog.h"
#include "utils/nsoption.h"
-#include "riscos/mouse.h"
-#include "riscos/save.h"
-#include "riscos/query.h"
-#include "riscos/wimp.h"
-#include "riscos/wimp_event.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/utf8.h"
#include "utils/utils.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/mouse.h"
+#include "riscos/save.h"
+#include "riscos/query.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
#include "riscos/ucstables.h"
#define ICON_DOWNLOAD_ICON 0
@@ -455,7 +456,7 @@ static void gui_download_window_error(struct gui_download_window *dw,
dw->ctx = NULL;
dw->error = true;
- schedule_remove(ro_gui_download_update_status_wrapper, dw);
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
/* place error message in status icon in red */
strncpy(dw->status, error_msg, sizeof dw->status);
@@ -715,15 +716,16 @@ void ro_gui_download_update_status(struct gui_download_window *dw)
warn_user("WimpError", error->errmess);
}
- if (dw->ctx)
- schedule(100, ro_gui_download_update_status_wrapper, dw);
- else
- schedule_remove(ro_gui_download_update_status_wrapper, dw);
+ if (dw->ctx) {
+ riscos_schedule(1000, ro_gui_download_update_status_wrapper, dw);
+ } else {
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
+ }
}
/**
- * Wrapper for ro_gui_download_update_status(), suitable for schedule().
+ * Wrapper for ro_gui_download_update_status(), suitable for riscos_schedule().
*/
void ro_gui_download_update_status_wrapper(void *p)
@@ -795,10 +797,11 @@ static void gui_download_window_done(struct gui_download_window *dw)
warn_user("SaveError", error->errmess);
}
- if (dw->send_dataload)
+ if (dw->send_dataload) {
ro_gui_download_send_dataload(dw);
+ }
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
}
@@ -889,7 +892,7 @@ bool ro_gui_download_keypress(wimp_key *key)
!nsoption_bool(confirm_overwrite)) && !dw->ctx)
{
/* finished already */
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
return true;
}
@@ -985,7 +988,7 @@ void ro_gui_download_datasave_ack(wimp_message *message)
ro_gui_download_send_dataload(dw);
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
}
@@ -1417,7 +1420,7 @@ void ro_gui_download_send_dataload(struct gui_download_window *dw)
warn_user("WimpError", error->errmess);
}
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
@@ -1480,8 +1483,8 @@ bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit)
return false;
}
- schedule_remove(ro_gui_download_update_status_wrapper, dw);
- schedule_remove(ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
+ riscos_schedule(-1, ro_gui_download_window_destroy_wrapper, dw);
/* remove from list */
if (dw->prev)
@@ -1534,7 +1537,7 @@ bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit)
/**
- * Wrapper for ro_gui_download_window_destroy(), suitable for schedule().
+ * Wrapper for ro_gui_download_window_destroy(), suitable for riscos_schedule().
*/
void ro_gui_download_window_destroy_wrapper(void *p)
@@ -1613,7 +1616,7 @@ void ro_gui_download_overwrite_confirmed(query_id id, enum query_response res, v
ro_gui_download_send_dataload(dw);
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
}
diff --git a/riscos/gui.c b/riscos/gui.c
index 1663c17..59a0138 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -1077,7 +1077,7 @@ void ro_gui_cleanup(void)
* \param active return as soon as possible
*/
-void gui_poll(bool active)
+static void riscos_poll(bool active)
{
wimp_event_no event;
wimp_block block;
@@ -1116,8 +1116,9 @@ void gui_poll(bool active)
* from gui_multitask(). Scheduled callbacks must only be run from the
* top-level.
*/
- if (event == wimp_NULL_REASON_CODE)
+ if (event == wimp_NULL_REASON_CODE) {
schedule_run();
+ }
ro_gui_window_update_boxes();
@@ -2358,7 +2359,8 @@ static struct gui_fetch_table riscos_fetch_table = {
};
static struct gui_browser_table riscos_browser_table = {
- .poll = gui_poll,
+ .poll = riscos_poll,
+ .schedule = riscos_schedule,
.quit = gui_quit,
.launch_url = gui_launch_url,
diff --git a/riscos/gui.h b/riscos/gui.h
index dbf6373..3ea0c0b 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -123,7 +123,6 @@ void ro_gui_dump_browser_window(struct browser_window *bw);
void ro_gui_drag_box_start(wimp_pointer *pointer);
bool ro_gui_prequit(void);
const char *ro_gui_default_language(void);
-void gui_poll(bool active); /* exported for riscos/wimp_event.c:722 */
char *url_to_path(const char *url);
/* in download.c */
@@ -183,8 +182,24 @@ bits ro_filetype_from_unix_path(const char *unix_path);
/* in schedule.c */
extern bool sched_active;
extern os_t sched_time;
+
+/**
+ * Process events up to current time.
+ */
bool schedule_run(void);
+/**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror riscos_schedule(int t, void (*callback)(void *p), void *p);
+
/* in search.c */
void ro_gui_search_init(void);
void ro_gui_search_prepare(struct browser_window *g);
diff --git a/riscos/gui/progress_bar.c b/riscos/gui/progress_bar.c
index 4457976..f5b4731 100644
--- a/riscos/gui/progress_bar.c
+++ b/riscos/gui/progress_bar.c
@@ -29,10 +29,11 @@
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
+
#include "desktop/plotters.h"
#include "utils/log.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
+
#include "riscos/gui.h"
#include "riscos/tinct.h"
#include "riscos/wimp_event.h"
@@ -159,8 +160,9 @@ void ro_gui_progress_bar_destroy(struct progress_bar *pb)
os_error *error;
assert(pb);
- if (pb->animating)
- schedule_remove(ro_gui_progress_bar_animate, pb);
+ if (pb->animating) {
+ riscos_schedule(-1, ro_gui_progress_bar_animate, pb);
+ }
ro_gui_wimp_event_finalise(pb->w);
error = xwimp_delete_window(pb->w);
if (error) {
@@ -292,12 +294,14 @@ void ro_gui_progress_bar_update(struct progress_bar *pb, int width, int height)
/* update the animation state */
if ((pb->value == 0) || (pb->value == pb->range)) {
- if (pb->animating)
- schedule_remove(ro_gui_progress_bar_animate, pb);
+ if (pb->animating) {
+ riscos_schedule(-1, ro_gui_progress_bar_animate, pb);
+ }
pb->animating = false;
} else {
- if (!pb->animating)
- schedule(20, ro_gui_progress_bar_animate, pb);
+ if (!pb->animating) {
+ riscos_schedule(200, ro_gui_progress_bar_animate, pb);
+ }
pb->animating = true;
}
@@ -372,8 +376,9 @@ void ro_gui_progress_bar_animate(void *p)
if (pb->offset < 0)
pb->offset += progress_width * 2;
- if (pb->animating)
- schedule(20, ro_gui_progress_bar_animate, pb);
+ if (pb->animating) {
+ riscos_schedule(200, ro_gui_progress_bar_animate, pb);
+ }
redraw.w = pb->w;
redraw.box = pb->visible;
diff --git a/riscos/gui/status_bar.c b/riscos/gui/status_bar.c
index 899fe99..46a511f 100644
--- a/riscos/gui/status_bar.c
+++ b/riscos/gui/status_bar.c
@@ -30,7 +30,6 @@
#include "oslib/wimpspriteop.h"
#include "desktop/plotters.h"
#include "utils/log.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
#include "riscos/gui.h"
#include "riscos/wimp.h"
@@ -171,7 +170,7 @@ void ro_gui_status_bar_destroy(struct status_bar *sb)
ro_gui_progress_bar_destroy(sb->pb);
/* Remove any scheduled redraw callbacks */
- schedule_remove(ro_gui_status_bar_redraw_callback, (void *) sb);
+ riscos_schedule(-1, ro_gui_status_bar_redraw_callback, (void *) sb);
free(sb);
}
@@ -331,7 +330,7 @@ void ro_gui_status_bar_set_text(struct status_bar *sb, const char *text)
* { callback, handle } pair is registered at once.
*/
if (sb->visible && text != NULL) {
- schedule(1, ro_gui_status_bar_redraw_callback, (void *) sb);
+ riscos_schedule(10, ro_gui_status_bar_redraw_callback, sb);
}
}
diff --git a/riscos/hotlist.c b/riscos/hotlist.c
index 7910353..14e90fb 100644
--- a/riscos/hotlist.c
+++ b/riscos/hotlist.c
@@ -30,27 +30,29 @@
#include "oslib/osfile.h"
#include "oslib/osmodule.h"
#include "oslib/wimp.h"
+
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "desktop/hotlist.h"
#include "desktop/tree.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/url.h"
+#include "utils/nsoption.h"
+
+#include "riscos/gui.h"
#include "riscos/dialog.h"
#include "riscos/hotlist.h"
#include "riscos/menus.h"
#include "riscos/message.h"
-#include "utils/nsoption.h"
#include "riscos/save.h"
#include "riscos/toolbar.h"
#include "riscos/treeview.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
#include "riscos/query.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/schedule.h"
-#include "utils/utils.h"
-#include "utils/url.h"
static void ro_gui_hotlist_toolbar_update_buttons(void);
static void ro_gui_hotlist_toolbar_save_buttons(char *config);
@@ -543,7 +545,7 @@ void ro_gui_hotlist_add_page(nsurl *url)
* message didn't bounce.
*/
- schedule(0, ro_gui_hotlist_scheduled_callback, NULL);
+ riscos_schedule(0, ro_gui_hotlist_scheduled_callback, NULL);
}
@@ -569,7 +571,7 @@ static void ro_gui_hotlist_addurl_bounce(wimp_message *message)
/* There's no longer any need to listen for the next Null poll. */
- schedule_remove(ro_gui_hotlist_scheduled_callback, NULL);
+ riscos_schedule(-1, ro_gui_hotlist_scheduled_callback, NULL);
}
diff --git a/riscos/schedule.c b/riscos/schedule.c
index 257f2e7..5129005 100644
--- a/riscos/schedule.c
+++ b/riscos/schedule.c
@@ -24,10 +24,11 @@
#include <stdbool.h>
#include <stdlib.h>
+
#include "oslib/os.h"
-#include "riscos/gui.h"
#include "utils/log.h"
-#include "utils/schedule.h"
+
+#include "riscos/gui.h"
/** Entry in the queue of scheduled callbacks. */
@@ -50,25 +51,53 @@ bool sched_active = false;
/** Time of soonest scheduled event (valid only if sched_active is true). */
os_t sched_time;
-
/**
- * Schedule a callback.
+ * Unschedule a callback.
*
- * \param t interval before the callback should be made / cs
* \param callback callback function
* \param p user parameter, passed to callback function
*
- * The callback function will be called as soon as possible after t cs have
- * passed.
+ * All scheduled callbacks matching both callback and p are removed.
*/
-void schedule(int t, void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
+{
+ struct sched_entry *entry, *next;
+
+ for (entry = &sched_queue; entry->next; entry = entry->next) {
+ if (entry->next->callback != callback || entry->next->p != p)
+ continue;
+ next = entry->next;
+ entry->next = entry->next->next;
+ free(next);
+ if (!entry->next)
+ break;
+ }
+
+ if (sched_queue.next) {
+ sched_active = true;
+ sched_time = sched_queue.next->time;
+ } else {
+ sched_active = false;
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in riscos/gui.h */
+nserror riscos_schedule(int t, void (*callback)(void *p), void *p)
{
struct sched_entry *entry;
struct sched_entry *queue;
os_t time;
+ nserror ret;
- schedule_remove(callback, p);
+ ret = schedule_remove(callback, p);
+ if ((t < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ t = t / 10; /* convert to centiseconds */
time = os_read_monotonic_time() + t;
@@ -91,44 +120,12 @@ void schedule(int t, void (*callback)(void *p), void *p)
sched_active = true;
sched_time = sched_queue.next->time;
-}
-
-/**
- * Unschedule a callback.
- *
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * All scheduled callbacks matching both callback and p are removed.
- */
-
-void schedule_remove(void (*callback)(void *p), void *p)
-{
- struct sched_entry *entry, *next;
-
- for (entry = &sched_queue; entry->next; entry = entry->next) {
- if (entry->next->callback != callback || entry->next->p != p)
- continue;
- next = entry->next;
- entry->next = entry->next->next;
- free(next);
- if (!entry->next)
- break;
- }
-
- if (sched_queue.next) {
- sched_active = true;
- sched_time = sched_queue.next->time;
- } else
- sched_active = false;
+ return NSERROR_OK;
}
-/**
- * Process events up to current time.
- */
-
+/* exported function documented in riscos/gui.h */
bool schedule_run(void)
{
struct sched_entry *entry;
@@ -144,8 +141,9 @@ bool schedule_run(void)
p = entry->p;
sched_queue.next = entry->next;
free(entry);
- /* The callback may call schedule() or schedule_remove(), so
- * leave the queue in a safe state. */
+ /* The callback may call riscos_schedule(), so leave
+ * the queue in a safe state.
+ */
callback(p);
}
diff --git a/utils/schedule.h b/utils/schedule.h
deleted file mode 100644
index b5fe386..0000000
--- a/utils/schedule.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011 Daniel Silverstone <dsilvers(a)netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/** \file
- * Job scheduler (interface).
- */
-
-#ifndef _NETSURF_UTILS_SCHEDULE_H_
-#define _NETSURF_UTILS_SCHEDULE_H_
-
-/* In platform specific schedule.c. */
-typedef void (*schedule_callback_fn)(void *p);
-
-void schedule(int t, schedule_callback_fn callback, void *p);
-void schedule_remove(schedule_callback_fn callback, void *p);
-
-#endif
diff --git a/windows/download.c b/windows/download.c
index 8bdff3a..fe2a092 100644
--- a/windows/download.c
+++ b/windows/download.c
@@ -27,14 +27,15 @@
#include "content/fetch.h"
#include "desktop/gui.h"
#include "desktop/download.h"
-#include "utils/schedule.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utils.h"
+
#include "windows/download.h"
#include "windows/gui.h"
#include "windows/resourceid.h"
+#include "windows/schedule.h"
static bool downloading = false;
static struct gui_download_window *download1;
@@ -182,7 +183,7 @@ void nsws_download_update_label(void *p)
{
struct gui_download_window *w = p;
if (w->hwnd == NULL) {
- schedule_remove(nsws_download_update_label, p);
+ win32_schedule(-1, nsws_download_update_label, p);
return;
}
HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_LABEL);
@@ -222,21 +223,23 @@ void nsws_download_update_label(void *p)
w->time_left = NULL;
}
SendMessage(sub, WM_SETTEXT, (WPARAM)0, (LPARAM)label);
- if (w->progress < 10000)
- schedule(50, nsws_download_update_label, p);
+ if (w->progress < 10000) {
+ win32_schedule(500, nsws_download_update_label, p);
+ }
}
void nsws_download_update_progress(void *p)
{
struct gui_download_window *w = p;
if (w->hwnd == NULL) {
- schedule_remove(nsws_download_update_progress, p);
+ win32_schedule(-1, nsws_download_update_progress, p);
return;
}
HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_PROGRESS);
SendMessage(sub, PBM_SETPOS, (WPARAM)(w->progress / 100), 0);
- if (w->progress < 10000)
- schedule(50, nsws_download_update_progress, p);
+ if (w->progress < 10000) {
+ win32_schedule(500, nsws_download_update_progress, p);
+ }
}
void nsws_download_clear_data(struct gui_download_window *w)
@@ -255,8 +258,8 @@ void nsws_download_clear_data(struct gui_download_window *w)
free(w->total_size);
if (w->file != NULL)
fclose(w->file);
- schedule_remove(nsws_download_update_progress, (void *)w);
- schedule_remove(nsws_download_update_label, (void *)w);
+ win32_schedule(-1, nsws_download_update_progress, (void *)w);
+ win32_schedule(-1, nsws_download_update_label, (void *)w);
}
diff --git a/windows/gui.c b/windows/gui.c
index 92ff400..8270c13 100644
--- a/windows/gui.c
+++ b/windows/gui.c
@@ -78,7 +78,7 @@ void gui_window_set_scroll(struct gui_window *w, int sx, int sy);
static bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
-static void gui_poll(bool active)
+static void win32_poll(bool active)
{
MSG Msg; /* message from system */
BOOL bRet; /* message fetch result */
@@ -1888,7 +1888,8 @@ struct gui_fetch_table *win32_fetch_table = &fetch_table;
static struct gui_browser_table browser_table = {
- .poll = gui_poll,
+ .poll = win32_poll,
+ .schedule = win32_schedule,
};
struct gui_browser_table *win32_browser_table = &browser_table;
diff --git a/windows/schedule.c b/windows/schedule.c
index 3181c55..f819918 100644
--- a/windows/schedule.c
+++ b/windows/schedule.c
@@ -19,12 +19,17 @@
#include <sys/time.h>
#include <time.h>
-#include "utils/schedule.h"
#include "windows/schedule.h"
#include "utils/log.h"
#include "utils/utils.h"
+#ifdef DEBUG_SCHEDULER
+#define SRLOG(x) LOG(x)
+#else
+#define SRLOG(x)
+#endif
+
/* linked list of scheduled callbacks */
static struct nscallback *schedule_list = NULL;
@@ -41,39 +46,6 @@ struct nscallback
/**
- * Schedule a callback.
- *
- * \param tival interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-void schedule(int cs_ival, void (*callback)(void *p), void *p)
-{
- struct nscallback *nscb;
- struct timeval tv;
-
- tv.tv_sec = cs_ival / 100; /* cs to seconds */
- tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */
-
- nscb = calloc(1, sizeof(struct nscallback));
-
- LOG(("adding callback %p for %p(%p) at %d cs", nscb, callback, p, cs_ival));
-
- gettimeofday(&nscb->tv, NULL);
- timeradd(&nscb->tv, &tv, &nscb->tv);
-
- nscb->callback = callback;
- nscb->p = p;
-
- /* add to list front */
- nscb->next = schedule_list;
- schedule_list = nscb;
-}
-
-/**
* Unschedule a callback.
*
* \param callback callback function
@@ -82,16 +54,18 @@ void schedule(int cs_ival, void (*callback)(void *p), void *p)
* All scheduled callbacks matching both callback and p are removed.
*/
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- if (schedule_list == NULL)
- return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
- LOG(("removing %p, %p", callback, p));
+ SRLOG(("removing %p, %p", callback, p));
cur_nscb = schedule_list;
prev_nscb = NULL;
@@ -101,7 +75,7 @@ void schedule_remove(void (*callback)(void *p), void *p)
(cur_nscb->p == p)) {
/* item to remove */
- LOG(("callback entry %p removing %p(%p)",
+ SRLOG(("callback entry %p removing %p(%p)",
cur_nscb, cur_nscb->callback, cur_nscb->p));
/* remove callback */
@@ -120,8 +94,44 @@ void schedule_remove(void (*callback)(void *p), void *p)
cur_nscb = prev_nscb->next;
}
}
+ return NSERROR_OK;
}
+/* exported interface documented in windows/schedule.h */
+nserror win32_schedule(int ival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+ nserror ret;
+
+ ret = schedule_remove(callback, p);
+ if ((ival < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ tv.tv_sec = ival / 1000; /* miliseconds to seconds */
+ tv.tv_usec = (cs_ival % 1000) * 1000; /* remainder to microseconds */
+
+ nscb = calloc(1, sizeof(struct nscallback));
+ if (nscb == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ SRLOG(("adding callback %p for %p(%p) at %d cs",
+ nscb, callback, p, ival));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+
+ return NSERROR_OK;
+}
/* exported interface documented in schedule.h */
int
@@ -157,7 +167,7 @@ schedule_run(void)
prev_nscb->next = unlnk_nscb->next;
}
- LOG(("callback entry %p running %p(%p)",
+ SRLOG(("callback entry %p running %p(%p)",
unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
/* call callback */
unlnk_nscb->callback(unlnk_nscb->p);
@@ -190,9 +200,9 @@ schedule_run(void)
/* make returned time relative to now */
timersub(&nexttime, &tv, &rettime);
-#if defined(DEBUG_SCHEDULER)
- LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
-#endif
+ SRLOG(("returning time to next event as %ldms",
+ (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
+
/* return next event time in milliseconds (24days max wait) */
return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
}
diff --git a/windows/schedule.h b/windows/schedule.h
index e6a5d10..6d47b2d 100644
--- a/windows/schedule.h
+++ b/windows/schedule.h
@@ -16,8 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef FRAMEBUFFER_SCHEDULE_H
-#define FRAMEBUFFER_SCHEDULE_H
+#ifndef WINDOWS_SCHEDULE_H
+#define WINDOWS_SCHEDULE_H
+
+/**
+ * Schedule a callback.
+ *
+ * \param ival interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror win32_schedule(int ival, void (*callback)(void *p), void *p);
/**
* Process scheduled callbacks up to current time.
-----------------------------------------------------------------------
Summary of changes:
amiga/font.c | 6 +-
amiga/gui.c | 11 ++-
amiga/menu.c | 9 ++-
amiga/schedule.c | 160 ++++++++++++++++++++-----------------
amiga/schedule.h | 38 ++++++++-
amiga/tree.c | 6 +-
atari/gui.c | 8 +-
atari/schedule.c | 124 ++++++++++++++---------------
atari/schedule.h | 25 +++++-
beos/gui.cpp | 1 +
beos/gui.h | 3 -
beos/scaffolding.cpp | 9 +-
beos/schedule.cpp | 26 ++++---
beos/schedule.h | 7 +-
cocoa/apple_image.m | 11 ++-
cocoa/gui.m | 2 +
cocoa/{selection.h => schedule.h} | 2 +-
cocoa/schedule.m | 20 ++---
content/fetchers/curl.c | 14 ++--
content/hlcache.c | 8 +-
desktop/browser.c | 13 ++--
desktop/gui.h | 46 +++++++++--
desktop/gui_factory.c | 4 +
framebuffer/gui.c | 10 +-
framebuffer/schedule.c | 103 ++++++++++++------------
framebuffer/schedule.h | 20 +++++
gtk/gui.c | 5 +-
gtk/scaffolding.c | 9 +-
gtk/schedule.c | 23 ++++--
gtk/schedule.h | 3 +-
image/gif.c | 17 +++--
image/image_cache.c | 16 ++--
monkey/main.c | 18 +++--
monkey/schedule.c | 23 ++++--
monkey/schedule.h | 3 +-
render/box_construct.c | 18 ++--
render/html.c | 2 +-
render/html_css.c | 11 ++-
render/html_object.c | 22 +++---
riscos/download.c | 49 ++++++-----
riscos/gui.c | 8 +-
riscos/gui.h | 17 ++++-
riscos/gui/progress_bar.c | 23 +++--
riscos/gui/status_bar.c | 5 +-
riscos/hotlist.c | 18 +++--
riscos/schedule.c | 88 ++++++++++----------
utils/schedule.h | 32 --------
windows/download.c | 21 +++--
windows/gui.c | 5 +-
windows/schedule.c | 96 ++++++++++++----------
windows/schedule.h | 16 +++-
51 files changed, 702 insertions(+), 532 deletions(-)
copy cocoa/{selection.h => schedule.h} (91%)
delete mode 100644 utils/schedule.h
diff --git a/amiga/font.c b/amiga/font.c
index 3430a4e..df4a188 100755
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -23,12 +23,12 @@
#include "amiga/gui.h"
#include "amiga/utf8.h"
#include "amiga/object.h"
+#include "amiga/schedule.h"
#include "utils/nsoption.h"
#include "css/css.h"
#include "css/utils.h"
#include "render/font.h"
#include "utils/log.h"
-#include "utils/schedule.h"
#include "utils/utf8.h"
#include "utils/utils.h"
@@ -831,7 +831,7 @@ void ami_init_fonts(void)
NewList(&ami_diskfontlib_list);
/* run first cleanup in ten minutes */
- schedule(60000, (schedule_callback_fn)ami_font_cleanup, ami_font_list);
+ ami_schedule(600000, ami_font_cleanup, ami_font_list);
}
void ami_close_fonts(void)
@@ -875,7 +875,7 @@ static void ami_font_cleanup(struct MinList *ami_font_list)
}while(node=nnode);
/* reschedule to run in five minutes */
- schedule(30000, (schedule_callback_fn)ami_font_cleanup, ami_font_list);
+ ami_schedule(300000, ami_font_cleanup, ami_font_list);
}
void ami_font_setdevicedpi(int id)
diff --git a/amiga/gui.c b/amiga/gui.c
index aedb26c..84e9dc9 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -2538,7 +2538,7 @@ static void ami_gui_fetch_callback(void *p)
static void gui_poll(bool active)
{
- if(active) schedule(0, ami_gui_fetch_callback, NULL);
+ if(active) ami_schedule(0, ami_gui_fetch_callback, NULL);
ami_get_msg();
}
@@ -4050,19 +4050,19 @@ static void ami_redraw_callback(void *p)
*/
void ami_schedule_redraw(struct gui_window_2 *gwin, bool full_redraw)
{
- int cs = 0;
+ int ms = 0;
if(full_redraw) gwin->redraw_required = true;
if(gwin->redraw_scheduled == true) return;
- if(gwin->bw->reformat_pending) cs = nsoption_int(reformat_delay);
- schedule(cs, ami_redraw_callback, gwin);
+ if(gwin->bw->reformat_pending) ms = nsoption_int(reformat_delay) * 10;
+ ami_schedule(ms, ami_redraw_callback, gwin);
gwin->redraw_scheduled = true;
}
static void ami_schedule_redraw_remove(struct gui_window_2 *gwin)
{
- schedule_remove(ami_redraw_callback, gwin);
+ ami_schedule(-1, ami_redraw_callback, gwin);
}
static void ami_do_redraw_tiled(struct gui_window_2 *gwin, bool busy,
@@ -5133,6 +5133,7 @@ static struct gui_fetch_table amiga_fetch_table = {
static struct gui_browser_table amiga_browser_table = {
.poll = gui_poll,
+ .schedule = ami_schedule,
.quit = gui_quit,
.set_search_ico = gui_set_search_ico,
diff --git a/amiga/menu.c b/amiga/menu.c
index 2c019bd..9cb857e 100644
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -58,12 +58,13 @@
#include "amiga/theme.h"
#include "amiga/tree.h"
#include "amiga/utf8.h"
+#include "amiga/schedule.h"
#include "desktop/hotlist.h"
#include "desktop/browser_private.h"
#include "desktop/gui.h"
#include "desktop/textinput.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
+
enum {
NSA_GLYPH_SUBMENU,
@@ -481,7 +482,11 @@ struct NewMenu *ami_create_menu(struct gui_window_2 *gwin)
/* Set up scheduler to refresh the hotlist menu */
if(nsoption_int(menu_refresh) > 0)
- schedule(nsoption_int(menu_refresh), (void *)ami_menu_refresh, gwin);
+ {
+ ami_schedule(nsoption_int(menu_refresh) * 10,
+ ami_menu_refresh,
+ gwin);
+ }
return(gwin->menu);
}
diff --git a/amiga/schedule.c b/amiga/schedule.c
index d4b35a5..4ec9df7 100755
--- a/amiga/schedule.c
+++ b/amiga/schedule.c
@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "utils/schedule.h"
#include "amiga/os3support.h"
#include "amiga/schedule.h"
@@ -37,51 +36,18 @@ struct nscallback
PblHeap *schedule_list;
-void ami_remove_timer_event(struct nscallback *nscb);
-
-/**
- * Schedule a callback.
- *
- * \param t interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-
-void schedule(int t, void (*callback)(void *p), void *p)
+static void ami_remove_timer_event(struct nscallback *nscb)
{
- struct nscallback *nscb;
- struct TimeVal tv;
- ULONG time_us = 0;
-
- if(schedule_list == NULL) return;
-
- nscb = AllocVecTagList(sizeof(struct nscallback), NULL);
if(!nscb) return;
- time_us = t*10000; /* t converted to �s */
-
- nscb->tv.Seconds = time_us / 1000000;
- nscb->tv.Microseconds = time_us % 1000000;
-
- GetSysTime(&tv);
- AddTime(&nscb->tv,&tv); // now contains time when event occurs
-
- if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL))
+ if(nscb->treq)
{
- *nscb->treq = *tioreq;
- nscb->treq->Request.io_Command=TR_ADDREQUEST;
- nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs
- nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro
- SendIO((struct IORequest *)nscb->treq);
- }
-
- nscb->callback = callback;
- nscb->p = p;
+ if(CheckIO((struct IORequest *)nscb->treq)==NULL)
+ AbortIO((struct IORequest *)nscb->treq);
- pblHeapInsert(schedule_list, nscb);
+ WaitIO((struct IORequest *)nscb->treq);
+ FreeVec(nscb->treq);
+ }
}
/**
@@ -93,14 +59,22 @@ void schedule(int t, void (*callback)(void *p), void *p)
* All scheduled callbacks matching both callback and p are removed.
*/
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
PblIterator *iterator;
struct nscallback *nscb;
bool restoreheap = false;
- if(schedule_list == NULL) return;
- if(pblHeapIsEmpty(schedule_list)) return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL)
+ {
+ return NSERROR_OK;
+ }
+
+ if(pblHeapIsEmpty(schedule_list))
+ {
+ return NSERROR_OK;
+ }
iterator = pblHeapIterator(schedule_list);
@@ -117,10 +91,15 @@ void schedule_remove(void (*callback)(void *p), void *p)
pblIteratorFree(iterator);
- if(restoreheap) pblHeapConstruct(schedule_list);
+ if(restoreheap)
+ {
+ pblHeapConstruct(schedule_list);
+ }
+
+ return NSERROR_OK;
}
-void schedule_remove_all(void)
+static void schedule_remove_all(void)
{
PblIterator *iterator;
struct nscallback *nscb;
@@ -139,13 +118,16 @@ void schedule_remove_all(void)
pblIteratorFree(iterator);
}
-/**
- * Process events up to current time.
- * This implementation only takes the top entry off the heap, it does not
- * venture to later scheduled events until the next time it is called -
- * immediately afterwards, if we're in a timer signalled loop.
- */
+static int ami_schedule_compare(const void *prev, const void *next)
+{
+ struct nscallback *nscb1 = *(struct nscallback **)prev;
+ struct nscallback *nscb2 = *(struct nscallback **)next;
+
+ return CmpTime(&nscb1->tv, &nscb2->tv);
+}
+
+/* exported function documented in amiga/schedule.h */
void schedule_run(BOOL poll)
{
struct nscallback *nscb;
@@ -176,28 +158,7 @@ void schedule_run(BOOL poll)
callback(p);
}
-void ami_remove_timer_event(struct nscallback *nscb)
-{
- if(!nscb) return;
-
- if(nscb->treq)
- {
- if(CheckIO((struct IORequest *)nscb->treq)==NULL)
- AbortIO((struct IORequest *)nscb->treq);
-
- WaitIO((struct IORequest *)nscb->treq);
- FreeVec(nscb->treq);
- }
-}
-
-int ami_schedule_compare(const void *prev, const void *next)
-{
- struct nscallback *nscb1 = *(struct nscallback **)prev;
- struct nscallback *nscb2 = *(struct nscallback **)next;
-
- return CmpTime(&nscb1->tv, &nscb2->tv);
-}
-
+/* exported function documented in amiga/schedule.h */
BOOL ami_schedule_create(void)
{
schedule_list = pblHeapNew();
@@ -206,6 +167,7 @@ BOOL ami_schedule_create(void)
pblHeapSetCompareFunction(schedule_list, ami_schedule_compare);
}
+/* exported function documented in amiga/schedule.h */
void ami_schedule_free(void)
{
schedule_remove_all();
@@ -213,6 +175,7 @@ void ami_schedule_free(void)
schedule_list = NULL;
}
+/* exported function documented in amiga/schedule.h */
void ami_schedule_open_timer(void)
{
msgport = AllocSysObjectTags(ASOT_PORT,
@@ -231,6 +194,7 @@ void ami_schedule_open_timer(void)
ITimer = (struct TimerIFace *)GetInterface((struct Library *)TimerBase,"main",1,NULL);
}
+/* exported function documented in amiga/schedule.h */
void ami_schedule_close_timer(void)
{
if(ITimer)
@@ -242,3 +206,51 @@ void ami_schedule_close_timer(void)
FreeSysObject(ASOT_IOREQUEST,tioreq);
FreeSysObject(ASOT_PORT,msgport);
}
+
+/* exported function documented in amiga/schedule.h */
+nserror ami_schedule(int t, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct TimeVal tv;
+ ULONG time_us = 0;
+
+ if(schedule_list == NULL)
+ {
+ return NSERROR_INIT_FAILED;
+ }
+
+ if(t < 0)
+ {
+ return schedule_remove(callback, p);
+ }
+
+ nscb = AllocVecTagList(sizeof(struct nscallback), NULL);
+ if(!nscb)
+ {
+ return NSERROR_NOMEM;
+ }
+
+ time_us = t * 1000; /* t converted to �s */
+
+ nscb->tv.Seconds = time_us / 1000000;
+ nscb->tv.Microseconds = time_us % 1000000;
+
+ GetSysTime(&tv);
+ AddTime(&nscb->tv,&tv); // now contains time when event occurs
+
+ if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL))
+ {
+ *nscb->treq = *tioreq;
+ nscb->treq->Request.io_Command=TR_ADDREQUEST;
+ nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs
+ nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro
+ SendIO((struct IORequest *)nscb->treq);
+ }
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ pblHeapInsert(schedule_list, nscb);
+
+ return NSERROR_OK;
+}
diff --git a/amiga/schedule.h b/amiga/schedule.h
index 3eddc89..6592306 100755
--- a/amiga/schedule.h
+++ b/amiga/schedule.h
@@ -19,7 +19,6 @@
#ifndef AMIGA_SCHEDULE_H
#define AMIGA_SCHEDULE_H
#include <proto/timer.h>
-#include "utils/schedule.h"
#include "amiga/os3support.h"
struct Device *TimerBase;
@@ -28,9 +27,42 @@ struct TimerIFace *ITimer;
struct TimeRequest *tioreq;
struct MsgPort *msgport;
-void ami_schedule_open_timer(void);
-void ami_schedule_close_timer(void);
+/**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made / ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ * \return NSERROR_OK on sucess or appropriate error on faliure
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror ami_schedule(int t, void (*callback)(void *p), void *p);
+
+/**
+ * Initialise amiga scheduler
+ *
+ * /return true if initialised ok or false on error.
+ */
BOOL ami_schedule_create(void);
+
+/**
+ * Finalise amiga scheduler
+ *
+ */
void ami_schedule_free(void);
+
+/**
+ * Process events up to current time.
+ *
+ * This implementation only takes the top entry off the heap, it does not
+ * venture to later scheduled events until the next time it is called -
+ * immediately afterwards, if we're in a timer signalled loop.
+ */
void schedule_run(BOOL poll);
+
+void ami_schedule_open_timer(void);
+void ami_schedule_close_timer(void);
+
#endif
diff --git a/amiga/tree.c b/amiga/tree.c
index 8cffdb2..fa12528 100644
--- a/amiga/tree.c
+++ b/amiga/tree.c
@@ -1390,11 +1390,11 @@ void ami_tree_redraw_request(int x, int y, int width, int height, void *data)
atrr_data->height = height;
atrr_data->twin = (struct treeview_window *)data;
- /**TODO: Queue these requests properly like the main browser code does
+ /** /todo Queue these requests properly like the main browser code does
**/
if(nsoption_bool(direct_render) == false)
- schedule(0, ami_tree_redraw_req, atrr_data);
+ ami_schedule(0, ami_tree_redraw_req, atrr_data);
else
- schedule(0, ami_tree_redraw_req_dr, atrr_data);
+ am_schedule(0, ami_tree_redraw_req_dr, atrr_data);
}
diff --git a/atari/gui.c b/atari/gui.c
index df02973..d838644 100644
--- a/atari/gui.c
+++ b/atari/gui.c
@@ -30,7 +30,6 @@
#include <stdbool.h>
#include <hubbub/hubbub.h>
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/log.h"
#include "utils/messages.h"
@@ -597,7 +596,7 @@ static void throbber_advance( void * data )
return;
toolbar_throbber_progress(gw->root->toolbar);
- schedule(100, throbber_advance, gw );
+ atari_schedule(1000, throbber_advance, gw );
}
static void gui_window_start_throbber(struct gui_window *w)
@@ -607,7 +606,7 @@ static void gui_window_start_throbber(struct gui_window *w)
return;
toolbar_set_throbber_state(w->root->toolbar, true);
- schedule(100, throbber_advance, w );
+ atari_schedule(1000, throbber_advance, w );
rendering = true;
}
@@ -618,7 +617,7 @@ static void gui_window_stop_throbber(struct gui_window *w)
if (w->root->toolbar->throbber.running == false)
return;
- schedule_remove(throbber_advance, w);
+ atari_schedule(-1, throbber_advance, w);
toolbar_set_throbber_state(w->root->toolbar, false);
@@ -1084,6 +1083,7 @@ static struct gui_fetch_table atari_fetch_table = {
static struct gui_browser_table atari_browser_table = {
.poll = gui_poll,
+ .schedule = atari_schedule,
.quit = gui_quit,
.cert_verify = gui_cert_verify,
diff --git a/atari/schedule.c b/atari/schedule.c
index a91c510..02a3762 100755
--- a/atari/schedule.c
+++ b/atari/schedule.c
@@ -22,12 +22,15 @@
#include <sys/time.h>
#include <time.h>
-#include "utils/schedule.h"
#include "atari/schedule.h"
+#ifdef DEBUG_SCHEDULER
#include "utils/log.h"
+#else
+#define LOG(X)
+#endif
-#define CS_NOW() ((clock() * 100) / CLOCKS_PER_SEC)
+#define MS_NOW() ((clock() * 1000) / CLOCKS_PER_SEC)
/* linked list of scheduled callbacks */
static struct nscallback *schedule_list = NULL;
@@ -47,45 +50,6 @@ static int max_scheduled;
static int cur_scheduled;
/**
- * Schedule a callback.
- *
- * \param tival interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-void schedule( int cs_ival, void (*callback)(void *p), void *p)
-{
- struct nscallback *nscb;
-
- /*
- remove any callback of this kind,
- other frontend do this, too. framebuffer frontend doesn't do it.
- */
- schedule_remove(callback, p);
-
- nscb = calloc(1, sizeof(struct nscallback));
-
- nscb->timeout = CS_NOW() + cs_ival;
-#ifdef DEBUG_SCHEDULER
- LOG(("adding callback %p for %p(%p) at %d cs", nscb, callback, p, nscb->timeout ));
-#endif
- nscb->callback = callback;
- nscb->p = p;
-
- /* add to list front */
- nscb->next = schedule_list;
- schedule_list = nscb;
- cur_scheduled++;
- if( cur_scheduled > max_scheduled )
- max_scheduled = cur_scheduled;
-}
-
-
-
-/**
* Unschedule a callback.
*
* \param callback callback function
@@ -94,18 +58,18 @@ void schedule( int cs_ival, void (*callback)(void *p), void *p)
* All scheduled callbacks matching both callback and p are removed.
*/
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- if (schedule_list == NULL)
- return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
-#ifdef DEBUG_SCHEDULER
LOG(("removing %p, %p", callback, p));
-#endif
cur_nscb = schedule_list;
prev_nscb = NULL;
@@ -114,9 +78,8 @@ void schedule_remove(void (*callback)(void *p), void *p)
if ((cur_nscb->callback == callback) &&
(cur_nscb->p == p)) {
/* item to remove */
-#ifdef DEBUG_SCHEDULER
- LOG(("callback entry %p removing %p(%p)", cur_nscb, cur_nscb->callback, cur_nscb->p));
-#endif
+ LOG(("callback entry %p removing %p(%p)",
+ cur_nscb, cur_nscb->callback, cur_nscb->p));
/* remove callback */
unlnk_nscb = cur_nscb;
@@ -135,20 +98,51 @@ void schedule_remove(void (*callback)(void *p), void *p)
cur_nscb = prev_nscb->next;
}
}
+ return NSERROR_OK;
+}
+
+/* exported function documented in atari/schedule.h */
+nserror atari_schedule(int ival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ nserror ret;
+
+ /* remove any existing callback of this kind */
+ ret = schedule_remove(callback, p);
+ if ((ival < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ nscb = calloc(1, sizeof(struct nscallback));
+
+ nscb->timeout = MS_NOW() + ival;
+
+ LOG(("adding callback %p for %p(%p) at %d ms",
+ nscb, callback, p, nscb->timeout ));
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+ cur_scheduled++;
+ if( cur_scheduled > max_scheduled ) {
+ max_scheduled = cur_scheduled;
+ }
+
+ return NSERROR_OK;
}
-/**
- * Process events up to current time.
- */
-int
-schedule_run(void)
+/* exported function documented in atari/schedule.h */
+int schedule_run(void)
{
unsigned long nexttime;
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- unsigned long now = CS_NOW();
+ unsigned long now = MS_NOW();
if (schedule_list == NULL)
return -1;
@@ -170,9 +164,9 @@ schedule_run(void)
prev_nscb->next = unlnk_nscb->next;
}
-#ifdef DEBUG_SCHEDULER
- LOG(("callback entry %p running %p(%p)", unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
-#endif
+ LOG(("callback entry %p running %p(%p)",
+ unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
+
/* call callback */
unlnk_nscb->callback(unlnk_nscb->p);
free(unlnk_nscb);
@@ -180,9 +174,8 @@ schedule_run(void)
/* need to deal with callback modifying the list. */
if (schedule_list == NULL) {
-#ifdef DEBUG_SCHEDULER
LOG(("schedule_list == NULL"));
-#endif
+
return -1; /* no more callbacks scheduled */
}
@@ -204,21 +197,22 @@ schedule_run(void)
}
/* make rettime relative to now and convert to ms */
- nexttime = (nexttime - now)*10;
-#ifdef DEBUG_SCHEDULER
+ nexttime = nexttime - now;
+
LOG(("returning time to next event as %ldms", nexttime ));
-#endif
+
/*return next event time in milliseconds (24days max wait) */
- return ( nexttime );
+ return nexttime;
}
+/* exported function documented in atari/schedule.h */
void list_schedule(void)
{
struct timeval tv;
struct nscallback *cur_nscb;
- LOG(("schedule list at cs clock %ld", CS_NOW() ));
+ LOG(("schedule list at ms clock %ld", MS_NOW() ));
cur_nscb = schedule_list;
while (cur_nscb != NULL) {
diff --git a/atari/schedule.h b/atari/schedule.h
index e21b759..47d8c2d 100755
--- a/atari/schedule.h
+++ b/atari/schedule.h
@@ -17,10 +17,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NS_SCHEDULE_H
-#define NS_SCHEDULE_H
+#ifndef NS_ATARI_SCHEDULE_H
+#define NS_ATARI_SCHEDULE_H
-void list_schedule(void);
+/**
+ * Process events up to current time.
+ */
int schedule_run(void);
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror atari_schedule(int cs_ival, void (*callback)(void *p), void *p);
+
+/**
+ * LOG all current scheduled events.
+ */
+void list_schedule(void);
+
#endif
diff --git a/beos/gui.cpp b/beos/gui.cpp
index 646356a..365a356 100644
--- a/beos/gui.cpp
+++ b/beos/gui.cpp
@@ -1049,6 +1049,7 @@ static struct gui_fetch_table beos_fetch_table = {
static struct gui_browser_table beos_browser_table = {
gui_poll,
+ beos_schedule,
gui_quit,
NULL, //set_search_ico
gui_launch_url,
diff --git a/beos/gui.h b/beos/gui.h
index 24223a1..642441f 100644
--- a/beos/gui.h
+++ b/beos/gui.h
@@ -51,9 +51,6 @@ virtual void AboutRequested();
virtual bool QuitRequested();
};
-
-extern void schedule_run(void);
-
extern BWindow *wndAbout;
extern BWindow *wndTooltip;
diff --git a/beos/scaffolding.cpp b/beos/scaffolding.cpp
index fa9549c..35153b3 100644
--- a/beos/scaffolding.cpp
+++ b/beos/scaffolding.cpp
@@ -62,7 +62,6 @@ extern "C" {
#include "render/font.h"
#include "render/form.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
#include "utils/log.h"
}
@@ -75,7 +74,7 @@ extern "C" {
//#include "beos/completion.h"
#include "beos/throbber.h"
#include "beos/window.h"
-//#include "beos/schedule.h"
+#include "beos/schedule.h"
//#include "beos/download.h"
#define TOOLBAR_HEIGHT 32
@@ -1324,7 +1323,7 @@ void nsbeos_throb(void *p)
g->top_view->UnlockLooper();
- schedule(10, nsbeos_throb, p);
+ beos_schedule(100, nsbeos_throb, p);
}
@@ -2190,7 +2189,7 @@ void gui_window_start_throbber(struct gui_window* _g)
nsbeos_window_update_back_forward(g);
- schedule(10, nsbeos_throb, g);
+ beos_schedule(100, nsbeos_throb, g);
}
void gui_window_stop_throbber(struct gui_window* _g)
@@ -2199,7 +2198,7 @@ void gui_window_stop_throbber(struct gui_window* _g)
nsbeos_window_update_back_forward(g);
- schedule_remove(nsbeos_throb, g);
+ beos_schedule(-1, nsbeos_throb, g);
if (!g->top_view->LockLooper())
return;
diff --git a/beos/schedule.cpp b/beos/schedule.cpp
index db0992e..75e3490 100644
--- a/beos/schedule.cpp
+++ b/beos/schedule.cpp
@@ -23,7 +23,7 @@
#include <List.h>
extern "C" {
-#include "utils/schedule.h"
+#include "beos/schedule.h"
#include "desktop/browser.h"
#ifdef DEBUG_BEOS_SCHEDULE
@@ -65,7 +65,7 @@ nsbeos_schedule_kill_callback(void *_target, void *_match)
return false;
}
-void
+static void
schedule_remove(void (*callback)(void *p), void *p)
{
LOG(("schedule_remove() for %p(%p)", cb->callback, cb->context));
@@ -75,22 +75,26 @@ schedule_remove(void (*callback)(void *p), void *p)
cb_match.callback = callback;
cb_match.context = p;
-
callbacks->DoForEach(nsbeos_schedule_kill_callback, &cb_match);
}
-void
-schedule(int t, void (*callback)(void *p), void *p)
+nserror beos_schedule(int t, void (*callback)(void *p), void *p)
{
- LOG(("schedule(%d, %p, %p)", t, cb->callback, cb->context));
- if (callbacks == NULL)
+ LOG(("t:%d cb:%p p:%p", t, cb->callback, cb->context));
+
+ if (callbacks == NULL) {
callbacks = new BList;
+ }
- bigtime_t timeout = system_time() + t * 10 * 1000LL;
- const int msec_timeout = t * 10;
- _nsbeos_callback_t *cb = (_nsbeos_callback_t *)malloc(sizeof(_nsbeos_callback_t));
/* Kill any pending schedule of this kind. */
schedule_remove(callback, p);
+
+ if (t < 0) {
+ return NSERROR_OK;
+ }
+
+ bigtime_t timeout = system_time() + t * 1000LL;
+ _nsbeos_callback_t *cb = (_nsbeos_callback_t *)malloc(sizeof(_nsbeos_callback_t));
cb->callback = callback;
cb->context = p;
cb->callback_killed = cb->callback_fired = false;
@@ -99,6 +103,8 @@ schedule(int t, void (*callback)(void *p), void *p)
earliest_callback_timeout = timeout;
}
callbacks->AddItem(cb);
+
+ return NSERROR_OK;
}
bool
diff --git a/beos/schedule.h b/beos/schedule.h
index 02205ba..a446156 100644
--- a/beos/schedule.h
+++ b/beos/schedule.h
@@ -19,8 +19,11 @@
#ifndef NETSURF_BEOS_CALLBACK_H
#define NETSURF_BEOS_CALLBACK_H 1
-typedef void (*beos_callback)(void *p);
-
extern bigtime_t earliest_callback_timeout;
+extern nserror beos_schedule(int t, void (*callback)(void *p), void *p);
+
+extern void schedule_run(void);
+
+
#endif /* NETSURF_BEOS_CALLBACK_H */
diff --git a/cocoa/apple_image.m b/cocoa/apple_image.m
index ab17f8a..c6f9df3 100644
--- a/cocoa/apple_image.m
+++ b/cocoa/apple_image.m
@@ -25,7 +25,8 @@
#include "image/bitmap.h"
#include "desktop/plotters.h"
#include "utils/utils.h"
-#include "utils/schedule.h"
+
+#include "cocoa/schedule.h"
typedef struct apple_image_content {
struct content base;
@@ -147,7 +148,7 @@ static void animate_image_cb( void *ptr )
data.redraw.object = &ai->base;
content_broadcast( &ai->base, CONTENT_MSG_REDRAW, data );
- schedule( ai->frameTimes[ai->currentFrame], animate_image_cb, ai );
+ cocoa_schedule(ai->frameTimes[ai->currentFrame], animate_image_cb, ai );
}
/**
@@ -190,10 +191,10 @@ bool apple_image_convert(struct content *c)
ai->frameTimes = calloc( ai->frames , sizeof(int));
for (NSUInteger i = 0; i < frames; i++) {
[image setProperty: NSImageCurrentFrame withValue: [NSNumber numberWithUnsignedInteger: i]];
- ai->frameTimes[i] = 100 * [[image valueForProperty: NSImageCurrentFrameDuration] floatValue];
+ ai->frameTimes[i] = 1000 * [[image valueForProperty: NSImageCurrentFrameDuration] floatValue];
}
[image setProperty: NSImageCurrentFrame withValue: [NSNumber numberWithUnsignedInteger: 0]];
- schedule( ai->frameTimes[0], animate_image_cb, ai );
+ cocoa_schedule( ai->frameTimes[0], animate_image_cb, ai );
}
return true;
@@ -206,7 +207,7 @@ void apple_image_destroy(struct content *c)
[(id)ai_c->bitmap release];
ai_c->bitmap = NULL;
- schedule_remove( animate_image_cb, c );
+ cocoa_schedule(-1, animate_image_cb, c );
}
diff --git a/cocoa/gui.m b/cocoa/gui.m
index eba3301..9ba6144 100644
--- a/cocoa/gui.m
+++ b/cocoa/gui.m
@@ -25,6 +25,7 @@
#import "cocoa/BrowserWindowController.h"
#import "cocoa/FormSelectMenu.h"
#import "cocoa/fetch.h"
+#import "cocoa/schedule.h"
#import "desktop/gui.h"
#import "desktop/netsurf.h"
@@ -294,6 +295,7 @@ struct gui_window_table *cocoa_window_table = &window_table;
static struct gui_browser_table browser_table = {
.poll = gui_poll,
+ .schedule = cocoa_schedule,
.launch_url = gui_launch_url,
.create_form_select_menu = gui_create_form_select_menu,
diff --git a/cocoa/selection.h b/cocoa/schedule.h
similarity index 91%
copy from cocoa/selection.h
copy to cocoa/schedule.h
index 67331ea..43b2c14 100644
--- a/cocoa/selection.h
+++ b/cocoa/schedule.h
@@ -16,4 +16,4 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-struct gui_clipboard_table *cocoa_clipboard_table;
+nserror cocoa_schedule(int t, void (*callback)(void *p), void *p);
diff --git a/cocoa/schedule.m b/cocoa/schedule.m
index 1ad75b3..2dd9a81 100644
--- a/cocoa/schedule.m
+++ b/cocoa/schedule.m
@@ -17,7 +17,8 @@
*/
#import <Cocoa/Cocoa.h>
-#import "utils/schedule.h"
+
+#import "cocoa/schedule.h"
@interface ScheduledCallback : NSObject {
void (*callback)( void *userData );
@@ -73,18 +74,15 @@ static NSMutableSet *timerSet = nil;
@end
-/* In platform specific schedule.c. */
-void schedule(int t, void (*callback)(void *p), void *p)
-{
- ScheduledCallback *cb = [[ScheduledCallback alloc] initWithCallback: callback userData: p];
- [cb schedule: (NSTimeInterval)t / 100];
- [cb release];
-}
-
-void schedule_remove(void (*callback)(void *p), void *p)
+/* exported interface documented in cocoa/schedule.h */
+nserror cocoa_schedule(int t, void (*callback)(void *p), void *p)
{
ScheduledCallback *cb = [[ScheduledCallback alloc] initWithCallback: callback userData: p];
[timerSet removeObject: cb];
+ if (t >= 0) {
+ [cb schedule: (NSTimeInterval)t / 1000];
+ }
[cb release];
-}
+ return NSERROR_OK;
+}
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index d58b7d5..612b77d 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -36,25 +36,25 @@
#include <strings.h>
#include <time.h>
#include <sys/stat.h>
+#include <openssl/ssl.h>
#include <libwapcaplet/libwapcaplet.h>
#include "utils/config.h"
-#include <openssl/ssl.h>
-#include "content/fetch.h"
-#include "content/fetchers/curl.h"
-#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/gui_factory.h"
#include "utils/corestrings.h"
#include "utils/nsoption.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
#include "utils/ring.h"
#include "utils/useragent.h"
+#include "content/fetch.h"
+#include "content/fetchers/curl.h"
+#include "content/urldb.h"
+
/* uncomment this to use scheduler based calling
#define FETCHER_CURLL_SCHEDULED 1
*/
@@ -504,7 +504,7 @@ bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
codem = curl_multi_add_handle(fetch_curl_multi, fetch->curl_handle);
assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
- schedule(1, (schedule_callback_fn)fetch_curl_poll, NULL);
+ guit->browser->schedule(10, (void *)fetch_curl_poll, NULL);
return true;
}
@@ -837,7 +837,7 @@ void fetch_curl_poll(lwc_string *scheme_ignored)
#ifdef FETCHER_CURLL_SCHEDULED
if (running != 0) {
- schedule(1, (schedule_callback_fn)fetch_curl_poll, fetch_curl_poll);
+ guit->browser->schedule(10, fetch_curl_poll, fetch_curl_poll);
}
#endif
}
diff --git a/content/hlcache.c b/content/hlcache.c
index 618f4fd..16f9697 100644
--- a/content/hlcache.c
+++ b/content/hlcache.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
+#include "desktop/gui_factory.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "content/mimesniff.h"
@@ -31,7 +32,6 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/ring.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/utils.h"
@@ -146,7 +146,7 @@ static void hlcache_clean(void *ignored)
llcache_clean();
/* Re-schedule ourselves */
- schedule(hlcache->params.bg_clean_time / 10, hlcache_clean, NULL);
+ guit->browser->schedule(hlcache->params.bg_clean_time, hlcache_clean, NULL);
}
/**
@@ -536,7 +536,7 @@ hlcache_initialise(const struct hlcache_parameters *hlcache_parameters)
hlcache->params = *hlcache_parameters;
/* Schedule the cache cleanup */
- schedule(hlcache->params.bg_clean_time / 10, hlcache_clean, NULL);
+ guit->browser->schedule(hlcache->params.bg_clean_time, hlcache_clean, NULL);
return NSERROR_OK;
}
@@ -545,7 +545,7 @@ hlcache_initialise(const struct hlcache_parameters *hlcache_parameters)
void hlcache_stop(void)
{
/* Remove the hlcache_clean schedule */
- schedule_remove(hlcache_clean, NULL);
+ guit->browser->schedule(-1, hlcache_clean, NULL);
}
/* See hlcache.h for documentation */
diff --git a/desktop/browser.c b/desktop/browser.c
index 03c7a8e..b1e4b75 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -63,7 +63,6 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsurl.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/utils.h"
#include "utils/utf8.h"
@@ -1327,9 +1326,10 @@ static nserror browser_window_callback(hlcache_handle *c,
browser_window_history_update(bw, c);
hotlist_update_url(hlcache_handle_get_url(c));
- if (bw->refresh_interval != -1)
- schedule(bw->refresh_interval,
+ if (bw->refresh_interval != -1) {
+ guit->browser->schedule(bw->refresh_interval * 10,
browser_window_refresh, bw);
+ }
break;
case CONTENT_MSG_ERRORCODE:
@@ -1620,10 +1620,11 @@ void browser_window_destroy_internal(struct browser_window *bw)
LOG(("Destroying window"));
- if (bw->children != NULL || bw->iframes != NULL)
+ if (bw->children != NULL || bw->iframes != NULL) {
browser_window_destroy_children(bw);
+ }
- schedule_remove(browser_window_refresh, bw);
+ guit->browser->schedule(-1, browser_window_refresh, bw);
/* If this brower window is not the root window, and has focus, unset
* the root browser window's focus pointer. */
@@ -2208,7 +2209,7 @@ void browser_window_stop(struct browser_window *bw)
assert(error == NSERROR_OK);
}
- schedule_remove(browser_window_refresh, bw);
+ guit->browser->schedule(-1, browser_window_refresh, bw);
if (bw->children) {
children = bw->rows * bw->cols;
diff --git a/desktop/gui.h b/desktop/gui.h
index 85f1265..361c6bd 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -75,7 +75,8 @@ typedef struct nsnsclipboard_styles {
plot_font_style_t style; /**< Style to give text run */
} nsclipboard_styles;
-/** Graphical user interface window function table
+/**
+ * Graphical user interface window function table.
*
* function table implementing window operations
*/
@@ -176,7 +177,9 @@ struct gui_window_table {
*/
void (*set_title)(struct gui_window *g, const char *title);
- /** set the navigation url. */
+ /**
+ * set the navigation url.
+ */
void (*set_url)(struct gui_window *g, const char *url);
/** set favicon */
@@ -209,7 +212,7 @@ struct gui_window_table {
/**
* Remove the caret, if present.
*
- * \param g window with caret
+ * \param g window with caret
*/
void (*remove_caret)(struct gui_window *g);
@@ -269,8 +272,9 @@ struct gui_window_table {
void (*start_selection)(struct gui_window *g);
};
+
/**
- * function table for download windows
+ * function table for download windows.
*/
struct gui_download_table {
struct gui_download_window *(*create)(struct download_context *ctx, struct gui_window *parent);
@@ -282,8 +286,9 @@ struct gui_download_table {
void (*done)(struct gui_download_window *dw);
};
+
/**
- * function table for clipboard operations
+ * function table for clipboard operations.
*/
struct gui_clipboard_table {
/**
@@ -305,6 +310,7 @@ struct gui_clipboard_table {
void (*set)(const char *buffer, size_t length, nsclipboard_styles styles[], int n_styles);
};
+
/**
* function table for fetcher operations
*/
@@ -390,8 +396,9 @@ struct gui_fetch_table {
};
+
/**
- * User interface utf8 characterset conversion routines
+ * User interface utf8 characterset conversion routines.
*/
struct gui_utf8_table {
/**
@@ -415,7 +422,9 @@ struct gui_utf8_table {
nserror (*local_to_utf8)(const char *string, size_t len, char **result);
};
-/** Graphical user interface browser misc function table
+
+/**
+ * Graphical user interface browser misc function table.
*
* function table implementing GUI interface to miscelaneous browser
* functionality
@@ -429,6 +438,23 @@ struct gui_browser_table {
*/
void (*poll)(bool active);
+ /**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made in ms or
+ * negative value to remove any existing callback.
+ * \param callback callback function
+ * \param p user parameter passed to callback function
+ * \return NSERROR_OK on sucess or appropriate error on faliure
+ *
+ * The callback function will be called as soon as possible
+ * after the timeout has elapsed.
+ *
+ * Additional calls with the same callback and user parameter will
+ * reset the callback time to the newly specified value.
+ *
+ */
+ nserror (*schedule)(int t, void (*callback)(void *p), void *p);
/* Optional entries */
@@ -474,7 +500,8 @@ struct gui_browser_table {
*/
struct gui_table {
- /** Browser table.
+ /**
+ * Browser table.
*
* Provides miscellaneous browser functionality. The table
* is mandantory and must be provided.
@@ -493,7 +520,8 @@ struct gui_table {
/** Fetcher table */
struct gui_fetch_table *fetch;
- /** UTF8 table
+ /**
+ * UTF8 table.
*
* Provides for conversion between the gui local character
* encoding and utf8. The table optional and may be NULL which
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index 8996ab5..638abfd 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -443,6 +443,10 @@ static nserror verify_browser_register(struct gui_browser_table *gbt)
return NSERROR_BAD_PARAMETER;
}
+ if (gbt->schedule == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
/* fill in the optional entries with defaults */
if (gbt->quit == NULL) {
gbt->quit = gui_default_quit;
diff --git a/framebuffer/gui.c b/framebuffer/gui.c
index cee58b9..7d3e95c 100644
--- a/framebuffer/gui.c
+++ b/framebuffer/gui.c
@@ -40,7 +40,6 @@
#include "utils/filepath.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/types.h"
#include "desktop/textinput.h"
#include "render/form.h"
@@ -557,7 +556,7 @@ static bool nslog_stream_configure(FILE *fptr)
-static void gui_poll(bool active)
+static void framebuffer_poll(bool active)
{
nsfb_event_t event;
int timeout; /* timeout in miliseconds */
@@ -1696,7 +1695,7 @@ throbber_advance(void *pw)
if (g->throbber_index >= 0) {
fbtk_set_bitmap(g->throbber, image);
- schedule(10, throbber_advance, g);
+ framebuffer_schedule(100, throbber_advance, g);
}
}
@@ -1704,7 +1703,7 @@ static void
gui_window_start_throbber(struct gui_window *g)
{
g->throbber_index = 0;
- schedule(10, throbber_advance, g);
+ framebuffer_schedule(100, throbber_advance, g);
}
static void
@@ -1785,7 +1784,8 @@ static struct gui_window_table framebuffer_window_table = {
static struct gui_browser_table framebuffer_browser_table = {
- .poll = gui_poll,
+ .poll = framebuffer_poll,
+ .schedule = framebuffer_schedule,
.quit = gui_quit,
};
diff --git a/framebuffer/schedule.c b/framebuffer/schedule.c
index 43f5318..151b6f9 100644
--- a/framebuffer/schedule.c
+++ b/framebuffer/schedule.c
@@ -20,10 +20,15 @@
#include <time.h>
#include <stdlib.h>
-#include "utils/schedule.h"
+#include "utils/log.h"
+
#include "framebuffer/schedule.h"
-#include "utils/log.h"
+#ifdef DEBUG_SCHEDULER
+#define SRLOG(x) LOG(x)
+#else
+#define SRLOG(x)
+#endif
/* linked list of scheduled callbacks */
static struct nscallback *schedule_list = NULL;
@@ -39,39 +44,6 @@ struct nscallback
void *p;
};
-
-/**
- * Schedule a callback.
- *
- * \param tival interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-
-void schedule(int cs_ival, void (*callback)(void *p), void *p)
-{
- struct nscallback *nscb;
- struct timeval tv;
-
- tv.tv_sec = cs_ival / 100; /* cs to seconds */
- tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */
-
- nscb = calloc(1, sizeof(struct nscallback));
-
- gettimeofday(&nscb->tv, NULL);
- timeradd(&nscb->tv, &tv, &nscb->tv);
-
- nscb->callback = callback;
- nscb->p = p;
-
- /* add to list front */
- nscb->next = schedule_list;
- schedule_list = nscb;
-}
-
/**
* Unschedule a callback.
*
@@ -80,17 +52,18 @@ void schedule(int cs_ival, void (*callback)(void *p), void *p)
*
* All scheduled callbacks matching both callback and p are removed.
*/
-
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- if (schedule_list == NULL)
- return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
- LOG(("removing %p, %p", callback, p));
+ SRLOG(("removing %p, %p", callback, p));
cur_nscb = schedule_list;
prev_nscb = NULL;
@@ -100,7 +73,7 @@ void schedule_remove(void (*callback)(void *p), void *p)
(cur_nscb->p == p)) {
/* item to remove */
- LOG(("callback entry %p removing %p(%p)",
+ SRLOG(("callback entry %p removing %p(%p)",
cur_nscb, cur_nscb->callback, cur_nscb->p));
/* remove callback */
@@ -119,16 +92,45 @@ void schedule_remove(void (*callback)(void *p), void *p)
cur_nscb = prev_nscb->next;
}
}
+
+ return NSERROR_OK;
}
-/**
- * Process scheduled callbacks up to current time.
- *
- * @return The number of milliseconds untill the next scheduled event
- * or -1 for no event.
- */
-int
-schedule_run(void)
+/* exported function documented in framebuffer/schedule.h */
+nserror framebuffer_schedule(int tival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+ nserror ret;
+
+ /* ensure uniqueness of the callback and context */
+ ret = schedule_remove(callback, p);
+ if ((tival < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ SRLOG(("Adding %p(%p) in %d", callback, p, tival));
+
+ tv.tv_sec = tival / 1000; /* miliseconds to seconds */
+ tv.tv_usec = (tival % 1000) * 1000; /* remainder to microseconds */
+
+ nscb = calloc(1, sizeof(struct nscallback));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in framebuffer/schedule.h */
+int schedule_run(void)
{
struct timeval tv;
struct timeval nexttime;
@@ -188,7 +190,8 @@ schedule_run(void)
/* make rettime relative to now */
timersub(&nexttime, &tv, &rettime);
- /*LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000))); */
+ SRLOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
+
/* return next event time in milliseconds (24days max wait) */
return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
}
diff --git a/framebuffer/schedule.h b/framebuffer/schedule.h
index 2c9b55f..4e94da6 100644
--- a/framebuffer/schedule.h
+++ b/framebuffer/schedule.h
@@ -19,7 +19,27 @@
#ifndef FRAMEBUFFER_SCHEDULE_H
#define FRAMEBUFFER_SCHEDULE_H
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+
+nserror framebuffer_schedule(int tival, void (*callback)(void *p), void *p);
+
+/**
+ * Process scheduled callbacks up to current time.
+ *
+ * @return The number of milliseconds untill the next scheduled event
+ * or -1 for no event.
+ */
int schedule_run(void);
+
void list_schedule(void);
#endif
diff --git a/gtk/gui.c b/gtk/gui.c
index a3bf57c..40c2ad6 100644
--- a/gtk/gui.c
+++ b/gtk/gui.c
@@ -522,7 +522,7 @@ static bool nslog_stream_configure(FILE *fptr)
-static void gui_poll(bool active)
+static void nsgtk_poll(bool active)
{
CURLMcode code;
fd_set read_fd_set, write_fd_set, exc_fd_set;
@@ -990,7 +990,8 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
static struct gui_browser_table nsgtk_browser_table = {
- .poll = gui_poll,
+ .poll = nsgtk_poll,
+ .schedule = nsgtk_schedule,
.quit = gui_quit,
.set_search_ico = gui_set_search_ico,
diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c
index 36ba13a..ffe6a22 100644
--- a/gtk/scaffolding.c
+++ b/gtk/scaffolding.c
@@ -26,7 +26,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/log.h"
#include "utils/nsoption.h"
@@ -70,7 +69,7 @@
#include "gtk/gdk.h"
#include "gtk/scaffolding.h"
#include "gtk/tabs.h"
-
+#include "gtk/schedule.h"
/** Macro to define a handler for menu, button and activate events. */
@@ -329,7 +328,7 @@ static void nsgtk_throb(void *p)
gtk_image_set_from_pixbuf(g->throbber, nsgtk_throbber->framedata[
g->throb_frame]);
- schedule(10, nsgtk_throb, p);
+ nsgtk_schedule(100, nsgtk_throb, p);
}
static guint nsgtk_scaffolding_update_edit_actions_sensitivity(
@@ -2175,7 +2174,7 @@ void gui_window_start_throbber(struct gui_window* _g)
nsgtk_window_update_back_forward(g);
- schedule(10, nsgtk_throb, g);
+ nsgtk_schedule(100, nsgtk_throb, g);
}
void gui_window_stop_throbber(struct gui_window* _g)
@@ -2184,7 +2183,7 @@ void gui_window_stop_throbber(struct gui_window* _g)
if (g == NULL)
return;
nsgtk_window_update_back_forward(g);
- schedule_remove(nsgtk_throb, g);
+ nsgtk_schedule(-1, nsgtk_throb, g);
if (g->buttons[STOP_BUTTON] != NULL)
g->buttons[STOP_BUTTON]->sensitivity = false;
if (g->buttons[RELOAD_BUTTON] != NULL)
diff --git a/gtk/schedule.c b/gtk/schedule.c
index 5b168b6..e28675a 100644
--- a/gtk/schedule.c
+++ b/gtk/schedule.c
@@ -20,7 +20,8 @@
#include <stdlib.h>
#include <stdbool.h>
-#include "utils/schedule.h"
+#include "utils/errors.h"
+
#include "gtk/schedule.h"
#ifdef DEBUG_GTK_SCHEDULE
@@ -71,7 +72,7 @@ nsgtk_schedule_kill_callback(void *_target, void *_match)
}
}
-void
+static void
schedule_remove(void (*callback)(void *p), void *p)
{
_nsgtk_callback_t cb_match = {
@@ -87,19 +88,27 @@ schedule_remove(void (*callback)(void *p), void *p)
nsgtk_schedule_kill_callback, &cb_match);
}
-void
-schedule(int t, void (*callback)(void *p), void *p)
+/* exported interface documented in gtk/schedule.h */
+nserror nsgtk_schedule(int t, void (*callback)(void *p), void *p)
{
- const int msec_timeout = t * 10;
- _nsgtk_callback_t *cb = malloc(sizeof(_nsgtk_callback_t));
+ _nsgtk_callback_t *cb;
+
/* Kill any pending schedule of this kind. */
schedule_remove(callback, p);
+
+ if (t < 0) {
+ return NSERROR_OK;
+ }
+
+ cb = malloc(sizeof(_nsgtk_callback_t));
cb->callback = callback;
cb->context = p;
cb->callback_killed = false;
/* Prepend is faster right now. */
queued_callbacks = g_list_prepend(queued_callbacks, cb);
- g_timeout_add(msec_timeout, nsgtk_schedule_generic_callback, cb);
+ g_timeout_add(t, nsgtk_schedule_generic_callback, cb);
+
+ return NSERROR_OK;
}
bool
diff --git a/gtk/schedule.h b/gtk/schedule.h
index c63215e..0a2d724 100644
--- a/gtk/schedule.h
+++ b/gtk/schedule.h
@@ -19,7 +19,8 @@
#ifndef NETSURF_GTK_CALLBACK_H
#define NETSURF_GTK_CALLBACK_H 1
-typedef void (*gtk_callback)(void *p);
+nserror nsgtk_schedule(int t, void (*callback)(void *p), void *p);
+
bool schedule_run(void);
#endif /* NETSURF_GTK_CALLBACK_H */
diff --git a/image/gif.c b/image/gif.c
index 4bd45c7..5c1b3ab 100644
--- a/image/gif.c
+++ b/image/gif.c
@@ -39,14 +39,15 @@
#include "content/hlcache.h"
#include "utils/nsoption.h"
#include "desktop/plotters.h"
-#include "image/image.h"
-#include "image/bitmap.h"
-#include "image/gif.h"
+#include "desktop/gui_factory.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
+#include "image/image.h"
+#include "image/bitmap.h"
+#include "image/gif.h"
+
typedef struct nsgif_content {
struct content base;
@@ -159,7 +160,7 @@ static void nsgif_animate(void *p)
delay = gif->gif->frames[gif->current_frame].frame_delay;
if (delay < nsoption_int(minimum_gif_delay))
delay = nsoption_int(minimum_gif_delay);
- schedule(delay, nsgif_animate, gif);
+ guit->browser->schedule(delay * 10, nsgif_animate, gif);
}
if ((!nsoption_bool(animate_images)) ||
@@ -292,7 +293,9 @@ static bool nsgif_convert(struct content *c)
/* Schedule the animation if we have one */
gif->current_frame = 0;
if (gif->gif->frame_count_partial > 1)
- schedule(gif->gif->frames[0].frame_delay, nsgif_animate, c);
+ guit->browser->schedule(gif->gif->frames[0].frame_delay * 10,
+ nsgif_animate,
+ c);
/* Exit as a success */
content_set_ready(c);
@@ -351,7 +354,7 @@ static void nsgif_destroy(struct content *c)
nsgif_content *gif = (nsgif_content *) c;
/* Free all the associated memory buffers */
- schedule_remove(nsgif_animate, c);
+ guit->browser->schedule(-1, nsgif_animate, c);
gif_finalise(gif->gif);
free(gif->gif);
}
diff --git a/image/image_cache.c b/image/image_cache.c
index c136908..0512439 100644
--- a/image/image_cache.c
+++ b/image/image_cache.c
@@ -22,7 +22,7 @@
#include <stdbool.h>
#include <string.h>
-#include "utils/schedule.h"
+#include "desktop/gui_factory.h"
#include "utils/log.h"
#include "content/content_protected.h"
@@ -290,9 +290,9 @@ static void image_cache__background_update(void *p)
image_cache__clean(icache);
- schedule((icache->params.bg_clean_time / 10),
- image_cache__background_update,
- icache);
+ guit->browser->schedule(icache->params.bg_clean_time,
+ image_cache__background_update,
+ icache);
}
/* exported interface documented in image_cache.h */
@@ -372,9 +372,9 @@ image_cache_init(const struct image_cache_parameters *image_cache_parameters)
image_cache->params = *image_cache_parameters;
- schedule((image_cache->params.bg_clean_time / 10),
- image_cache__background_update,
- image_cache);
+ guit->browser->schedule(image_cache->params.bg_clean_time,
+ image_cache__background_update,
+ image_cache);
LOG(("Image cache initilised with a limit of %d hysteresis of %d",
image_cache->params.limit, image_cache->params.hysteresis));
@@ -387,7 +387,7 @@ nserror image_cache_fini(void)
{
unsigned int op_count;
- schedule_remove(image_cache__background_update, image_cache);
+ guit->browser->schedule(-1, image_cache__background_update, image_cache);
LOG(("Size at finish %d (in %d)",
image_cache->total_bitmap_size,
diff --git a/monkey/main.c b/monkey/main.c
index 07ce7ee..96476d2 100644
--- a/monkey/main.c
+++ b/monkey/main.c
@@ -21,14 +21,6 @@
#include <stdlib.h>
#include "utils/nsoption.h"
-#include "monkey/poll.h"
-#include "monkey/dispatch.h"
-#include "monkey/browser.h"
-#include "monkey/cert.h"
-#include "monkey/401login.h"
-#include "monkey/filetype.h"
-#include "monkey/fetch.h"
-
#include "content/urldb.h"
#include "content/fetchers/resource.h"
#include "desktop/gui.h"
@@ -37,6 +29,15 @@
#include "utils/filepath.h"
#include "utils/url.h"
+#include "monkey/poll.h"
+#include "monkey/dispatch.h"
+#include "monkey/browser.h"
+#include "monkey/cert.h"
+#include "monkey/401login.h"
+#include "monkey/filetype.h"
+#include "monkey/fetch.h"
+#include "monkey/schedule.h"
+
char **respaths; /** resource search path vector */
/* Stolen from gtk/gui.c */
@@ -103,6 +104,7 @@ static bool nslog_stream_configure(FILE *fptr)
static struct gui_browser_table monkey_browser_table = {
.poll = monkey_poll,
+ .schedule = monkey_schedule,
.quit = monkey_quit,
.launch_url = gui_launch_url,
diff --git a/monkey/schedule.c b/monkey/schedule.c
index c4b1385..e8ec1c6 100644
--- a/monkey/schedule.c
+++ b/monkey/schedule.c
@@ -20,7 +20,7 @@
#include <stdlib.h>
#include <stdbool.h>
-#include "utils/schedule.h"
+#include "utils/errors.h"
#include "monkey/schedule.h"
@@ -75,7 +75,7 @@ nsgtk_schedule_kill_callback(void *_target, void *_match)
}
}
-void
+static void
schedule_remove(void (*callback)(void *p), void *p)
{
_nsgtk_callback_t cb_match = {
@@ -91,20 +91,27 @@ schedule_remove(void (*callback)(void *p), void *p)
nsgtk_schedule_kill_callback, &cb_match);
}
-void
-schedule(int t, void (*callback)(void *p), void *p)
+nserror monkey_schedule(int t, void (*callback)(void *p), void *p)
{
- const int msec_timeout = t * 10;
- _nsgtk_callback_t *cb = malloc(sizeof(_nsgtk_callback_t));
+ _nsgtk_callback_t *cb;
+
/* Kill any pending schedule of this kind. */
schedule_remove(callback, p);
+ if (t < 0) {
+ return NSERROR_OK;
+ }
+
+ cb = malloc(sizeof(_nsgtk_callback_t));
cb->callback = callback;
cb->context = p;
cb->callback_killed = false;
/* Prepend is faster right now. */
- LOG(("queued a callback to %p(%p) for %d msecs time", callback, p, msec_timeout));
+ LOG(("queued a callback to %p(%p) for %d msecs time", callback, p, t));
queued_callbacks = g_list_prepend(queued_callbacks, cb);
- g_timeout_add(msec_timeout, nsgtk_schedule_generic_callback, cb);
+ g_timeout_add(t, nsgtk_schedule_generic_callback, cb);
+
+ return NSERROR_OK;
+
}
bool
diff --git a/monkey/schedule.h b/monkey/schedule.h
index c63215e..44ef9bf 100644
--- a/monkey/schedule.h
+++ b/monkey/schedule.h
@@ -19,7 +19,8 @@
#ifndef NETSURF_GTK_CALLBACK_H
#define NETSURF_GTK_CALLBACK_H 1
-typedef void (*gtk_callback)(void *p);
+nserror monkey_schedule(int t, void (*callback)(void *p), void *p);
+
bool schedule_run(void);
#endif /* NETSURF_GTK_CALLBACK_H */
diff --git a/render/box_construct.c b/render/box_construct.c
index f5ef099..6991025 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -31,25 +31,27 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+
#include "utils/config.h"
#include "content/content_protected.h"
#include "css/css.h"
#include "css/utils.h"
#include "css/select.h"
+#include "desktop/gui_factory.h"
#include "utils/nsoption.h"
-#include "render/box.h"
-#include "render/box_textarea.h"
-#include "render/form.h"
-#include "render/html_internal.h"
#include "utils/corestrings.h"
#include "utils/locale.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/talloc.h"
#include "utils/url.h"
#include "utils/utils.h"
+#include "render/box.h"
+#include "render/box_textarea.h"
+#include "render/form.h"
+#include "render/html_internal.h"
+
/**
* Context for box tree construction
*/
@@ -183,9 +185,7 @@ nserror dom_to_box(dom_node *n, html_content *c, box_construct_complete_cb cb)
ctx->cb = cb;
ctx->bctx = c->bctx;
- schedule(0, (schedule_callback_fn) convert_xml_to_box, ctx);
-
- return NSERROR_OK;
+ return guit->browser->schedule(0, (void *)convert_xml_to_box, ctx);
}
/* mapping from CSS display to box type
@@ -446,7 +446,7 @@ void convert_xml_to_box(struct box_construct_ctx *ctx)
} while (++num_processed < max_processed_before_yield);
/* More work to do: schedule a continuation */
- schedule(0, (schedule_callback_fn) convert_xml_to_box, ctx);
+ guit->browser->schedule(0, (void *)convert_xml_to_box, ctx);
}
/**
diff --git a/render/html.c b/render/html.c
index e375e62..bb24e58 100644
--- a/render/html.c
+++ b/render/html.c
@@ -34,7 +34,6 @@
#include "utils/libdom.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/talloc.h"
#include "utils/url.h"
#include "utils/utf8.h"
@@ -591,6 +590,7 @@ void html_finish_conversion(html_content *c)
error = dom_to_box(html, c, html_box_convert_done);
if (error != NSERROR_OK) {
+ LOG(("box conversion failed"));
dom_node_unref(html);
html_object_free_objects(c);
content_broadcast_errorcode(&c->base, error);
diff --git a/render/html_css.c b/render/html_css.c
index ad24804..b4c25ba 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -28,12 +28,13 @@
#include <stdlib.h>
#include "content/hlcache.h"
+#include "desktop/gui_factory.h"
#include "utils/nsoption.h"
-#include "render/html_internal.h"
#include "utils/corestrings.h"
#include "utils/config.h"
#include "utils/log.h"
-#include "utils/schedule.h"
+
+#include "render/html_internal.h"
static nsurl *html_default_stylesheet_url;
static nsurl *html_adblock_stylesheet_url;
@@ -307,7 +308,7 @@ static void html_css_process_modified_styles(void *pw)
/* If we failed to process any sheet, schedule a retry */
if (all_done == false) {
- schedule(100, html_css_process_modified_styles, c);
+ guit->browser->schedule(1000, html_css_process_modified_styles, c);
}
}
@@ -332,7 +333,7 @@ bool html_css_update_style(html_content *c, dom_node *style)
s->modified = true;
- schedule(0, html_css_process_modified_styles, c);
+ guit->browser->schedule(0, html_css_process_modified_styles, c);
return true;
}
@@ -462,7 +463,7 @@ nserror html_css_free_stylesheets(html_content *html)
{
unsigned int i;
- schedule_remove(html_css_process_modified_styles, html);
+ guit->browser->schedule(-1, html_css_process_modified_styles, html);
for (i = 0; i != html->stylesheet_count; i++) {
if (html->stylesheets[i].sheet != NULL) {
diff --git a/render/html_object.c b/render/html_object.c
index e76919d..6499f24 100644
--- a/render/html_object.c
+++ b/render/html_object.c
@@ -31,12 +31,13 @@
#include "css/utils.h"
#include "utils/nsoption.h"
#include "desktop/scrollbar.h"
-#include "render/box.h"
-#include "render/html_internal.h"
+#include "desktop/gui_factory.h"
#include "utils/corestrings.h"
#include "utils/config.h"
#include "utils/log.h"
-#include "utils/schedule.h"
+
+#include "render/box.h"
+#include "render/html_internal.h"
/* break reference loop */
static void html_object_refresh(void *p);
@@ -335,7 +336,7 @@ html_object_callback(hlcache_handle *object,
case CONTENT_MSG_REFRESH:
if (content_get_type(object) == CONTENT_HTML) {
/* only for HTML objects */
- schedule(event->data.delay * 100,
+ guit->browser->schedule(event->data.delay * 1000,
html_object_refresh, o);
}
@@ -534,7 +535,7 @@ static bool html_replace_object(struct content_html_object *object, nsurl *url)
}
/**
- * schedule() callback for object refresh
+ * schedule callback for object refresh
*/
static void html_object_refresh(void *p)
@@ -630,8 +631,9 @@ nserror html_object_close_objects(html_content *html)
if (content_get_type(object->content) == CONTENT_NONE)
continue;
- if (content_get_type(object->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, object);
+ if (content_get_type(object->content) == CONTENT_HTML) {
+ guit->browser->schedule(-1, html_object_refresh, object);
+ }
content_close(object->content);
}
@@ -646,9 +648,9 @@ nserror html_object_free_objects(html_content *html)
if (victim->content != NULL) {
LOG(("object %p", victim->content));
- if (content_get_type(victim->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, victim);
-
+ if (content_get_type(victim->content) == CONTENT_HTML) {
+ guit->browser->schedule(-1, html_object_refresh, victim);
+ }
hlcache_handle_release(victim->content);
}
diff --git a/riscos/download.c b/riscos/download.c
index b10c6c1..804a664 100644
--- a/riscos/download.c
+++ b/riscos/download.c
@@ -33,7 +33,6 @@
#include <sys/time.h>
#include <time.h>
#include <curl/curl.h>
-
#include "oslib/mimemap.h"
#include "oslib/osargs.h"
#include "oslib/osfile.h"
@@ -42,22 +41,24 @@
#include "oslib/osgbpb.h"
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
+
#include "desktop/gui.h"
#include "desktop/netsurf.h"
#include "desktop/download.h"
-#include "riscos/dialog.h"
#include "utils/nsoption.h"
-#include "riscos/mouse.h"
-#include "riscos/save.h"
-#include "riscos/query.h"
-#include "riscos/wimp.h"
-#include "riscos/wimp_event.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/schedule.h"
#include "utils/url.h"
#include "utils/utf8.h"
#include "utils/utils.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/mouse.h"
+#include "riscos/save.h"
+#include "riscos/query.h"
+#include "riscos/wimp.h"
+#include "riscos/wimp_event.h"
#include "riscos/ucstables.h"
#define ICON_DOWNLOAD_ICON 0
@@ -455,7 +456,7 @@ static void gui_download_window_error(struct gui_download_window *dw,
dw->ctx = NULL;
dw->error = true;
- schedule_remove(ro_gui_download_update_status_wrapper, dw);
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
/* place error message in status icon in red */
strncpy(dw->status, error_msg, sizeof dw->status);
@@ -715,15 +716,16 @@ void ro_gui_download_update_status(struct gui_download_window *dw)
warn_user("WimpError", error->errmess);
}
- if (dw->ctx)
- schedule(100, ro_gui_download_update_status_wrapper, dw);
- else
- schedule_remove(ro_gui_download_update_status_wrapper, dw);
+ if (dw->ctx) {
+ riscos_schedule(1000, ro_gui_download_update_status_wrapper, dw);
+ } else {
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
+ }
}
/**
- * Wrapper for ro_gui_download_update_status(), suitable for schedule().
+ * Wrapper for ro_gui_download_update_status(), suitable for riscos_schedule().
*/
void ro_gui_download_update_status_wrapper(void *p)
@@ -795,10 +797,11 @@ static void gui_download_window_done(struct gui_download_window *dw)
warn_user("SaveError", error->errmess);
}
- if (dw->send_dataload)
+ if (dw->send_dataload) {
ro_gui_download_send_dataload(dw);
+ }
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
}
@@ -889,7 +892,7 @@ bool ro_gui_download_keypress(wimp_key *key)
!nsoption_bool(confirm_overwrite)) && !dw->ctx)
{
/* finished already */
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
return true;
}
@@ -985,7 +988,7 @@ void ro_gui_download_datasave_ack(wimp_message *message)
ro_gui_download_send_dataload(dw);
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
}
@@ -1417,7 +1420,7 @@ void ro_gui_download_send_dataload(struct gui_download_window *dw)
warn_user("WimpError", error->errmess);
}
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
@@ -1480,8 +1483,8 @@ bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit)
return false;
}
- schedule_remove(ro_gui_download_update_status_wrapper, dw);
- schedule_remove(ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
+ riscos_schedule(-1, ro_gui_download_window_destroy_wrapper, dw);
/* remove from list */
if (dw->prev)
@@ -1534,7 +1537,7 @@ bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit)
/**
- * Wrapper for ro_gui_download_window_destroy(), suitable for schedule().
+ * Wrapper for ro_gui_download_window_destroy(), suitable for riscos_schedule().
*/
void ro_gui_download_window_destroy_wrapper(void *p)
@@ -1613,7 +1616,7 @@ void ro_gui_download_overwrite_confirmed(query_id id, enum query_response res, v
ro_gui_download_send_dataload(dw);
- schedule(200, ro_gui_download_window_destroy_wrapper, dw);
+ riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw);
}
}
diff --git a/riscos/gui.c b/riscos/gui.c
index 1663c17..59a0138 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -1077,7 +1077,7 @@ void ro_gui_cleanup(void)
* \param active return as soon as possible
*/
-void gui_poll(bool active)
+static void riscos_poll(bool active)
{
wimp_event_no event;
wimp_block block;
@@ -1116,8 +1116,9 @@ void gui_poll(bool active)
* from gui_multitask(). Scheduled callbacks must only be run from the
* top-level.
*/
- if (event == wimp_NULL_REASON_CODE)
+ if (event == wimp_NULL_REASON_CODE) {
schedule_run();
+ }
ro_gui_window_update_boxes();
@@ -2358,7 +2359,8 @@ static struct gui_fetch_table riscos_fetch_table = {
};
static struct gui_browser_table riscos_browser_table = {
- .poll = gui_poll,
+ .poll = riscos_poll,
+ .schedule = riscos_schedule,
.quit = gui_quit,
.launch_url = gui_launch_url,
diff --git a/riscos/gui.h b/riscos/gui.h
index dbf6373..3ea0c0b 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -123,7 +123,6 @@ void ro_gui_dump_browser_window(struct browser_window *bw);
void ro_gui_drag_box_start(wimp_pointer *pointer);
bool ro_gui_prequit(void);
const char *ro_gui_default_language(void);
-void gui_poll(bool active); /* exported for riscos/wimp_event.c:722 */
char *url_to_path(const char *url);
/* in download.c */
@@ -183,8 +182,24 @@ bits ro_filetype_from_unix_path(const char *unix_path);
/* in schedule.c */
extern bool sched_active;
extern os_t sched_time;
+
+/**
+ * Process events up to current time.
+ */
bool schedule_run(void);
+/**
+ * Schedule a callback.
+ *
+ * \param t interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror riscos_schedule(int t, void (*callback)(void *p), void *p);
+
/* in search.c */
void ro_gui_search_init(void);
void ro_gui_search_prepare(struct browser_window *g);
diff --git a/riscos/gui/progress_bar.c b/riscos/gui/progress_bar.c
index 4457976..f5b4731 100644
--- a/riscos/gui/progress_bar.c
+++ b/riscos/gui/progress_bar.c
@@ -29,10 +29,11 @@
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
+
#include "desktop/plotters.h"
#include "utils/log.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
+
#include "riscos/gui.h"
#include "riscos/tinct.h"
#include "riscos/wimp_event.h"
@@ -159,8 +160,9 @@ void ro_gui_progress_bar_destroy(struct progress_bar *pb)
os_error *error;
assert(pb);
- if (pb->animating)
- schedule_remove(ro_gui_progress_bar_animate, pb);
+ if (pb->animating) {
+ riscos_schedule(-1, ro_gui_progress_bar_animate, pb);
+ }
ro_gui_wimp_event_finalise(pb->w);
error = xwimp_delete_window(pb->w);
if (error) {
@@ -292,12 +294,14 @@ void ro_gui_progress_bar_update(struct progress_bar *pb, int width, int height)
/* update the animation state */
if ((pb->value == 0) || (pb->value == pb->range)) {
- if (pb->animating)
- schedule_remove(ro_gui_progress_bar_animate, pb);
+ if (pb->animating) {
+ riscos_schedule(-1, ro_gui_progress_bar_animate, pb);
+ }
pb->animating = false;
} else {
- if (!pb->animating)
- schedule(20, ro_gui_progress_bar_animate, pb);
+ if (!pb->animating) {
+ riscos_schedule(200, ro_gui_progress_bar_animate, pb);
+ }
pb->animating = true;
}
@@ -372,8 +376,9 @@ void ro_gui_progress_bar_animate(void *p)
if (pb->offset < 0)
pb->offset += progress_width * 2;
- if (pb->animating)
- schedule(20, ro_gui_progress_bar_animate, pb);
+ if (pb->animating) {
+ riscos_schedule(200, ro_gui_progress_bar_animate, pb);
+ }
redraw.w = pb->w;
redraw.box = pb->visible;
diff --git a/riscos/gui/status_bar.c b/riscos/gui/status_bar.c
index 899fe99..46a511f 100644
--- a/riscos/gui/status_bar.c
+++ b/riscos/gui/status_bar.c
@@ -30,7 +30,6 @@
#include "oslib/wimpspriteop.h"
#include "desktop/plotters.h"
#include "utils/log.h"
-#include "utils/schedule.h"
#include "utils/utils.h"
#include "riscos/gui.h"
#include "riscos/wimp.h"
@@ -171,7 +170,7 @@ void ro_gui_status_bar_destroy(struct status_bar *sb)
ro_gui_progress_bar_destroy(sb->pb);
/* Remove any scheduled redraw callbacks */
- schedule_remove(ro_gui_status_bar_redraw_callback, (void *) sb);
+ riscos_schedule(-1, ro_gui_status_bar_redraw_callback, (void *) sb);
free(sb);
}
@@ -331,7 +330,7 @@ void ro_gui_status_bar_set_text(struct status_bar *sb, const char *text)
* { callback, handle } pair is registered at once.
*/
if (sb->visible && text != NULL) {
- schedule(1, ro_gui_status_bar_redraw_callback, (void *) sb);
+ riscos_schedule(10, ro_gui_status_bar_redraw_callback, sb);
}
}
diff --git a/riscos/hotlist.c b/riscos/hotlist.c
index 7910353..14e90fb 100644
--- a/riscos/hotlist.c
+++ b/riscos/hotlist.c
@@ -30,27 +30,29 @@
#include "oslib/osfile.h"
#include "oslib/osmodule.h"
#include "oslib/wimp.h"
+
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "desktop/hotlist.h"
#include "desktop/tree.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/url.h"
+#include "utils/nsoption.h"
+
+#include "riscos/gui.h"
#include "riscos/dialog.h"
#include "riscos/hotlist.h"
#include "riscos/menus.h"
#include "riscos/message.h"
-#include "utils/nsoption.h"
#include "riscos/save.h"
#include "riscos/toolbar.h"
#include "riscos/treeview.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
#include "riscos/query.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/schedule.h"
-#include "utils/utils.h"
-#include "utils/url.h"
static void ro_gui_hotlist_toolbar_update_buttons(void);
static void ro_gui_hotlist_toolbar_save_buttons(char *config);
@@ -543,7 +545,7 @@ void ro_gui_hotlist_add_page(nsurl *url)
* message didn't bounce.
*/
- schedule(0, ro_gui_hotlist_scheduled_callback, NULL);
+ riscos_schedule(0, ro_gui_hotlist_scheduled_callback, NULL);
}
@@ -569,7 +571,7 @@ static void ro_gui_hotlist_addurl_bounce(wimp_message *message)
/* There's no longer any need to listen for the next Null poll. */
- schedule_remove(ro_gui_hotlist_scheduled_callback, NULL);
+ riscos_schedule(-1, ro_gui_hotlist_scheduled_callback, NULL);
}
diff --git a/riscos/schedule.c b/riscos/schedule.c
index 257f2e7..5129005 100644
--- a/riscos/schedule.c
+++ b/riscos/schedule.c
@@ -24,10 +24,11 @@
#include <stdbool.h>
#include <stdlib.h>
+
#include "oslib/os.h"
-#include "riscos/gui.h"
#include "utils/log.h"
-#include "utils/schedule.h"
+
+#include "riscos/gui.h"
/** Entry in the queue of scheduled callbacks. */
@@ -50,25 +51,53 @@ bool sched_active = false;
/** Time of soonest scheduled event (valid only if sched_active is true). */
os_t sched_time;
-
/**
- * Schedule a callback.
+ * Unschedule a callback.
*
- * \param t interval before the callback should be made / cs
* \param callback callback function
* \param p user parameter, passed to callback function
*
- * The callback function will be called as soon as possible after t cs have
- * passed.
+ * All scheduled callbacks matching both callback and p are removed.
*/
-void schedule(int t, void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
+{
+ struct sched_entry *entry, *next;
+
+ for (entry = &sched_queue; entry->next; entry = entry->next) {
+ if (entry->next->callback != callback || entry->next->p != p)
+ continue;
+ next = entry->next;
+ entry->next = entry->next->next;
+ free(next);
+ if (!entry->next)
+ break;
+ }
+
+ if (sched_queue.next) {
+ sched_active = true;
+ sched_time = sched_queue.next->time;
+ } else {
+ sched_active = false;
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in riscos/gui.h */
+nserror riscos_schedule(int t, void (*callback)(void *p), void *p)
{
struct sched_entry *entry;
struct sched_entry *queue;
os_t time;
+ nserror ret;
- schedule_remove(callback, p);
+ ret = schedule_remove(callback, p);
+ if ((t < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ t = t / 10; /* convert to centiseconds */
time = os_read_monotonic_time() + t;
@@ -91,44 +120,12 @@ void schedule(int t, void (*callback)(void *p), void *p)
sched_active = true;
sched_time = sched_queue.next->time;
-}
-
-/**
- * Unschedule a callback.
- *
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * All scheduled callbacks matching both callback and p are removed.
- */
-
-void schedule_remove(void (*callback)(void *p), void *p)
-{
- struct sched_entry *entry, *next;
-
- for (entry = &sched_queue; entry->next; entry = entry->next) {
- if (entry->next->callback != callback || entry->next->p != p)
- continue;
- next = entry->next;
- entry->next = entry->next->next;
- free(next);
- if (!entry->next)
- break;
- }
-
- if (sched_queue.next) {
- sched_active = true;
- sched_time = sched_queue.next->time;
- } else
- sched_active = false;
+ return NSERROR_OK;
}
-/**
- * Process events up to current time.
- */
-
+/* exported function documented in riscos/gui.h */
bool schedule_run(void)
{
struct sched_entry *entry;
@@ -144,8 +141,9 @@ bool schedule_run(void)
p = entry->p;
sched_queue.next = entry->next;
free(entry);
- /* The callback may call schedule() or schedule_remove(), so
- * leave the queue in a safe state. */
+ /* The callback may call riscos_schedule(), so leave
+ * the queue in a safe state.
+ */
callback(p);
}
diff --git a/utils/schedule.h b/utils/schedule.h
deleted file mode 100644
index b5fe386..0000000
--- a/utils/schedule.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011 Daniel Silverstone <dsilvers(a)netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/** \file
- * Job scheduler (interface).
- */
-
-#ifndef _NETSURF_UTILS_SCHEDULE_H_
-#define _NETSURF_UTILS_SCHEDULE_H_
-
-/* In platform specific schedule.c. */
-typedef void (*schedule_callback_fn)(void *p);
-
-void schedule(int t, schedule_callback_fn callback, void *p);
-void schedule_remove(schedule_callback_fn callback, void *p);
-
-#endif
diff --git a/windows/download.c b/windows/download.c
index 8bdff3a..fe2a092 100644
--- a/windows/download.c
+++ b/windows/download.c
@@ -27,14 +27,15 @@
#include "content/fetch.h"
#include "desktop/gui.h"
#include "desktop/download.h"
-#include "utils/schedule.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utils.h"
+
#include "windows/download.h"
#include "windows/gui.h"
#include "windows/resourceid.h"
+#include "windows/schedule.h"
static bool downloading = false;
static struct gui_download_window *download1;
@@ -182,7 +183,7 @@ void nsws_download_update_label(void *p)
{
struct gui_download_window *w = p;
if (w->hwnd == NULL) {
- schedule_remove(nsws_download_update_label, p);
+ win32_schedule(-1, nsws_download_update_label, p);
return;
}
HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_LABEL);
@@ -222,21 +223,23 @@ void nsws_download_update_label(void *p)
w->time_left = NULL;
}
SendMessage(sub, WM_SETTEXT, (WPARAM)0, (LPARAM)label);
- if (w->progress < 10000)
- schedule(50, nsws_download_update_label, p);
+ if (w->progress < 10000) {
+ win32_schedule(500, nsws_download_update_label, p);
+ }
}
void nsws_download_update_progress(void *p)
{
struct gui_download_window *w = p;
if (w->hwnd == NULL) {
- schedule_remove(nsws_download_update_progress, p);
+ win32_schedule(-1, nsws_download_update_progress, p);
return;
}
HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_PROGRESS);
SendMessage(sub, PBM_SETPOS, (WPARAM)(w->progress / 100), 0);
- if (w->progress < 10000)
- schedule(50, nsws_download_update_progress, p);
+ if (w->progress < 10000) {
+ win32_schedule(500, nsws_download_update_progress, p);
+ }
}
void nsws_download_clear_data(struct gui_download_window *w)
@@ -255,8 +258,8 @@ void nsws_download_clear_data(struct gui_download_window *w)
free(w->total_size);
if (w->file != NULL)
fclose(w->file);
- schedule_remove(nsws_download_update_progress, (void *)w);
- schedule_remove(nsws_download_update_label, (void *)w);
+ win32_schedule(-1, nsws_download_update_progress, (void *)w);
+ win32_schedule(-1, nsws_download_update_label, (void *)w);
}
diff --git a/windows/gui.c b/windows/gui.c
index 92ff400..8270c13 100644
--- a/windows/gui.c
+++ b/windows/gui.c
@@ -78,7 +78,7 @@ void gui_window_set_scroll(struct gui_window *w, int sx, int sy);
static bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
-static void gui_poll(bool active)
+static void win32_poll(bool active)
{
MSG Msg; /* message from system */
BOOL bRet; /* message fetch result */
@@ -1888,7 +1888,8 @@ struct gui_fetch_table *win32_fetch_table = &fetch_table;
static struct gui_browser_table browser_table = {
- .poll = gui_poll,
+ .poll = win32_poll,
+ .schedule = win32_schedule,
};
struct gui_browser_table *win32_browser_table = &browser_table;
diff --git a/windows/schedule.c b/windows/schedule.c
index 3181c55..f819918 100644
--- a/windows/schedule.c
+++ b/windows/schedule.c
@@ -19,12 +19,17 @@
#include <sys/time.h>
#include <time.h>
-#include "utils/schedule.h"
#include "windows/schedule.h"
#include "utils/log.h"
#include "utils/utils.h"
+#ifdef DEBUG_SCHEDULER
+#define SRLOG(x) LOG(x)
+#else
+#define SRLOG(x)
+#endif
+
/* linked list of scheduled callbacks */
static struct nscallback *schedule_list = NULL;
@@ -41,39 +46,6 @@ struct nscallback
/**
- * Schedule a callback.
- *
- * \param tival interval before the callback should be made / cs
- * \param callback callback function
- * \param p user parameter, passed to callback function
- *
- * The callback function will be called as soon as possible after t cs have
- * passed.
- */
-void schedule(int cs_ival, void (*callback)(void *p), void *p)
-{
- struct nscallback *nscb;
- struct timeval tv;
-
- tv.tv_sec = cs_ival / 100; /* cs to seconds */
- tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */
-
- nscb = calloc(1, sizeof(struct nscallback));
-
- LOG(("adding callback %p for %p(%p) at %d cs", nscb, callback, p, cs_ival));
-
- gettimeofday(&nscb->tv, NULL);
- timeradd(&nscb->tv, &tv, &nscb->tv);
-
- nscb->callback = callback;
- nscb->p = p;
-
- /* add to list front */
- nscb->next = schedule_list;
- schedule_list = nscb;
-}
-
-/**
* Unschedule a callback.
*
* \param callback callback function
@@ -82,16 +54,18 @@ void schedule(int cs_ival, void (*callback)(void *p), void *p)
* All scheduled callbacks matching both callback and p are removed.
*/
-void schedule_remove(void (*callback)(void *p), void *p)
+static nserror schedule_remove(void (*callback)(void *p), void *p)
{
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
- if (schedule_list == NULL)
- return;
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_OK;
+ }
- LOG(("removing %p, %p", callback, p));
+ SRLOG(("removing %p, %p", callback, p));
cur_nscb = schedule_list;
prev_nscb = NULL;
@@ -101,7 +75,7 @@ void schedule_remove(void (*callback)(void *p), void *p)
(cur_nscb->p == p)) {
/* item to remove */
- LOG(("callback entry %p removing %p(%p)",
+ SRLOG(("callback entry %p removing %p(%p)",
cur_nscb, cur_nscb->callback, cur_nscb->p));
/* remove callback */
@@ -120,8 +94,44 @@ void schedule_remove(void (*callback)(void *p), void *p)
cur_nscb = prev_nscb->next;
}
}
+ return NSERROR_OK;
}
+/* exported interface documented in windows/schedule.h */
+nserror win32_schedule(int ival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+ nserror ret;
+
+ ret = schedule_remove(callback, p);
+ if ((ival < 0) || (ret != NSERROR_OK)) {
+ return ret;
+ }
+
+ tv.tv_sec = ival / 1000; /* miliseconds to seconds */
+ tv.tv_usec = (cs_ival % 1000) * 1000; /* remainder to microseconds */
+
+ nscb = calloc(1, sizeof(struct nscallback));
+ if (nscb == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ SRLOG(("adding callback %p for %p(%p) at %d cs",
+ nscb, callback, p, ival));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+
+ return NSERROR_OK;
+}
/* exported interface documented in schedule.h */
int
@@ -157,7 +167,7 @@ schedule_run(void)
prev_nscb->next = unlnk_nscb->next;
}
- LOG(("callback entry %p running %p(%p)",
+ SRLOG(("callback entry %p running %p(%p)",
unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
/* call callback */
unlnk_nscb->callback(unlnk_nscb->p);
@@ -190,9 +200,9 @@ schedule_run(void)
/* make returned time relative to now */
timersub(&nexttime, &tv, &rettime);
-#if defined(DEBUG_SCHEDULER)
- LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
-#endif
+ SRLOG(("returning time to next event as %ldms",
+ (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
+
/* return next event time in milliseconds (24days max wait) */
return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
}
diff --git a/windows/schedule.h b/windows/schedule.h
index e6a5d10..6d47b2d 100644
--- a/windows/schedule.h
+++ b/windows/schedule.h
@@ -16,8 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef FRAMEBUFFER_SCHEDULE_H
-#define FRAMEBUFFER_SCHEDULE_H
+#ifndef WINDOWS_SCHEDULE_H
+#define WINDOWS_SCHEDULE_H
+
+/**
+ * Schedule a callback.
+ *
+ * \param ival interval before the callback should be made in ms
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t ms have
+ * passed.
+ */
+nserror win32_schedule(int ival, void (*callback)(void *p), void *p);
/**
* Process scheduled callbacks up to current time.
--
NetSurf Browser
8 years, 11 months