Browse Source

Merge lp:~tangent-org/gearmand/1.2-build/ Build: jenkins-Gearmand-460

Continuous Integration 12 years ago
parent
commit
cd53a9be0d

+ 6 - 0
docs/architecture.rst

@@ -0,0 +1,6 @@
+Architecture 
+============
+
+TTL
+
+  TBD

+ 1 - 0
docs/index.rst

@@ -19,6 +19,7 @@ Introduction:
    install
    how_to_report_a_bug
    glossary
+   architecture
 
 ------
 Server

+ 1 - 1
libgearman-1.0/job.h

@@ -2,7 +2,7 @@
  * 
  *  Gearmand client and server library.
  *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
  *  Copyright (C) 2008 Brian Aker, Eric Day
  *  All rights reserved.
  *

+ 1 - 1
libgearman-1.0/task.h

@@ -2,7 +2,7 @@
  * 
  *  Gearmand client and server library.
  *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
  *  Copyright (C) 2008 Brian Aker, Eric Day
  *  All rights reserved.
  *

+ 6 - 1
libgearman/interface/task.hpp

@@ -144,7 +144,12 @@ struct Task
     return _result_ptr;
   }
 
-  void free_result();
+  void result(gearman_result_st* result_);
+
+  void free_result()
+  {
+    result(NULL);
+  }
 
   bool create_result(size_t initial_size);
 

+ 299 - 206
libgearman/job.cc

@@ -241,361 +241,454 @@ static inline void gearman_job_reset_error(gearman_job_st *job)
 
 gearman_return_t gearman_job_send_data(gearman_job_st *job, const void *data, size_t data_size)
 {
-  const void *args[2];
-  size_t args_size[2];
-
-  if (job->reducer)
+  if (job)
   {
-    gearman_argument_t value= gearman_argument_make(NULL, 0, static_cast<const char *>(data), data_size);
-    job->reducer->add(value);
+    const void *args[2];
+    size_t args_size[2];
 
-    return GEARMAN_SUCCESS;
-  }
+    if (job->reducer)
+    {
+      gearman_argument_t value= gearman_argument_make(NULL, 0, static_cast<const char *>(data), data_size);
+      job->reducer->add(value);
 
-  if ((job->options.work_in_use) == false)
-  {
-    args[0]= job->assigned.arg[0];
-    args_size[0]= job->assigned.arg_size[0];
-    args[1]= data;
-    args_size[1]= data_size;
-    gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
-                                                     GEARMAN_MAGIC_REQUEST,
-                                                     GEARMAN_COMMAND_WORK_DATA,
-                                                     args, args_size, 2);
-    if (gearman_failed(ret))
+      return GEARMAN_SUCCESS;
+    }
+
+    if ((job->options.work_in_use) == false)
     {
-      return ret;
+      args[0]= job->assigned.arg[0];
+      args_size[0]= job->assigned.arg_size[0];
+      args[1]= data;
+      args_size[1]= data_size;
+      gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
+                                                       GEARMAN_MAGIC_REQUEST,
+                                                       GEARMAN_COMMAND_WORK_DATA,
+                                                       args, args_size, 2);
+      if (gearman_failed(ret))
+      {
+        return ret;
+      }
+
+      job->options.work_in_use= true;
     }
 
-    job->options.work_in_use= true;
+    return _job_send(job);
   }
 
-  return _job_send(job);
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 gearman_return_t gearman_job_send_warning(gearman_job_st *job,
                                           const void *warning,
                                           size_t warning_size)
 {
-  const void *args[2];
-  size_t args_size[2];
-
-  if ((job->options.work_in_use) == false)
+  if (job)
   {
-    args[0]= job->assigned.arg[0];
-    args_size[0]= job->assigned.arg_size[0];
-    args[1]= warning;
-    args_size[1]= warning_size;
+    const void *args[2];
+    size_t args_size[2];
 
-    gearman_return_t ret;
-    ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
-                                    GEARMAN_MAGIC_REQUEST,
-                                    GEARMAN_COMMAND_WORK_WARNING,
-                                    args, args_size, 2);
-    if (gearman_failed(ret))
+    if ((job->options.work_in_use) == false)
     {
-      return ret;
+      args[0]= job->assigned.arg[0];
+      args_size[0]= job->assigned.arg_size[0];
+      args[1]= warning;
+      args_size[1]= warning_size;
+
+      gearman_return_t ret;
+      ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
+                                      GEARMAN_MAGIC_REQUEST,
+                                      GEARMAN_COMMAND_WORK_WARNING,
+                                      args, args_size, 2);
+      if (gearman_failed(ret))
+      {
+        return ret;
+      }
+
+      job->options.work_in_use= true;
     }
 
-    job->options.work_in_use= true;
+    return _job_send(job);
   }
 
-  return _job_send(job);
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 gearman_return_t gearman_job_send_status(gearman_job_st *job,
                                          uint32_t numerator,
                                          uint32_t denominator)
 {
-  char numerator_string[12];
-  char denominator_string[12];
-  const void *args[3];
-  size_t args_size[3];
-
-  if (not (job->options.work_in_use))
+  if (job)
   {
-    snprintf(numerator_string, 12, "%u", numerator);
-    snprintf(denominator_string, 12, "%u", denominator);
-
-    args[0]= job->assigned.arg[0];
-    args_size[0]= job->assigned.arg_size[0];
-    args[1]= numerator_string;
-    args_size[1]= strlen(numerator_string) + 1;
-    args[2]= denominator_string;
-    args_size[2]= strlen(denominator_string);
+    char numerator_string[12];
+    char denominator_string[12];
+    const void *args[3];
+    size_t args_size[3];
 
-    gearman_return_t ret;
-    ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
-                                    GEARMAN_MAGIC_REQUEST,
-                                    GEARMAN_COMMAND_WORK_STATUS,
-                                    args, args_size, 3);
-    if (gearman_failed(ret))
+    if (not (job->options.work_in_use))
     {
-      return ret;
+      snprintf(numerator_string, 12, "%u", numerator);
+      snprintf(denominator_string, 12, "%u", denominator);
+
+      args[0]= job->assigned.arg[0];
+      args_size[0]= job->assigned.arg_size[0];
+      args[1]= numerator_string;
+      args_size[1]= strlen(numerator_string) + 1;
+      args[2]= denominator_string;
+      args_size[2]= strlen(denominator_string);
+
+      gearman_return_t ret;
+      ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
+                                      GEARMAN_MAGIC_REQUEST,
+                                      GEARMAN_COMMAND_WORK_STATUS,
+                                      args, args_size, 3);
+      if (gearman_failed(ret))
+      {
+        return ret;
+      }
+
+      job->options.work_in_use= true;
     }
 
-    job->options.work_in_use= true;
+    return _job_send(job);
   }
 
-  return _job_send(job);
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 gearman_return_t gearman_job_send_complete(gearman_job_st *job,
                                            const void *result,
                                            size_t result_size)
 {
-  if (job->reducer)
+  if (job)
   {
-    return GEARMAN_INVALID_ARGUMENT;
+    if (job->reducer)
+    {
+      return GEARMAN_INVALID_ARGUMENT;
+    }
+
+    return gearman_job_send_complete_fin(job, result, result_size);
   }
 
-  return gearman_job_send_complete_fin(job, result, result_size);
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 gearman_return_t gearman_job_send_complete_fin(gearman_job_st *job,
                                                const void *result, size_t result_size)
 {
-  if (job->options.finished)
-  {
-    return GEARMAN_SUCCESS;
-  }
-
-  if (job->reducer)
+  if (job)
   {
-    if (result_size)
+    if (job->options.finished)
     {
-      gearman_argument_t value= gearman_argument_make(NULL, 0, static_cast<const char *>(result), result_size);
-      job->reducer->add(value);
+      return GEARMAN_SUCCESS;
     }
 
-    gearman_return_t rc= job->reducer->complete();
-    if (gearman_failed(rc))
+    if (job->reducer)
     {
-      return gearman_error(job->worker->impl()->universal, rc, "The reducer's complete() returned an error");
-    }
+      if (result_size)
+      {
+        gearman_argument_t value= gearman_argument_make(NULL, 0, static_cast<const char *>(result), result_size);
+        job->reducer->add(value);
+      }
 
-    const gearman_vector_st *reduced_value= job->reducer->result.string();
-    if (reduced_value)
-    {
-      result= gearman_string_value(reduced_value);
-      result_size= gearman_string_length(reduced_value);
-    }
-    else
-    {
-      result= NULL;
-      result_size= 0;
-    }
-  } 
+      gearman_return_t rc= job->reducer->complete();
+      if (gearman_failed(rc))
+      {
+        return gearman_error(job->worker->impl()->universal, rc, "The reducer's complete() returned an error");
+      }
 
-  const void *args[2];
-  size_t args_size[2];
+      const gearman_vector_st *reduced_value= job->reducer->result.string();
+      if (reduced_value)
+      {
+        result= gearman_string_value(reduced_value);
+        result_size= gearman_string_length(reduced_value);
+      }
+      else
+      {
+        result= NULL;
+        result_size= 0;
+      }
+    } 
 
-  if (not (job->options.work_in_use))
-  {
-    args[0]= job->assigned.arg[0];
-    args_size[0]= job->assigned.arg_size[0];
+    const void *args[2];
+    size_t args_size[2];
 
-    args[1]= result;
-    args_size[1]= result_size;
-    gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
-                                                     GEARMAN_MAGIC_REQUEST,
-                                                     GEARMAN_COMMAND_WORK_COMPLETE,
-                                                     args, args_size, 2);
+    if (not (job->options.work_in_use))
+    {
+      args[0]= job->assigned.arg[0];
+      args_size[0]= job->assigned.arg_size[0];
+
+      args[1]= result;
+      args_size[1]= result_size;
+      gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
+                                                       GEARMAN_MAGIC_REQUEST,
+                                                       GEARMAN_COMMAND_WORK_COMPLETE,
+                                                       args, args_size, 2);
+      if (gearman_failed(ret))
+      {
+        return ret;
+      }
+      job->options.work_in_use= true;
+    }
+
+    gearman_return_t ret= _job_send(job);
     if (gearman_failed(ret))
     {
       return ret;
     }
-    job->options.work_in_use= true;
-  }
 
-  gearman_return_t ret= _job_send(job);
-  if (gearman_failed(ret))
-  {
-    return ret;
-  }
+    job->options.finished= true;
 
-  job->options.finished= true;
+    return GEARMAN_SUCCESS;
+  }
 
-  return GEARMAN_SUCCESS;
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 gearman_return_t gearman_job_send_exception(gearman_job_st *job,
                                             const void *exception,
                                             size_t exception_size)
 {
-  const void *args[2];
-  size_t args_size[2];
-
-  if (not (job->options.work_in_use))
+  if (job)
   {
-    args[0]= job->assigned.arg[0];
-    args_size[0]= job->assigned.arg_size[0];
-    args[1]= exception;
-    args_size[1]= exception_size;
+    const void *args[2];
+    size_t args_size[2];
 
-    gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
-                                                     GEARMAN_MAGIC_REQUEST,
-                                                     GEARMAN_COMMAND_WORK_EXCEPTION,
-                                                     args, args_size, 2);
-    if (gearman_failed(ret))
-      return ret;
+    if (not (job->options.work_in_use))
+    {
+      args[0]= job->assigned.arg[0];
+      args_size[0]= job->assigned.arg_size[0];
+      args[1]= exception;
+      args_size[1]= exception_size;
+
+      gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
+                                                       GEARMAN_MAGIC_REQUEST,
+                                                       GEARMAN_COMMAND_WORK_EXCEPTION,
+                                                       args, args_size, 2);
+      if (gearman_failed(ret))
+        return ret;
+
+      job->options.work_in_use= true;
+    }
 
-    job->options.work_in_use= true;
+    return _job_send(job);
   }
 
-  return _job_send(job);
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 gearman_return_t gearman_job_send_fail(gearman_job_st *job)
 {
-  if (job->reducer)
-    return GEARMAN_INVALID_ARGUMENT;
+  if (job)
+  {
+    if (job->reducer)
+    {
+      return GEARMAN_INVALID_ARGUMENT;
+    }
 
-  return gearman_job_send_fail_fin(job);
+    return gearman_job_send_fail_fin(job);
+  }
+
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 gearman_return_t gearman_job_send_fail_fin(gearman_job_st *job)
 {
-  const void *args[1];
-  size_t args_size[1];
-
-  if (job->options.finished)
+  if (job)
   {
-    return GEARMAN_SUCCESS;
-  }
+    const void *args[1];
+    size_t args_size[1];
 
-  if (not (job->options.work_in_use))
-  {
-    args[0]= job->assigned.arg[0];
-    args_size[0]= job->assigned.arg_size[0] - 1;
-    gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
-                                                     GEARMAN_MAGIC_REQUEST,
-                                                     GEARMAN_COMMAND_WORK_FAIL,
-                                                     args, args_size, 1);
-    if (gearman_failed(ret))
+    if (job->options.finished)
     {
-      return ret;
+      return GEARMAN_SUCCESS;
     }
 
-    job->options.work_in_use= true;
-  }
+    if (not (job->options.work_in_use))
+    {
+      args[0]= job->assigned.arg[0];
+      args_size[0]= job->assigned.arg_size[0] - 1;
+      gearman_return_t ret= gearman_packet_create_args(job->worker->impl()->universal, job->work,
+                                                       GEARMAN_MAGIC_REQUEST,
+                                                       GEARMAN_COMMAND_WORK_FAIL,
+                                                       args, args_size, 1);
+      if (gearman_failed(ret))
+      {
+        return ret;
+      }
 
-  gearman_return_t ret;
-  ret= _job_send(job);
-  if (gearman_failed(ret))
-    return ret;
+      job->options.work_in_use= true;
+    }
 
-  job->options.finished= true;
-  return GEARMAN_SUCCESS;
+    gearman_return_t ret;
+    ret= _job_send(job);
+    if (gearman_failed(ret))
+      return ret;
+
+    job->options.finished= true;
+    return GEARMAN_SUCCESS;
+  }
+
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 const char *gearman_job_handle(const gearman_job_st *job)
 {
-  return static_cast<const char *>(job->assigned.arg[0]);
+  if (job)
+  {
+    return static_cast<const char *>(job->assigned.arg[0]);
+  }
+
+  return NULL;
 }
 
 const char *gearman_job_function_name(const gearman_job_st *job)
 {
-  return static_cast<char *>(job->assigned.arg[1]);
+  if (job)
+  {
+    return static_cast<char *>(job->assigned.arg[1]);
+  }
+  return NULL;
 }
 
 gearman_string_t gearman_job_function_name_string(const gearman_job_st *job)
 {
-  gearman_string_t temp= { job->assigned.arg[1], job->assigned.arg_size[1] };
-  return temp;
+  if (job)
+  {
+    gearman_string_t temp= { job->assigned.arg[1], job->assigned.arg_size[1] };
+    return temp;
+  }
+
+  static gearman_string_t ret= {0, 0};
+  return ret;
 }
 
 const char *gearman_job_unique(const gearman_job_st *job)
 {
-  if (job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_UNIQ or
-      job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL)
+  if (job)
   {
-    return static_cast<const char *>(job->assigned.arg[2]);
+    if (job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_UNIQ or
+        job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL)
+    {
+      return static_cast<const char *>(job->assigned.arg[2]);
+    }
+
+    return "";
   }
 
-  return "";
+  return NULL;
 }
 
 bool gearman_job_is_map(const gearman_job_st *job)
 {
-  return bool(job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL) and job->assigned.arg_size[3] > 1;
+  if (job)
+  {
+    return bool(job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL) and job->assigned.arg_size[3] > 1;
+  }
+
+  return NULL;
 }
 
 gearman_string_t gearman_job_reducer_string(const gearman_job_st *job)
 {
-  if (job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL and job->assigned.arg_size[3] > 1)
+  if (job)
   {
-    gearman_string_t temp= { job->assigned.arg[3], job->assigned.arg_size[3] -1 };
-    return temp;
-  }
+    if (job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL and job->assigned.arg_size[3] > 1)
+    {
+      gearman_string_t temp= { job->assigned.arg[3], job->assigned.arg_size[3] -1 };
+      return temp;
+    }
+
+    static gearman_string_t null_temp= { gearman_literal_param("") };
 
-  static gearman_string_t null_temp= { gearman_literal_param("") };
+    return null_temp;
+  }
 
-  return null_temp;
+  static gearman_string_t ret= {0, 0};
+  return ret;
 }
 
 const char *gearman_job_reducer(const gearman_job_st *job)
 {
-  if (job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL)
-    return static_cast<const char *>(job->assigned.arg[3]);
+  if (job)
+  {
+    if (job->assigned.command == GEARMAN_COMMAND_JOB_ASSIGN_ALL)
+    {
+      return static_cast<const char *>(job->assigned.arg[3]);
+    }
+
+    return "";
+  }
 
-  return "";
+  return NULL;
 }
 
 const void *gearman_job_workload(const gearman_job_st *job)
 {
-  return job->assigned.data;
+  if (job)
+  {
+    return job->assigned.data;
+  }
+
+  return NULL;
 }
 
 size_t gearman_job_workload_size(const gearman_job_st *job)
 {
-  return job->assigned.data_size;
+  if (job)
+  {
+    return job->assigned.data_size;
+  }
+
+  return 0;
 }
 
 void *gearman_job_take_workload(gearman_job_st *job, size_t *data_size)
 {
-  return gearman_packet_take_data(job->assigned, data_size);
+  if (job)
+  {
+    return gearman_packet_take_data(job->assigned, data_size);
+  }
+
+  return NULL;
 }
 
 void gearman_job_free(gearman_job_st *job)
 {
-  if (job == NULL)
-  {
-    return;
-  }
-
-  if (job->options.assigned_in_use)
+  if (job)
   {
-    gearman_packet_free(&(job->assigned));
-  }
+    if (job->options.assigned_in_use)
+    {
+      gearman_packet_free(&(job->assigned));
+    }
 
-  if (job->options.work_in_use)
-  {
-    gearman_packet_free(&(job->work));
-  }
+    if (job->options.work_in_use)
+    {
+      gearman_packet_free(&(job->work));
+    }
 
-  if (job->worker->impl()->job_list == job)
-  {
-    job->worker->impl()->job_list= job->next;
-  }
+    if (job->worker->impl()->job_list == job)
+    {
+      job->worker->impl()->job_list= job->next;
+    }
 
-  if (job->prev)
-  {
-    job->prev->next= job->next;
-  }
+    if (job->prev)
+    {
+      job->prev->next= job->next;
+    }
 
-  if (job->next)
-  {
-    job->next->prev= job->prev;
-  }
-  job->worker->impl()->job_count--;
+    if (job->next)
+    {
+      job->next->prev= job->prev;
+    }
+    job->worker->impl()->job_count--;
 
-  delete job->reducer;
-  job->reducer= NULL;
+    delete job->reducer;
+    job->reducer= NULL;
 
-  if (job->options.allocated)
-  {
-    delete job;
+    if (job->options.allocated)
+    {
+      delete job;
+    }
   }
 }
 

+ 26 - 15
libgearman/task.cc

@@ -290,15 +290,23 @@ void gearman_task_give_workload(gearman_task_st *task_shell, const void *workloa
   }
 }
 
-size_t gearman_task_send_workload(gearman_task_st *task_shell, const void *workload,
-                                  size_t workload_size,
+size_t gearman_task_send_workload(gearman_task_st *task_shell,
+                                  const void *workload, size_t workload_size,
                                   gearman_return_t *ret_ptr)
 {
+  gearman_return_t unused;
+  if (ret_ptr == NULL)
+  {
+    ret_ptr= &unused;
+  }
+
   if (task_shell and task_shell->impl())
   {
     return task_shell->impl()->con->send_and_flush(workload, workload_size, ret_ptr);
   }
 
+  *ret_ptr= GEARMAN_INVALID_ARGUMENT;
+
   return 0;
 }
 
@@ -314,9 +322,6 @@ gearman_result_st *gearman_task_result(gearman_task_st *task_shell)
 
 gearman_result_st *gearman_task_mutable_result(gearman_task_st* task_shell)
 {
-  assert(task_shell); // Programmer error
-  assert(task_shell->impl()); // Programmer error
-
   if (task_shell)
   {
     Task* task= task_shell->impl();
@@ -372,17 +377,19 @@ size_t gearman_task_recv_data(gearman_task_st *task_shell, void *data,
                                   size_t data_size,
                                   gearman_return_t *ret_ptr)
 {
-  if (task_shell and task_shell->impl())
+  gearman_return_t unused;
+  if (ret_ptr == NULL)
   {
-    gearman_return_t unused;
-    if (ret_ptr == NULL)
-    {
-      ret_ptr= &unused;
-    }
+    ret_ptr= &unused;
+  }
 
+  if (task_shell and task_shell->impl())
+  {
     return task_shell->impl()->con->receive_data(data, data_size, *ret_ptr);
   }
 
+  *ret_ptr= GEARMAN_INVALID_ARGUMENT;
+
   return 0;
 }
 
@@ -404,8 +411,6 @@ const char *gearman_task_error(const gearman_task_st *task_shell)
 
 gearman_return_t gearman_task_return(const gearman_task_st *task_shell)
 {
-  assert(task_shell); // Only used internally.
-  assert(task_shell->impl());
   if (task_shell and task_shell->impl())
   {
     return task_shell->impl()->result_rc;
@@ -419,15 +424,21 @@ Task::~Task()
   free_result();
 }
 
-void Task::free_result()
+void Task::result(gearman_result_st* result_)
 {
   delete _result_ptr;
-  _result_ptr= NULL;
+  _result_ptr= result_;
 }
 
 bool Task::create_result(size_t initial_size)
 {
   assert(_result_ptr == NULL);
+  if (_result_ptr)
+  {
+    _result_ptr->clear();
+    return _result_ptr;
+  }
+
   _result_ptr= new (std::nothrow) gearman_result_st(initial_size);
   return bool(_result_ptr);
 }

+ 21 - 6
libgearman/worker.cc

@@ -1281,12 +1281,12 @@ gearman_return_t gearman_worker_set_memory_allocators(gearman_worker_st *worker,
                                                       gearman_calloc_fn *calloc_fn,
                                                       void *context)
 {
-  if (worker == NULL)
+  if (worker)
   {
-    return GEARMAN_INVALID_ARGUMENT;
+    return gearman_set_memory_allocator(worker->impl()->universal.allocator, malloc_fn, free_fn, realloc_fn, calloc_fn, context);
   }
 
-  return gearman_set_memory_allocator(worker->impl()->universal.allocator, malloc_fn, free_fn, realloc_fn, calloc_fn, context);
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 bool gearman_worker_set_server_option(gearman_worker_st *worker_shell, const char *option_arg, size_t option_arg_size)
@@ -1321,16 +1321,31 @@ gearman_id_t gearman_worker_id(gearman_worker_st *self)
 
 gearman_worker_st *gearman_job_clone_worker(gearman_job_st *job)
 {
-  return gearman_worker_clone(NULL, job->worker);
+  if (job)
+  {
+    return gearman_worker_clone(NULL, job->worker);
+  }
+
+  return NULL;
 }
 
 gearman_return_t gearman_worker_set_identifier(gearman_worker_st *worker,
                                                const char *id, size_t id_size)
 {
-  return gearman_set_identifier(worker->impl()->universal, id, id_size);
+  if (worker)
+  {
+    return gearman_set_identifier(worker->impl()->universal, id, id_size);
+  }
+
+  return GEARMAN_INVALID_ARGUMENT;
 }
 
 const char *gearman_worker_namespace(gearman_worker_st *self)
 {
-  return gearman_univeral_namespace(self->impl()->universal);
+  if (self)
+  {
+    return gearman_univeral_namespace(self->impl()->universal);
+  }
+
+  return NULL;
 }

+ 282 - 7
tests/libgearman-1.0/client_test.cc

@@ -187,10 +187,12 @@ static test_return_t clone_test(void *)
   }
 
   {
-    const gearman_client_st *from= gearman_client_create(NULL);
+    gearman_client_st *from= gearman_client_create(NULL);
+    ASSERT_TRUE(from);
     gearman_client_st* client= gearman_client_clone(NULL, from);
-    test_truth(client);
+    ASSERT_TRUE(client);
     gearman_client_free(client);
+    gearman_client_free(from);
   }
 
   {
@@ -1749,6 +1751,230 @@ static test_return_t gearman_client_set_server_option_GEARMAN_INVALID_ARGUMENT_T
   return TEST_SUCCESS;
 }
 
+static test_return_t gearman_task_free_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  gearman_task_free(NULL);
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_context_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  gearman_task_context(NULL);
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_set_context_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  gearman_task_set_context(NULL, NULL);
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_function_name_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_task_function_name(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_unique_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_task_unique(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_job_handle_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_task_job_handle(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_is_known_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(false, gearman_task_is_known(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_is_running_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(false, gearman_task_is_running(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_numerator_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(0, gearman_task_numerator(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_denominator_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(0, gearman_task_denominator(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_give_workload_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  gearman_task_give_workload(NULL, NULL, 0);
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_send_workload_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  gearman_return_t ret;
+  ASSERT_EQ(0, gearman_task_send_workload(NULL, NULL, 0, &ret));
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, ret);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_data_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_task_data(NULL));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_data_size_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(0, gearman_task_data_size(NULL));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_take_data_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  size_t taken_space;
+  ASSERT_EQ(NULL, gearman_task_take_data(NULL, &taken_space));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_recv_data_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  gearman_return_t ret;
+  ASSERT_EQ(0, gearman_task_recv_data(NULL, NULL, 0, &ret));
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, ret);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_error_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_task_error(NULL));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_result_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_task_result(NULL));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_return_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, gearman_task_return(NULL));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_task_strstate_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_task_strstate(NULL));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_free_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  gearman_job_free(NULL);
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_send_data_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, gearman_job_send_data(NULL, NULL, 0));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_send_warning_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, gearman_job_send_warning(NULL, NULL, 0));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_send_status_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, gearman_job_send_status(NULL, 0, 0));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_send_complete_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, gearman_job_send_complete(NULL, 0, 0));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_send_exception_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, gearman_job_send_exception(NULL, 0, 0));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_send_fail_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(GEARMAN_INVALID_ARGUMENT, gearman_job_send_fail(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_handle_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_job_handle(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_function_name_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_job_function_name(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_unique_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_job_unique(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_workload_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_job_unique(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_workload_size_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(0, gearman_job_workload_size(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_take_workload_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_job_take_workload(NULL, NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_clone_worker_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_job_clone_worker(NULL));
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearman_job_error_GEARMAN_INVALID_ARGUMENT_TEST(void*)
+{
+  ASSERT_EQ(NULL, gearman_job_error(NULL));
+  return TEST_SUCCESS;
+}
+
 static test_return_t default_v1_SETUP(void *object)
 {
   gearman_function_t echo_react_fn= gearman_function_create_v1(echo_or_react_worker);
@@ -1807,16 +2033,20 @@ static test_return_t pre_logging(void *object)
 static void *world_create(server_startup_st& servers, test_return_t& error)
 {
   const char *argv[]= { "--exceptions", 0 };
-  if (server_startup(servers, "gearmand", libtest::default_port(), argv) == false)
+  in_port_t first_port= libtest::default_port();
+  ASSERT_TRUE(server_startup(servers, "gearmand", first_port, argv));
+
+  if (0)
   {
-    error= TEST_SKIPPED;
-    return NULL;
+    const char *null_args[]= { 0 };
+    in_port_t second_port= libtest::get_free_port();
+    ASSERT_TRUE(server_startup(servers, "gearmand", second_port, null_args));
   }
 
   client_test_st *test= new client_test_st();
   ASSERT_TRUE(test);
 
-  test->add_server(NULL, libtest::default_port());
+  test->add_server(NULL, first_port);
 
   error= TEST_SUCCESS;
 
@@ -1889,6 +2119,49 @@ test_st gearman_client_st_GEARMAN_INVALID_ARGUMENT_TESTS[] ={
   {0, 0, 0}
 };
 
+test_st gearman_task_st_GEARMAN_INVALID_ARGUMENT_TESTS[] ={
+  {"gearman_task_free()", 0, gearman_task_free_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_context()", 0, gearman_task_context_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_set_context()", 0, gearman_task_set_context_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_function_name()", 0, gearman_task_function_name_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_unique()", 0, gearman_task_unique_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_job_handle()", 0, gearman_task_job_handle_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_is_known()", 0, gearman_task_is_known_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_is_running()", 0, gearman_task_is_running_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_numerator()", 0, gearman_task_numerator_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_denominator()", 0, gearman_task_denominator_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_give_workload()", 0, gearman_task_give_workload_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_send_workload()", 0, gearman_task_send_workload_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_data()", 0, gearman_task_data_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_data_size()", 0, gearman_task_data_size_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_take_data()", 0, gearman_task_take_data_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_recv_data()", 0, gearman_task_recv_data_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_error()", 0, gearman_task_error_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_result()", 0, gearman_task_result_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_return()", 0, gearman_task_return_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_task_strstate()", 0, gearman_task_strstate_GEARMAN_INVALID_ARGUMENT_TEST },
+  {0, 0, 0}
+};
+
+test_st gearman_job_st_GEARMAN_INVALID_ARGUMENT_TESTS[] ={
+  {"gearman_job_free()", 0, gearman_job_free_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_send_data()", 0, gearman_job_send_data_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_send_warning()", 0, gearman_job_send_warning_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_send_statu()", 0, gearman_job_send_status_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_send_complete()", 0, gearman_job_send_complete_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_send_exception()", 0, gearman_job_send_exception_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_send()", 0, gearman_job_send_fail_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_handle()", 0, gearman_job_handle_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_function_name()", 0, gearman_job_function_name_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_unique()", 0, gearman_job_unique_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_workload()", 0, gearman_job_workload_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_workload_size()", 0, gearman_job_workload_size_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_take_workload()", 0, gearman_job_take_workload_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_clone_worker()", 0, gearman_job_clone_worker_GEARMAN_INVALID_ARGUMENT_TEST },
+  {"gearman_job_error()", 0, gearman_job_error_GEARMAN_INVALID_ARGUMENT_TEST },
+  {0, 0, 0}
+};
+
 test_st gearman_client_set_identifier_TESTS[] ={
   {"gearman_client_set_identifier()", 0, gearman_client_set_identifier_TEST },
   {"gearman_client_set_identifier(with_work)", 0, gearman_client_set_identifier_plus_work_TEST },
@@ -2091,8 +2364,10 @@ test_st limit_tests[] ={
 
 collection_st collection[] ={
   {"gearman_return_t", 0, 0, gearman_return_t_TESTS},
-  {"gearman_client_st GEARMAN_INVALID_ARGUMENT", 0, 0, gearman_client_st_GEARMAN_INVALID_ARGUMENT_TESTS },
   {"init", 0, 0, gearman_client_st_init_TESTS},
+  {"gearman_client_st GEARMAN_INVALID_ARGUMENT", 0, 0, gearman_client_st_GEARMAN_INVALID_ARGUMENT_TESTS },
+  {"gearman_task_st GEARMAN_INVALID_ARGUMENT", 0, 0, gearman_task_st_GEARMAN_INVALID_ARGUMENT_TESTS },
+  {"gearman_job_st GEARMAN_INVALID_ARGUMENT", 0, 0, gearman_job_st_GEARMAN_INVALID_ARGUMENT_TESTS },
   {"gearman_id_t", 0, 0, gearman_id_t_TESTS},
   {"gearman_strerror()", 0, 0, gearman_strerror_tests },
   {"gearman_client_st init", 0, 0, gearman_client_st_init_TESTS },