<commit_before>/* GStreamer
 * Copyright (C) 2012 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <libsoup/soup-server.h>
#include <libsoup/soup-message.h>
#include <libsoup/soup-socket.h>
#include <libsoup/soup-address.h>

#include "snra-resource.h"
#include "snra-http-resource.h"

#if 0
#define DEBUG_PRINT(...) g_print (__VA_ARGS__);
#else
#define DEBUG_PRINT(...)
#endif

G_DEFINE_TYPE (SnraHttpResource, snra_http_resource, G_TYPE_OBJECT);

enum
{
  PROP_0,
  PROP_SOURCE_PATH,
  PROP_LAST
};

static gint resources_open = 0;

static void snra_http_resource_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void snra_http_resource_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

typedef struct _SnraTransfer
{
  SnraHttpResource *resource;
} SnraTransfer;

static gboolean
snra_http_resource_open (SnraHttpResource * resource)
{
  if (resource->data == NULL) {
    GError *error = NULL;

    resources_open++;
    DEBUG_PRINT ("Opening resource %s. %d now open\n", resource->source_path,
        resources_open);
    resource->data = g_mapped_file_new (resource->source_path, FALSE, &error);
    if (resource->data == NULL) {
      g_message ("Failed to open resource %s: %s", resource->source_path,
          error->message);
      g_error_free (error);
      return FALSE;
    }
  }
  resource->use_count++;
  return TRUE;
}

static void
snra_http_resource_close (SnraHttpResource * resource)
{
  if (resource->use_count) {
    resource->use_count--;
    if (resource->use_count == 0) {
      resources_open--;
      g_print ("Releasing resource %s. %d now open\n", resource->source_path,
          resources_open);
#if GLIB_CHECK_VERSION(2,22,0)
      g_mapped_file_unref (resource->data);
#else
      g_mapped_file_free (resource->data);
#endif
      resource->data = NULL;
    }
  }
}

static void
resource_wrote_body (G_GNUC_UNUSED SoupMessage * msg, SnraTransfer * transfer)
{
  g_print ("Got wrote-body for %s. Use count now %d\n",
      transfer->resource->source_path, transfer->resource->use_count);
}

static void
resource_finished (G_GNUC_UNUSED SoupMessage * msg, SnraTransfer * transfer)
{
  g_print ("Completed transfer of %s. Use count now %d\n",
      transfer->resource->source_path, transfer->resource->use_count - 1);

  /* Close the resource, destroy the transfer */
  snra_http_resource_close (transfer->resource);

#if 0
  g_print ("close resource %s (%p) use count now %d msg %p\n",
      transfer->resource->source_path, transfer->resource,
      transfer->resource->use_count, msg);
#endif

  g_object_unref (transfer->resource);
  g_free (transfer);
}

void
snra_http_resource_new_transfer (SnraHttpResource * resource, SoupMessage * msg)
{
  /* Create a new transfer structure, and pass the contents of our
   * resource to it */
  SnraTransfer *transfer;

  if (!snra_http_resource_open (resource)) {
    soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
    return;
  }

#if 0
  g_print ("open resource %s (%p) use count now %d msg %p\n",
      resource->source_path, resource, resource->use_count, msg);
#endif

  transfer = g_new0 (SnraTransfer, 1);
  transfer->resource = g_object_ref (resource);

  {
    const gsize len = g_mapped_file_get_length (transfer->resource->data);
    gchar *chunk = g_mapped_file_get_contents (transfer->resource->data);

    g_signal_connect (msg, "finished", G_CALLBACK (resource_finished),
        transfer);
    g_signal_connect (msg, "wrote-body", G_CALLBACK (resource_wrote_body),
        transfer);

    soup_message_set_status (msg, SOUP_STATUS_OK);
    //soup_message_headers_set_encoding (msg->response_headers,
        //SOUP_ENCODING_CONTENT_LENGTH);
    soup_message_set_response (msg,
        snra_resource_get_mime_type (resource->source_path),
        SOUP_MEMORY_TEMPORARY, chunk, len);
  }
}

static void
snra_http_resource_init (G_GNUC_UNUSED SnraHttpResource * resource)
{
}

static void
snra_http_resource_class_init (SnraHttpResourceClass * resource_class)
{
  GObjectClass *gobject_class = (GObjectClass *) (resource_class);

  gobject_class->set_property = snra_http_resource_set_property;
  gobject_class->get_property = snra_http_resource_get_property;

  g_object_class_install_property (gobject_class, PROP_SOURCE_PATH,
      g_param_spec_string ("source-path", "Source Path",
          "Source file path resource", NULL, G_PARAM_READWRITE));
}

static void<commit_msg>Use buffer_new_with_owner to avoid copying mmap data<commit_after>/* GStreamer
 * Copyright (C) 2012 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <libsoup/soup-server.h>
#include <libsoup/soup-message.h>
#include <libsoup/soup-socket.h>
#include <libsoup/soup-address.h>

#include "snra-resource.h"
#include "snra-http-resource.h"

#if 0
#define DEBUG_PRINT(...) g_print (__VA_ARGS__);
#else
#define DEBUG_PRINT(...)
#endif

G_DEFINE_TYPE (SnraHttpResource, snra_http_resource, G_TYPE_OBJECT);

enum
{
  PROP_0,
  PROP_SOURCE_PATH,
  PROP_LAST
};

static gint resources_open = 0;

static void snra_http_resource_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void snra_http_resource_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

typedef struct _SnraTransfer
{
  SnraHttpResource *resource;
} SnraTransfer;

static gboolean
snra_http_resource_open (SnraHttpResource * resource)
{
  if (resource->data == NULL) {
    GError *error = NULL;

    resources_open++;
    DEBUG_PRINT ("Opening resource %s. %d now open\n", resource->source_path,
        resources_open);
    resource->data = g_mapped_file_new (resource->source_path, FALSE, &error);
    if (resource->data == NULL) {
      g_message ("Failed to open resource %s: %s", resource->source_path,
          error->message);
      g_error_free (error);
      return FALSE;
    }
  }
  g_object_ref (resource);
  resource->use_count++;
  return TRUE;
}

static void
snra_http_resource_close (SnraHttpResource * resource)
{
  if (resource->use_count) {
    resource->use_count--;
    if (resource->use_count == 0) {
      resources_open--;
      DEBUG_PRINT ("Releasing resource %s. %d now open\n", resource->source_path,
          resources_open);
#if GLIB_CHECK_VERSION(2,22,0)
      g_mapped_file_unref (resource->data);
#else
      g_mapped_file_free (resource->data);
#endif
      resource->data = NULL;
    }
  }

  DEBUG_PRINT ("closed resource %s (%p) use count now %d\n",
      resource->source_path, resource, resource->use_count);

  g_object_unref (resource);
}

static SnraTransfer *
snra_transfer_new (SnraHttpResource *resource)
{
  SnraTransfer *transfer;

  if (!snra_http_resource_open (resource))
    return NULL;

  transfer = g_new0 (SnraTransfer, 1);
  transfer->resource = g_object_ref (resource);

  DEBUG_PRINT ("Started transfer with resource %s (%p) use count now %d\n",
      resource->source_path, resource, resource->use_count);

  return transfer;
}

static void
snra_transfer_free (SnraTransfer *transfer)
{
  snra_http_resource_close (transfer->resource);

  DEBUG_PRINT ("Completed transfer of %s. Use count now %d\n",
      transfer->resource->source_path, transfer->resource->use_count);

  g_object_unref (transfer->resource);
  g_free (transfer);
}

void
snra_http_resource_new_transfer (SnraHttpResource * resource, SoupMessage * msg)
{
  /* Create a new transfer structure, and pass the contents of our
   * resource to it */
  SnraTransfer *transfer;
  SoupBuffer *buffer;

  transfer = snra_transfer_new (resource);

  if (!transfer) {
    soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
    return;
  }

  buffer = soup_buffer_new_with_owner (
      g_mapped_file_get_contents (transfer->resource->data),
      g_mapped_file_get_length (transfer->resource->data),
      transfer, (GDestroyNotify) snra_transfer_free);

  soup_message_set_status (msg, SOUP_STATUS_OK);
  soup_message_headers_replace (msg->response_headers,
      "Content-Type", snra_resource_get_mime_type (resource->source_path));
  soup_message_body_append_buffer (msg->response_body, buffer);
  soup_buffer_free (buffer);
}

static void
snra_http_resource_init (G_GNUC_UNUSED SnraHttpResource * resource)
{
}

static void
snra_http_resource_class_init (SnraHttpResourceClass * resource_class)
{
  GObjectClass *gobject_class = (GObjectClass *) (resource_class);

  gobject_class->set_property = snra_http_resource_set_property;
  gobject_class->get_property = snra_http_resource_get_property;

  g_object_class_install_property (gobject_class, PROP_SOURCE_PATH,
      g_param_spec_string ("source-path", "Source Path",
          "Source file path resource", NULL, G_PARAM_READWRITE));
}

static void
{'fraction_non_alphanumeric': 0.10349826053343641, 'fraction_numerical': 0.005894858909934287, 'mean_word_length': 4.395724713242961, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '340489', 'n_tokens_mistral': 3414, 'n_tokens_neox': 3319, 'n_words': 896}