Browse Source

Reworks vector for reuse in server.

Brian Aker 12 years ago
parent
commit
fe1a19b818

+ 3 - 3
libgearman/actions.cc

@@ -67,7 +67,7 @@ static gearman_return_t _client_pause_data(gearman_task_st *task)
     }
     assert_msg(task->result_ptr, "programmer error, result_ptr has not been allocated for task");
 
-    gearman_string_append(gearman_task_mutable_result(task)->string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
+    gearman_string_append(gearman_task_mutable_result(task)->mutable_string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
   }
 
   if (task->recv->command == GEARMAN_COMMAND_WORK_DATA)
@@ -134,7 +134,7 @@ static gearman_return_t _client_do_data(gearman_task_st *task)
       }
     }
 
-    gearman_string_append(gearman_task_mutable_result(task)->string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
+    gearman_string_append(gearman_task_mutable_result(task)->mutable_string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
   }
 
   return GEARMAN_SUCCESS;
@@ -153,7 +153,7 @@ static gearman_return_t _client_do_complete(gearman_task_st *task)
       }
     }
 
-    gearman_string_append(gearman_task_mutable_result(task)->string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
+    gearman_string_append(gearman_task_mutable_result(task)->mutable_string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
   }
 
   task->result_rc= GEARMAN_SUCCESS;

+ 8 - 7
libgearman/assert.hpp

@@ -54,13 +54,14 @@
 #  include <alloca.h>
 # endif
 
-#ifdef __cplusplus
-# include <cstdarg>
-# include <cstdio>
-#else
-# include <stdarg.h>
-# include <stdio.h>
-#endif // __cplusplus
+# ifdef __cplusplus
+#  include <cstdarg>
+#  include <cstdio>
+# else
+#  include <stdarg.h>
+#  include <stdio.h>
+# endif // __cplusplus
+
 # include <libgearman/backtrace.hpp>
 
 # define assert_msg(__expr, __mesg) \

+ 6 - 0
libgearman/include.am

@@ -72,6 +72,12 @@ libgearman_libgearmancore_la_CXXFLAGS= -DBUILDING_LIBGEARMAN
 libgearman_libgearmancore_la_LIBADD= @DL_LIB@
 libgearman_libgearmancore_la_LIBADD+= libhashkit/libhashkit.la
 
+noinst_LTLIBRARIES+= libgearman/libgearman-vector.la
+libgearman_libgearman_vector_la_CXXFLAGS= -DBUILDING_LIBGEARMAN
+libgearman_libgearman_vector_la_LIBADD= @DL_LIB@
+libgearman_libgearman_vector_la_SOURCES= libgearman/vector.cc
+libgearman_libgearman_vector_la_SOURCES+= libgearman/backtrace.cc
+
 libgearman_libgearman_la_LIBADD=
 libgearman_libgearman_la_SOURCES=
 libgearman_libgearman_la_CXXFLAGS=

+ 1 - 1
libgearman/job.cc

@@ -372,7 +372,7 @@ gearman_return_t gearman_job_send_complete_fin(gearman_job_st *job,
       return gearman_error(job->worker->universal, rc, "The reducer's complete() returned an error");
     }
 
-    gearman_vector_st *reduced_value= job->reducer->result.string();
+    const gearman_vector_st *reduced_value= job->reducer->result.string();
     if (reduced_value)
     {
       result= gearman_string_value(reduced_value);

+ 10 - 30
libgearman/result.cc

@@ -50,32 +50,14 @@ gearman_result_st::gearman_result_st() :
   _is_null(true),
   type(GEARMAN_RESULT_BOOLEAN)
 {
-  memset(&value.string, 0, sizeof(gearman_vector_st));
   value.boolean= false;
 }
 
 gearman_result_st::gearman_result_st(size_t initial_size) :
   _is_null(true),
-  type(GEARMAN_RESULT_BINARY)
+  type(GEARMAN_RESULT_BINARY),
+  value(initial_size)
 {
-  gearman_vector_st *allocated_str;
-  int limit= 2;
-  while (--limit)
-  {
-    if ((allocated_str= gearman_string_create(&value.string, initial_size)))
-    {
-      assert_msg(allocated_str == &value.string, "Programmer error, gearman_string_create() is not returning a correct value");
-      return;
-    }
-
-    assert_vmsg(allocated_str == NULL, "gearman_string_create() failed to allocation an intial string with %lu", (unsigned long)(initial_size));
-
-    // if we fail to allocate on the initial size, try to fail to "something"
-    initial_size= 0;
-  }
-
-  // We should never reach this point
-  assert_msg(allocated_str, "We should never exit with no allocation, most likely something in memory allocation is broken");
 }
 
 bool gearman_result_is_null(const gearman_result_st *self)
@@ -162,7 +144,7 @@ gearman_string_t gearman_result_take_string(gearman_result_st *self)
   {
     gearman_string_t ret_string= gearman_string_take_string(&self->value.string);
     self->type= GEARMAN_RESULT_BOOLEAN; // Set to default type
-    self->_is_null= false;
+    self->_is_null= true;
 
     return ret_string;
   }
@@ -183,21 +165,19 @@ gearman_return_t gearman_result_store_value(gearman_result_st *self, const void
     return GEARMAN_INVALID_ARGUMENT;
   }
 
-  if (self->type == GEARMAN_RESULT_BINARY)
+  self->value.string.clear();
+  if (value)
   {
-    gearman_string_reset(&self->value.string);
-  }
-  else
-  {
-    if (gearman_string_create(&self->value.string, size) == NULL)
+    if (gearman_string_append(&self->value.string, static_cast<const char *>(value), size) == false)
     {
       return GEARMAN_MEMORY_ALLOCATION_FAILURE;
     }
-    self->type= GEARMAN_RESULT_BINARY;
   }
+
   self->_is_null= false;
+  self->type= GEARMAN_RESULT_BINARY;
 
-  return gearman_string_append(&self->value.string, static_cast<const char *>(value), size);
+  return GEARMAN_SUCCESS;
 }
 
 void gearman_result_store_integer(gearman_result_st *self, int64_t value)
@@ -206,7 +186,7 @@ void gearman_result_store_integer(gearman_result_st *self, int64_t value)
   {
     if (self->type == GEARMAN_RESULT_BINARY)
     {
-      gearman_string_free(&self->value.string);
+      self->value.string.clear();
     }
 
     self->type= GEARMAN_RESULT_INTEGER;

+ 25 - 8
libgearman/result.hpp

@@ -46,10 +46,22 @@ struct gearman_result_st
   bool _is_null;
   enum gearman_result_t type;
 
-  union {
+  struct Value {
     bool boolean;
     int64_t integer;
     gearman_vector_st string;
+
+    Value() :
+      boolean(false),
+      integer(0)
+    { }
+
+    Value(size_t initial_size) :
+      boolean(false),
+      integer(0),
+      string(initial_size)
+    { }
+
   } value;
 
   gearman_result_st();
@@ -65,7 +77,7 @@ struct gearman_result_st
   {
     if (type == GEARMAN_RESULT_BINARY)
     {
-      gearman_string_free(&value.string);
+      value.string.clear();
     }
     else if (type == GEARMAN_RESULT_INTEGER)
     {
@@ -77,7 +89,16 @@ struct gearman_result_st
     _is_null= true;
   }
 
-  gearman_vector_st *string()
+  gearman_vector_st *mutable_string()
+  {
+    value.integer= 0;
+    value.boolean= false;
+    type= GEARMAN_RESULT_BINARY;
+
+    return &value.string;
+  }
+
+  const gearman_vector_st *string() const
   {
     if (type == GEARMAN_RESULT_BINARY)
     {
@@ -99,11 +120,7 @@ struct gearman_result_st
 
   ~gearman_result_st()
   {
-    if (type == GEARMAN_RESULT_BINARY)
-    {
-      assert_msg(gearman_is_initialized(&value.string), "Somehow we have a GEARMAN_RESULT_BINARY, but no valid string");
-      gearman_string_free(&value.string);
-    }
+    gearman_string_free(&value.string);
   }
 
 private:

+ 9 - 11
libgearman/task.cc

@@ -368,12 +368,12 @@ size_t gearman_task_send_workload(gearman_task_st *task, const void *workload,
 
 gearman_result_st *gearman_task_result(gearman_task_st *task)
 {
-  if (task == NULL)
+  if (task)
   {
-    return NULL;
+    return task->result_ptr;
   }
 
-  return task->result_ptr;
+  return NULL;
 }
 
 gearman_result_st *gearman_task_mutable_result(gearman_task_st *task)
@@ -399,19 +399,17 @@ const void *gearman_task_data(const gearman_task_st *task)
     return task->recv->data;
   }
 
-    return NULL;
+  return NULL;
 }
 
 size_t gearman_task_data_size(const gearman_task_st *task)
 {
-  if (task == NULL)
-  {
-    return 0;
-  }
-
-  if (task->recv and task->recv->data_size)
+  if (task)
   {
-    return task->recv->data_size;
+    if (task->recv and task->recv->data_size)
+    {
+      return task->recv->data_size;
+    }
   }
 
   return 0;

+ 8 - 1
libgearman/universal.cc

@@ -621,7 +621,14 @@ gearman_id_t gearman_universal_id(gearman_universal_st &universal)
 void gearman_universal_set_namespace(gearman_universal_st& universal, const char *namespace_key, size_t namespace_key_size)
 {
   gearman_string_free(universal._namespace);
-  universal._namespace= gearman_string_create(NULL, namespace_key, namespace_key_size);
+  if (namespace_key)
+  {
+    universal._namespace= gearman_string_create(NULL, namespace_key, namespace_key_size);
+  }
+  else
+  {
+    universal._namespace= NULL;
+  }
 }
 
 const char *gearman_univeral_namespace(gearman_universal_st& universal)

+ 129 - 82
libgearman/vector.cc

@@ -2,7 +2,7 @@
  * 
  *  Gearmand String
  *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that the following conditions are
@@ -36,94 +36,103 @@
 
 
 #include "gear_config.h"
-#include <libgearman/common.h>
 
 #include "libgearman/assert.hpp"
+#include "libgearman/is.hpp"
+#include "libgearman/vector.hpp"
 
 #include <cstdlib>
 #include <cstring>
+#include <memory>
 
 #include "util/memory.h"
 using namespace org::tangent;
 
-#define GEARMAN_BLOCK_SIZE 1024*4
-
-inline static gearman_return_t _string_check(gearman_vector_st *string, const size_t need)
+inline static bool _string_check(gearman_vector_st *string, const size_t need)
 {
+  assert_msg(string, "Programmer error, _string_check() was passed a null gearman_vector_st");
   if (string)
   {
-    if (need && need > size_t(string->current_size - size_t(string->end - string->string)))
+    if (need and need > size_t(string->current_size - size_t(string->end - string->string)))
     {
       size_t current_offset= size_t(string->end - string->string);
-      char *new_value;
-      size_t adjust;
-      size_t new_size;
 
       /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
-      adjust= (need - size_t(string->current_size - size_t(string->end - string->string))) / GEARMAN_BLOCK_SIZE;
+      size_t adjust= (need - size_t(string->current_size - size_t(string->end - string->string))) / GEARMAN_VECTOR_BLOCK_SIZE;
       adjust++;
 
-      new_size= sizeof(char) * size_t((adjust * GEARMAN_BLOCK_SIZE) + string->current_size);
+      size_t new_size= sizeof(char) * size_t((adjust * GEARMAN_VECTOR_BLOCK_SIZE) + string->current_size);
       /* Test for overflow */
       if (new_size < need)
       {
-        return GEARMAN_MEMORY_ALLOCATION_FAILURE;
+        return false;
       }
 
-      new_value= static_cast<char *>(realloc(string->string, new_size));
+      char* new_value= static_cast<char *>(realloc(string->string, new_size));
       if (new_value == NULL)
       {
-        return GEARMAN_MEMORY_ALLOCATION_FAILURE;
+        return false;
       }
 
       string->string= new_value;
       string->end= string->string + current_offset;
 
-      string->current_size+= (GEARMAN_BLOCK_SIZE * adjust);
+      string->current_size+= (GEARMAN_VECTOR_BLOCK_SIZE * adjust);
     }
 
-    return GEARMAN_SUCCESS;
+    return true;
   }
 
-  return GEARMAN_INVALID_ARGUMENT;
+  return false;
 }
 
-static inline void _init_string(gearman_vector_st *self)
+void gearman_vector_st::init()
 {
-  self->current_size= 0;
-  self->end= self->string= NULL;
+  current_size= 0;
+  end= string= NULL;
 }
 
-gearman_vector_st *gearman_string_create(gearman_vector_st *self, const char *str, size_t initial_size)
+gearman_vector_st *gearman_string_create(gearman_vector_st *self, const char *str, size_t str_size)
 {
+  assert_msg(str, "Programmer error, gearman_string_clear() was passed a null string");
   if (str == NULL)
   {
     return NULL;
   }
 
-  self= gearman_string_create(self, initial_size);
+  self= gearman_string_create(self, str_size);
+  assert_vmsg(self, "Programmer error, gearman_string_create() returned a null gearman_vector_st() requesting a reserve of %u", uint32_t(str_size));
   if (self)
   {
-    if (gearman_failed(gearman_string_append(self, str, initial_size)))
+    if ((gearman_string_append(self, str, str_size) == false))
     {
+      assert_vmsg(self, "Programmer error, gearman_string_append() returned false while trying to append a string of %u length", uint32_t(str_size));
       gearman_string_free(self);
       return NULL;
     }
   }
 
-   return self;
+  return self;
 }
 
-gearman_vector_st *gearman_string_create(gearman_vector_st *self, size_t initial_size)
+gearman_vector_st::gearman_vector_st(size_t initial_size) :
+  end(NULL),
+  string(NULL),
+  current_size(0)
 {
-  /* Saving malloc calls :) */
-  if (self)
+  if (initial_size)
   {
-    gearman_set_allocated(self, false);
+    _string_check(this, initial_size +1);
   }
-  else
+}
+
+gearman_vector_st *gearman_string_create(gearman_vector_st *self, size_t reserve_)
+{
+  /* Saving malloc calls :) */
+  if (self == NULL)
   {
-    self= static_cast<gearman_vector_st *>(malloc(sizeof(gearman_vector_st)));
+    self= new (std::nothrow) gearman_vector_st(reserve_);
+    assert_vmsg(self, "Programmer error, new gearman_vector_st() failed reserve: %u", uint32_t(reserve_));
 
     if (self == NULL)
     {
@@ -132,30 +141,21 @@ gearman_vector_st *gearman_string_create(gearman_vector_st *self, size_t initial
 
     gearman_set_allocated(self, true);
   }
+  else
+  {
+    self->clear();
+    self->resize(reserve_);
+  }
   gearman_set_initialized(self, true);
 
-  _init_string(self);
-
-  if (gearman_failed(_string_check(self, initial_size)))
+  assert_vmsg(reserve_ <= self->capacity(), "Programmer error, capacity: %u reserve: %u", uint32_t(self->capacity()), uint32_t(reserve_));
+  if (reserve_ > self->capacity())
   {
-    if (gearman_is_allocated(self))
-    {
-      void* tmp_ptr= self;
-      util::free__(tmp_ptr);
-    }
-    else
-    {
-      gearman_set_initialized(self, false);
-    }
+    gearman_string_free(self);
 
     return NULL;
   }
 
-  if (initial_size)
-  {
-    self->string[0]= 0;
-  }
-
   return self;
 }
 
@@ -170,7 +170,7 @@ gearman_vector_st *gearman_string_clone(const gearman_vector_st *self)
     {
       if (gearman_string_length(self))
       {
-        if (gearman_failed(gearman_string_append(clone, gearman_string_value(self), gearman_string_length(self))))
+        if (gearman_string_append(clone, gearman_string_value(self), gearman_string_length(self)) == false)
         {
           gearman_string_free(clone);
           return NULL;
@@ -182,38 +182,35 @@ gearman_vector_st *gearman_string_clone(const gearman_vector_st *self)
   return clone;
 }
 
-gearman_return_t gearman_string_append_character(gearman_vector_st *string, char character)
+bool gearman_string_append_character(gearman_vector_st *string, char character)
 {
-  gearman_return_t rc;
-
-
-  if (gearman_failed(rc= _string_check(string, 1 +1))) // Null terminate
+  assert_msg(string, "Programmer error, gearman_string_append_character() was passed a null gearman_vector_st");
+  if (_string_check(string, 1 +1) == false) // Null terminate
   {
-    return rc;
+    return false;
   }
 
   *string->end= character;
   string->end++;
   *string->end= 0;
 
-  return GEARMAN_SUCCESS;
+  return true;
 }
 
-gearman_return_t gearman_string_append(gearman_vector_st *string,
-                                       const char *value, size_t length)
+bool gearman_string_append(gearman_vector_st *string,
+                           const char *value, size_t length)
 {
-  gearman_return_t rc;
-
-  if (gearman_failed(rc= _string_check(string, length +1)))
+  assert_msg(string, "Programmer error, gearman_string_append() was passed a null gearman_vector_st");
+  if (_string_check(string, length +1) == false)
   {
-    return rc;
+    return false;
   }
 
   memcpy(string->end, value, length);
   string->end+= length;
   *string->end= 0; // Add a NULL
 
-  return GEARMAN_SUCCESS;
+  return true;
 }
 
 char *gearman_string_c_copy(gearman_vector_st *string)
@@ -233,47 +230,97 @@ char *gearman_string_c_copy(gearman_vector_st *string)
   return c_ptr;
 }
 
-void gearman_string_reset(gearman_vector_st *string)
+void gearman_string_clear(gearman_vector_st *string)
 {
-  assert(string);
-  string->end= string->string;
+  assert_msg(string, "Programmer error, gearman_string_clear() was passed a null gearman_vector_st");
+  string->clear();
 }
 
-void gearman_string_free(gearman_vector_st *ptr)
+gearman_vector_st::~gearman_vector_st()
 {
-  if (ptr)
+  if (string)
   {
-    if (ptr->string)
+    void* tmp_ptr= string;
+    util::free__(tmp_ptr);
+  }
+}
+
+void gearman_vector_st::resize(const size_t size_)
+{
+  if (size_ == 0)
+  {
+    void* tmp_ptr= string;
+    util::free__(tmp_ptr);
+    init();
+  }
+  else if (size_ > capacity())
+  {
+    reserve(size_);
+  }
+  else if (size_ < capacity())
+  {
+    size_t final_size= (size_ < size()) ?  size_ : size();
+    char* new_value= static_cast<char *>(realloc(string, size_ +1));
+    if (new_value == NULL)
     {
-      void* tmp_ptr= ptr->string;
-      util::free__(tmp_ptr);
+      return;
     }
+    string= new_value;
+    end= string +final_size;
+    current_size= size_ +1;
+    string[final_size]= 0;
+  }
+}
 
-    if (gearman_is_allocated(ptr))
+void gearman_string_free(gearman_vector_st *string)
+{
+  if (string)
+  {
+    if (gearman_is_allocated(string))
     {
-      void* tmp_ptr= ptr;
-      util::free__(tmp_ptr);
+      delete string;
       return;
     }
 
-    assert(gearman_is_allocated(ptr) == false);
-    gearman_set_initialized(ptr, false);
-    ptr->string= NULL;
-    ptr->end= NULL;
-    ptr->current_size= 0;
+    assert(gearman_is_allocated(string) == false);
+    string->resize(0);
+    gearman_set_initialized(string, false);
   }
 }
 
-gearman_return_t gearman_string_check(gearman_vector_st *string, size_t need)
+bool gearman_string_reserve(gearman_vector_st *string, size_t need_)
+{
+  if (need_)
+  {
+    return _string_check(string, need_ +1);
+  }
+
+  // Let _string_check handle the behavior of zero
+  return _string_check(string, need_);
+}
+
+size_t gearman_vector_st::size() const
 {
-  return _string_check(string, need);
+  assert(end >= string);
+  return size_t(end -string);
+}
+
+void gearman_vector_st::reserve(size_t need_)
+{
+  if (need_)
+  {
+    _string_check(this, need_ +1);
+  }
+
+  // Let _string_check handle the behavior of zero
+  _string_check(this, need_);
 }
 
 size_t gearman_string_length(const gearman_vector_st *self)
 {
   if (self)
   {
-    return size_t(self->end - self->string);
+    return self->size();
   }
 
   return 0;
@@ -302,7 +349,7 @@ gearman_string_t gearman_string_take_string(gearman_vector_st *self)
   if (gearman_string_length(self))
   {
     gearman_string_t passable= gearman_string(self);
-    _init_string(self);
+    self->init();
     return passable;
   }
 

+ 58 - 14
libgearman/vector.hpp

@@ -36,6 +36,10 @@
 
 #pragma once
 
+#include "libgearman-1.0/string.h"
+
+#define GEARMAN_VECTOR_BLOCK_SIZE 1024*4
+
 /**
   vectors are always under our control so we make some assumptions about them.
 
@@ -47,10 +51,55 @@ struct gearman_vector_st {
   char *end;
   char *string;
   size_t current_size;
-  struct {
-    bool is_allocated:1;
-    bool is_initialized:1;
+
+  struct Options {
+    bool is_allocated;
+    bool is_initialized;
+    Options() :
+      is_allocated(false),
+      is_initialized(true)
+    { }
   } options;
+
+  gearman_vector_st() :
+    end(NULL),
+    string(NULL),
+    current_size(0)
+  {
+  }
+
+  gearman_vector_st(size_t initial_size);
+
+  ~gearman_vector_st();
+
+  void resize(size_t);
+  void reserve(size_t);
+
+
+  void clear()
+  {
+    end= string;
+    if (current_size)
+    {
+      string[0]= 0;
+    }
+  }
+
+  size_t capacity() const
+  {
+    // We tell a white lie about size since we always keep things null
+    // terminated
+    if (current_size == 1)
+    {
+      return 0;
+    }
+
+    return current_size;
+  }
+
+  size_t size() const;
+
+  void init();
 };
 
 
@@ -64,24 +113,19 @@ gearman_vector_st *gearman_string_create(gearman_vector_st *self, const char *st
 extern "C" {
 #endif
 
-
-
 gearman_vector_st *gearman_string_clone(const gearman_vector_st *);
 
-
-gearman_return_t gearman_string_check(gearman_vector_st *string, size_t need);
-
+bool gearman_string_reserve(gearman_vector_st *string, size_t need);
 
 char *gearman_string_c_copy(gearman_vector_st *string);
 
+bool gearman_string_append_character(gearman_vector_st *string,
+                                     char character);
 
-gearman_return_t gearman_string_append_character(gearman_vector_st *string,
-                                                 char character);
-
-gearman_return_t gearman_string_append(gearman_vector_st *string,
-                                       const char *value, size_t length);
+bool gearman_string_append(gearman_vector_st *string,
+                           const char *value, size_t length);
 
-void gearman_string_reset(gearman_vector_st *string);
+void gearman_string_clear(gearman_vector_st *string);
 
 
 void gearman_string_free(gearman_vector_st *string);

Some files were not shown because too many files changed in this diff