Blame SOURCES/047-more-bundle-fixes.patch

60de42
From a30e9fa6c209ad310bddc079c4afd14fb4876f4f Mon Sep 17 00:00:00 2001
60de42
From: Ken Gaillot <kgaillot@redhat.com>
60de42
Date: Mon, 3 Apr 2017 15:33:24 -0500
60de42
Subject: [PATCH 1/8] Fix: libpe_status: avoid memory leak when bundle resource
60de42
 fails to unpack
60de42
60de42
---
60de42
 lib/pengine/container.c | 31 ++++++++++++++++---------------
60de42
 1 file changed, 16 insertions(+), 15 deletions(-)
60de42
60de42
diff --git a/lib/pengine/container.c b/lib/pengine/container.c
60de42
index 09113ae..cae62f0 100644
60de42
--- a/lib/pengine/container.c
60de42
+++ b/lib/pengine/container.c
60de42
@@ -599,10 +599,22 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set)
60de42
         GListPtr childIter = NULL;
60de42
         resource_t *new_rsc = NULL;
60de42
         container_mount_t *mount = NULL;
60de42
-        container_port_t *port = calloc(1, sizeof(container_port_t));
60de42
+        container_port_t *port = NULL;
60de42
 
60de42
         int offset = 0, max = 1024;
60de42
-        char *buffer = calloc(1, max+1);
60de42
+        char *buffer = NULL;
60de42
+
60de42
+        if (common_unpack(xml_resource, &new_rsc, rsc, data_set) == FALSE) {
60de42
+            pe_err("Failed unpacking resource %s", ID(rsc->xml));
60de42
+            if (new_rsc != NULL && new_rsc->fns != NULL) {
60de42
+                new_rsc->fns->free(new_rsc);
60de42
+            }
60de42
+            return FALSE;
60de42
+        }
60de42
+
60de42
+        container_data->child = new_rsc;
60de42
+        container_data->child->orig_xml = xml_obj; // Also the trigger for common_free()
60de42
+                                                   // to free xml_resource as container_data->child->xml
60de42
 
60de42
         mount = calloc(1, sizeof(container_mount_t));
60de42
         mount->source = strdup(DEFAULT_REMOTE_KEY_LOCATION);
60de42
@@ -618,27 +630,16 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set)
60de42
         mount->flags = 1;
60de42
         container_data->mounts = g_list_append(container_data->mounts, mount);
60de42
 
60de42
+        port = calloc(1, sizeof(container_port_t));
60de42
         if(container_data->control_port) {
60de42
             port->source = strdup(container_data->control_port);
60de42
         } else {
60de42
             port->source = crm_itoa(DEFAULT_REMOTE_PORT);
60de42
         }
60de42
-
60de42
         port->target = strdup(port->source);
60de42
         container_data->ports = g_list_append(container_data->ports, port);
60de42
 
60de42
-        if (common_unpack(xml_resource, &new_rsc, rsc, data_set) == FALSE) {
60de42
-            pe_err("Failed unpacking resource %s", crm_element_value(rsc->xml, XML_ATTR_ID));
60de42
-            if (new_rsc != NULL && new_rsc->fns != NULL) {
60de42
-                new_rsc->fns->free(new_rsc);
60de42
-            }
60de42
-            return FALSE;
60de42
-        }
60de42
-
60de42
-        container_data->child = new_rsc;
60de42
-        container_data->child->orig_xml = xml_obj; // Also the trigger for common_free()
60de42
-                                                   // to free xml_resource as container_data->child->xml
60de42
-
60de42
+        buffer = calloc(1, max+1);
60de42
         for(childIter = container_data->child->children; childIter != NULL; childIter = childIter->next) {
60de42
             container_grouping_t *tuple = calloc(1, sizeof(container_grouping_t));
60de42
             tuple->child = childIter->data;
60de42
-- 
60de42
1.8.3.1
60de42
60de42
60de42
From 21ed491adc82fd04b39bc2d6035527b1514e99f4 Mon Sep 17 00:00:00 2001
60de42
From: Ken Gaillot <kgaillot@redhat.com>
60de42
Date: Mon, 3 Apr 2017 15:40:56 -0500
60de42
Subject: [PATCH 2/8] Refactor: libpe_status: remove dead code
60de42
60de42
died in 09f233dd
60de42
---
60de42
 lib/pengine/unpack.c | 5 -----
60de42
 1 file changed, 5 deletions(-)
60de42
60de42
diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c
60de42
index ef51cd5..6aa51dd 100644
60de42
--- a/lib/pengine/unpack.c
60de42
+++ b/lib/pengine/unpack.c
60de42
@@ -637,7 +637,6 @@ gboolean
60de42
 unpack_remote_nodes(xmlNode * xml_resources, pe_working_set_t * data_set)
60de42
 {
60de42
     xmlNode *xml_obj = NULL;
60de42
-    GHashTable *rsc_name_check = NULL;
60de42
 
60de42
     /* generate remote nodes from resource config before unpacking resources */
60de42
     for (xml_obj = __xml_first_child(xml_resources); xml_obj != NULL; xml_obj = __xml_next_element(xml_obj)) {
60de42
@@ -691,10 +690,6 @@ unpack_remote_nodes(xmlNode * xml_resources, pe_working_set_t * data_set)
60de42
             }
60de42
         }
60de42
     }
60de42
-    if (rsc_name_check) {
60de42
-        g_hash_table_destroy(rsc_name_check);
60de42
-    }
60de42
-
60de42
     return TRUE;
60de42
 }
60de42
 
60de42
-- 
60de42
1.8.3.1
60de42
60de42
60de42
From 3093687bc307b0a554ba5837d28ca1fc11f22935 Mon Sep 17 00:00:00 2001
60de42
From: Ken Gaillot <kgaillot@redhat.com>
60de42
Date: Mon, 3 Apr 2017 15:43:55 -0500
60de42
Subject: [PATCH 3/8] Low: pengine: ensure other container in constraint has
60de42
 Docker info
60de42
60de42
Not really necessary, but makes static analysis happy
60de42
---
60de42
 pengine/container.c | 7 +++++--
60de42
 1 file changed, 5 insertions(+), 2 deletions(-)
60de42
60de42
diff --git a/pengine/container.c b/pengine/container.c
60de42
index 1623861..3da19aa 100644
60de42
--- a/pengine/container.c
60de42
+++ b/pengine/container.c
60de42
@@ -313,13 +313,16 @@ container_create_probe(resource_t * rsc, node_t * node, action_t * complete,
60de42
                  * Partly this is to ensure that replicas_per_host is
60de42
                  * observed, but also to ensure that the containers
60de42
                  * don't fail to start because the necessary port
60de42
-                 * mappings (which wont include an IP for uniqueness)
60de42
+                 * mappings (which won't include an IP for uniqueness)
60de42
                  * are already taken
60de42
                  */
60de42
 
60de42
                 for (GListPtr tIter = container_data->tuples; tIter != NULL && container_data->replicas_per_host == 1; tIter = tIter->next) {
60de42
                     container_grouping_t *other = (container_grouping_t *)tIter->data;
60de42
-                    if(other != tuple) {
60de42
+
60de42
+                    if ((other != tuple) && (other != NULL)
60de42
+                        && (other->docker != NULL)) {
60de42
+
60de42
                         custom_action_order(tuple->docker, generate_op_key(tuple->docker->id, RSC_STATUS, 0), NULL,
60de42
                                             other->docker, generate_op_key(other->docker->id, RSC_START, 0), NULL,
60de42
                                             pe_order_optional, data_set);
60de42
-- 
60de42
1.8.3.1
60de42
60de42
60de42
From 50399650dbd6425218638cef32c77f02a0807472 Mon Sep 17 00:00:00 2001
60de42
From: Ken Gaillot <kgaillot@redhat.com>
60de42
Date: Mon, 3 Apr 2017 15:46:01 -0500
60de42
Subject: [PATCH 4/8] Low: libpe_status: ensure resource is not NULL
60de42
60de42
not really necessary, but makes static analysis happy
60de42
---
60de42
 lib/pengine/container.c | 1 +
60de42
 1 file changed, 1 insertion(+)
60de42
60de42
diff --git a/lib/pengine/container.c b/lib/pengine/container.c
60de42
index cae62f0..2a60e4c 100644
60de42
--- a/lib/pengine/container.c
60de42
+++ b/lib/pengine/container.c
60de42
@@ -440,6 +440,7 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set)
60de42
     xmlNode *xml_resource = NULL;
60de42
     container_variant_data_t *container_data = NULL;
60de42
 
60de42
+    CRM_ASSERT(rsc != NULL);
60de42
     pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
60de42
 
60de42
     container_data = calloc(1, sizeof(container_variant_data_t));
60de42
-- 
60de42
1.8.3.1
60de42
60de42
60de42
From a755fb0a64873c16aac9924d95b0c2bdb13f5065 Mon Sep 17 00:00:00 2001
60de42
From: Ken Gaillot <kgaillot@redhat.com>
60de42
Date: Mon, 3 Apr 2017 16:52:54 -0500
60de42
Subject: [PATCH 5/8] Low: libpe_status: improve container print functions
60de42
60de42
---
60de42
 lib/pengine/container.c | 92 ++++++++++++++++++++++++++++++-------------------
60de42
 1 file changed, 56 insertions(+), 36 deletions(-)
60de42
60de42
diff --git a/lib/pengine/container.c b/lib/pengine/container.c
60de42
index 2a60e4c..2af2558 100644
60de42
--- a/lib/pengine/container.c
60de42
+++ b/lib/pengine/container.c
60de42
@@ -716,6 +716,21 @@ find_container_child(const char *stem, resource_t * rsc, node_t *node)
60de42
 }
60de42
 
60de42
 static void
60de42
+print_rsc_in_list(resource_t *rsc, const char *pre_text, long options,
60de42
+                  void *print_data)
60de42
+{
60de42
+    if (rsc != NULL) {
60de42
+        if (options & pe_print_html) {
60de42
+            status_print("
  • ");
  • 60de42
    +        }
    60de42
    +        rsc->fns->print(rsc, pre_text, options, print_data);
    60de42
    +        if (options & pe_print_html) {
    60de42
    +            status_print("\n");
    60de42
    +        }
    60de42
    +    }
    60de42
    +}
    60de42
    +
    60de42
    +static void
    60de42
     container_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data)
    60de42
     {
    60de42
         container_variant_data_t *container_data = NULL;
    60de42
    @@ -725,39 +740,31 @@ container_print_xml(resource_t * rsc, const char *pre_text, long options, void *
    60de42
         if (pre_text == NULL) {
    60de42
             pre_text = "";
    60de42
         }
    60de42
    -    child_text = crm_concat(pre_text, "   ", ' ');
    60de42
    +    child_text = crm_concat(pre_text, "       ", ' ');
    60de42
     
    60de42
    -    status_print("%s
    60de42
    +    get_container_variant_data(container_data, rsc);
    60de42
    +
    60de42
    +    status_print("%s
    60de42
         status_print("id=\"%s\" ", rsc->id);
    60de42
    +    status_print("type=\"docker\" ");
    60de42
    +    status_print("image=\"%s\" ", container_data->image);
    60de42
    +    status_print("unique=\"%s\" ", is_set(rsc->flags, pe_rsc_unique)? "true" : "false");
    60de42
         status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false");
    60de42
         status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false");
    60de42
         status_print(">\n");
    60de42
     
    60de42
    -    get_container_variant_data(container_data, rsc);
    60de42
    -
    60de42
    -    status_print("%sDocker container: %s [%s]%s%s",
    60de42
    -                 pre_text, rsc->id, container_data->image,
    60de42
    -                 is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "",
    60de42
    -                 is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)");
    60de42
    -
    60de42
         for (GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) {
    60de42
             container_grouping_t *tuple = (container_grouping_t *)gIter->data;
    60de42
     
    60de42
             CRM_ASSERT(tuple);
    60de42
    -        if(tuple->ip) {
    60de42
    -            tuple->ip->fns->print(tuple->ip, child_text, options, print_data);
    60de42
    -        }
    60de42
    -        if(tuple->child) {
    60de42
    -            tuple->child->fns->print(tuple->child, child_text, options, print_data);
    60de42
    -        }
    60de42
    -        if(tuple->docker) {
    60de42
    -            tuple->docker->fns->print(tuple->docker, child_text, options, print_data);
    60de42
    -        }
    60de42
    -        if(tuple->remote) {
    60de42
    -            tuple->remote->fns->print(tuple->remote, child_text, options, print_data);
    60de42
    -        }
    60de42
    -    }
    60de42
    -    status_print("%s</container>\n", pre_text);
    60de42
    +        status_print("%s    <replica id=\"%d\">\n", pre_text, tuple->offset);
    60de42
    +        print_rsc_in_list(tuple->ip, child_text, options, print_data);
    60de42
    +        print_rsc_in_list(tuple->child, child_text, options, print_data);
    60de42
    +        print_rsc_in_list(tuple->docker, child_text, options, print_data);
    60de42
    +        print_rsc_in_list(tuple->remote, child_text, options, print_data);
    60de42
    +        status_print("%s    </replica>\n", pre_text);
    60de42
    +    }
    60de42
    +    status_print("%s</bundle>\n", pre_text);
    60de42
         free(child_text);
    60de42
     }
    60de42
     
    60de42
    @@ -809,37 +816,50 @@ container_print(resource_t * rsc, const char *pre_text, long options, void *prin
    60de42
             pre_text = " ";
    60de42
         }
    60de42
     
    60de42
    -    child_text = crm_strdup_printf("     %s", pre_text);
    60de42
         status_print("%sDocker container%s: %s [%s]%s%s\n",
    60de42
                      pre_text, container_data->replicas>1?" set":"", rsc->id, container_data->image,
    60de42
                      is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "",
    60de42
                      is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)");
    60de42
    +    if (options & pe_print_html) {
    60de42
    +        status_print("
    \n
      \n");
    60de42
    +    }
    60de42
    +
    60de42
     
    60de42
         for (GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) {
    60de42
             container_grouping_t *tuple = (container_grouping_t *)gIter->data;
    60de42
     
    60de42
             CRM_ASSERT(tuple);
    60de42
    +        if (options & pe_print_html) {
    60de42
    +            status_print("
  • ");
  • 60de42
    +        }
    60de42
    +
    60de42
             if(is_set(options, pe_print_clone_details)) {
    60de42
    +            child_text = crm_strdup_printf("     %s", pre_text);
    60de42
                 if(g_list_length(container_data->tuples) > 1) {
    60de42
                     status_print("  %sReplica[%d]\n", pre_text, tuple->offset);
    60de42
                 }
    60de42
    -
    60de42
    -            if(tuple->ip) {
    60de42
    -                tuple->ip->fns->print(tuple->ip, child_text, options, print_data);
    60de42
    -            }
    60de42
    -            if(tuple->docker) {
    60de42
    -                tuple->docker->fns->print(tuple->docker, child_text, options, print_data);
    60de42
    -            }
    60de42
    -            if(tuple->remote) {
    60de42
    -                tuple->remote->fns->print(tuple->remote, child_text, options, print_data);
    60de42
    +            if (options & pe_print_html) {
    60de42
    +                status_print("
    \n
      \n");
    60de42
                 }
    60de42
    -            if(tuple->child) {
    60de42
    -                tuple->child->fns->print(tuple->child, child_text, options, print_data);
    60de42
    +            print_rsc_in_list(tuple->ip, child_text, options, print_data);
    60de42
    +            print_rsc_in_list(tuple->docker, child_text, options, print_data);
    60de42
    +            print_rsc_in_list(tuple->remote, child_text, options, print_data);
    60de42
    +            print_rsc_in_list(tuple->child, child_text, options, print_data);
    60de42
    +            if (options & pe_print_html) {
    60de42
    +                status_print("\n");
    60de42
                 }
    60de42
             } else {
    60de42
    -            char *child_text = crm_strdup_printf("%s  ", pre_text);
    60de42
    +            child_text = crm_strdup_printf("%s  ", pre_text);
    60de42
                 tuple_print(tuple, child_text, options, print_data);
    60de42
             }
    60de42
    +        free(child_text);
    60de42
    +
    60de42
    +        if (options & pe_print_html) {
    60de42
    +            status_print("\n");
    60de42
    +        }
    60de42
    +    }
    60de42
    +    if (options & pe_print_html) {
    60de42
    +        status_print("\n");
    60de42
         }
    60de42
     }
    60de42
     
    60de42
    -- 
    60de42
    1.8.3.1
    60de42
    60de42
    60de42
    From 1302b775b8bc4913b894081707f9ad386402d25d Mon Sep 17 00:00:00 2001
    60de42
    From: Ken Gaillot <kgaillot@redhat.com>
    60de42
    Date: Mon, 3 Apr 2017 17:06:06 -0500
    60de42
    Subject: [PATCH 6/8] Low: tools: update crm_mon RNG schema for bundles
    60de42
    60de42
    ---
    60de42
     xml/crm_mon.rng | 26 ++++++++++++++++++++++++++
    60de42
     1 file changed, 26 insertions(+)
    60de42
    60de42
    diff --git a/xml/crm_mon.rng b/xml/crm_mon.rng
    60de42
    index 653c15e..731c118 100644
    60de42
    --- a/xml/crm_mon.rng
    60de42
    +++ b/xml/crm_mon.rng
    60de42
    @@ -241,6 +241,9 @@
    60de42
                 <zeroOrMore>
    60de42
                     <ref name="element-clone" />
    60de42
                 </zeroOrMore>
    60de42
    +            <zeroOrMore>
    60de42
    +                <ref name="element-bundle" />
    60de42
    +            </zeroOrMore>
    60de42
             </interleave>
    60de42
         </define>
    60de42
     
    60de42
    @@ -298,4 +301,27 @@
    60de42
             </element>
    60de42
         </define>
    60de42
     
    60de42
    +    <define name="element-bundle">
    60de42
    +        <element name="bundle">
    60de42
    +            <attribute name="id"> <text/> </attribute>
    60de42
    +            <attribute name="type">
    60de42
    +                <choice>
    60de42
    +                    <value>docker</value>
    60de42
    +                </choice>
    60de42
    +            </attribute>
    60de42
    +            <attribute name="image"> <text/> </attribute>
    60de42
    +            <attribute name="unique"> <data type="boolean" /> </attribute>
    60de42
    +            <attribute name="managed"> <data type="boolean" /> </attribute>
    60de42
    +            <attribute name="failed"> <data type="boolean" /> </attribute>
    60de42
    +            <zeroOrMore>
    60de42
    +                <element name="replica">
    60de42
    +                    <attribute name="id"> <data type="int" /> </attribute>
    60de42
    +                    <zeroOrMore>
    60de42
    +                        <ref name="element-resource" />
    60de42
    +                    </zeroOrMore>
    60de42
    +                </element>
    60de42
    +            </zeroOrMore>
    60de42
    +        </element>
    60de42
    +    </define>
    60de42
    +
    60de42
     </grammar>
    60de42
    -- 
    60de42
    1.8.3.1
    60de42
    60de42
    60de42
    From 3b5f0f58bae3b2764222eede878da5801336b2c9 Mon Sep 17 00:00:00 2001
    60de42
    From: Ken Gaillot <kgaillot@redhat.com>
    60de42
    Date: Mon, 3 Apr 2017 18:21:19 -0500
    60de42
    Subject: [PATCH 7/8] Fix: libpe_status: run-command should apply even without
    60de42
     a primitive
    60de42
    60de42
    ---
    60de42
     lib/pengine/container.c | 4 ++++
    60de42
     1 file changed, 4 insertions(+)
    60de42
    60de42
    diff --git a/lib/pengine/container.c b/lib/pengine/container.c
    60de42
    index 2af2558..9c59be6 100644
    60de42
    --- a/lib/pengine/container.c
    60de42
    +++ b/lib/pengine/container.c
    60de42
    @@ -301,6 +301,10 @@ create_docker_resource(
    60de42
              *     create_nvp(xml_obj, "monitor_cmd", "/usr/libexec/pacemaker/lrmd_internal_ctl -c poke");
    60de42
              */
    60de42
             } else {
    60de42
    +            if(data->docker_run_command) {
    60de42
    +                create_nvp(xml_obj, "run_cmd", data->docker_run_command);
    60de42
    +            }
    60de42
    +
    60de42
                 /* TODO: Allow users to specify their own?
    60de42
                  *
    60de42
                  * We don't know what's in the container, so we just want
    60de42
    -- 
    60de42
    1.8.3.1
    60de42
    60de42
    60de42
    From 75b29dee7fa4adf0141f8932b060392a238adbc7 Mon Sep 17 00:00:00 2001
    60de42
    From: Ken Gaillot <kgaillot@redhat.com>
    60de42
    Date: Mon, 3 Apr 2017 17:44:03 -0500
    60de42
    Subject: [PATCH 8/8] Fix: libpe_status: implement active check for bundles
    60de42
    60de42
    ---
    60de42
     lib/pengine/container.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-
    60de42
     1 file changed, 49 insertions(+), 1 deletion(-)
    60de42
    60de42
    diff --git a/lib/pengine/container.c b/lib/pengine/container.c
    60de42
    index 9c59be6..b93d98f 100644
    60de42
    --- a/lib/pengine/container.c
    60de42
    +++ b/lib/pengine/container.c
    60de42
    @@ -683,10 +683,58 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set)
    60de42
         return TRUE;
    60de42
     }
    60de42
     
    60de42
    +static int
    60de42
    +tuple_rsc_active(resource_t *rsc, gboolean all)
    60de42
    +{
    60de42
    +    if (rsc) {
    60de42
    +        gboolean child_active = rsc->fns->active(rsc, all);
    60de42
    +
    60de42
    +        if (child_active && !all) {
    60de42
    +            return TRUE;
    60de42
    +        } else if (!child_active && all) {
    60de42
    +            return FALSE;
    60de42
    +        }
    60de42
    +    }
    60de42
    +    return -1;
    60de42
    +}
    60de42
    +
    60de42
     gboolean
    60de42
     container_active(resource_t * rsc, gboolean all)
    60de42
     {
    60de42
    -    return TRUE;
    60de42
    +    container_variant_data_t *container_data = NULL;
    60de42
    +    GListPtr iter = NULL;
    60de42
    +
    60de42
    +    get_container_variant_data(container_data, rsc);
    60de42
    +    for (iter = container_data->tuples; iter != NULL; iter = iter->next) {
    60de42
    +        container_grouping_t *tuple = (container_grouping_t *)(iter->data);
    60de42
    +        int rsc_active;
    60de42
    +
    60de42
    +        rsc_active = tuple_rsc_active(tuple->ip, all);
    60de42
    +        if (rsc_active >= 0) {
    60de42
    +            return (gboolean) rsc_active;
    60de42
    +        }
    60de42
    +
    60de42
    +        rsc_active = tuple_rsc_active(tuple->child, all);
    60de42
    +        if (rsc_active >= 0) {
    60de42
    +            return (gboolean) rsc_active;
    60de42
    +        }
    60de42
    +
    60de42
    +        rsc_active = tuple_rsc_active(tuple->docker, all);
    60de42
    +        if (rsc_active >= 0) {
    60de42
    +            return (gboolean) rsc_active;
    60de42
    +        }
    60de42
    +
    60de42
    +        rsc_active = tuple_rsc_active(tuple->remote, all);
    60de42
    +        if (rsc_active >= 0) {
    60de42
    +            return (gboolean) rsc_active;
    60de42
    +        }
    60de42
    +    }
    60de42
    +
    60de42
    +    /* If "all" is TRUE, we've already checked that no resources were inactive,
    60de42
    +     * so return TRUE; if "all" is FALSE, we didn't find any active resources,
    60de42
    +     * so return FALSE.
    60de42
    +     */
    60de42
    +    return all;
    60de42
     }
    60de42
     
    60de42
     resource_t *
    60de42
    -- 
    60de42
    1.8.3.1
    60de42