Updated the handling of queries so that the maximum PeerDist version can be
authorcrh <crh@ubiqx.org>
Fri, 5 Oct 2012 22:15:18 +0000 (17:15 -0500)
committercrh <crh@ubiqx.org>
Fri, 5 Oct 2012 22:15:18 +0000 (17:15 -0500)
specified.

src/daemon/PrequelD.c

index 31990e616fa5f5822ab7a563d7c62ce2b1503c0f..1162887a06e13bc9a74a17082c938ddc45cc2d1e 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Email: crh@ubiqx.mn.org
  *
- * $Id: PrequelD.c 2012-09-20 12:19:52 -0500 crh$
+ * $Id: PrequelD.c 2012-10-05 17:15:18 -0500 crh$
  *
  * -------------------------------------------------------------------------- **
  *
@@ -91,7 +91,7 @@
  *
  * FIX:
  *
- *  + The exclude configuration command doesn't yet work.
+ *  + The 'exclude' configuration command doesn't yet work.
  *
  *  + Need to detect whether we are running already or not.  We can run
  *    multiple daemons at once, as long as their src directories don't
  *  forEach( V, L ) - A macro for traversing a linked list of <pd_ConfigRec>
  *                    records.
  *                    V - The variable that will point to each node in the
- *                        list.  V must be substituted by a pointer to a
+ *                        list.  <V> must be substituted by a pointer to a
  *                        <pd_ConfigRec>.
  *                    L - The list to be traversed.
  *
  *              is true, then the client did provide a value and that value
  *              is stored in the <val> field.
  *
- *  ProtVers  - PeerDist protocol major/minor number structure.
- *
  *  WorkItem  - A queue entry and a string pointer pointing to the pathname
  *              of a source file that is in need of hashing.
  *
@@ -213,12 +211,6 @@ typedef struct
   uint64_t  val;                /* The given value.   */
   } RangeVal;
 
-typedef struct
-  {
-  unsigned char major;          /* PeerDist major version number. */
-  unsigned char minor;          /* PeerDist minor version number. */
-  } ProtVers;
-
 typedef struct
   {
   ubi_slNode  node;             /* Linked list node.  */
@@ -265,7 +257,7 @@ static const char *License =
 static const char *Revision =
                     "$Revision$";
 static const char *Id =
-                    "$Id: PrequelD.c 2012-09-20 12:19:52 -0500 crh$";
+                    "$Id: PrequelD.c 2012-10-05 17:15:18 -0500 crh$";
 
 static const char *HelpMsg[] =
   {
@@ -473,13 +465,14 @@ static int RecvGetc( RecvBufr *Rb )
    *
    *  Notes:  The <RecvErrs> type defines the list of possible error codes.
    *          Note, however, that a return value of zero (0) should not be
-   *          interpreted as <rv_success>.  It should be interpreted as '\0'
+   *          interpreted as <rv_success>.  It should be interpreted as '\0',
    *          a valid input character.
    *
    *          The buffer is refilled if it is empty, which means that the
    *          most recent character returned will still be in the buffer.
    *          so "unget" of one character is always safe.  There are no
-   *          guarantees beyond that.
+   *          guarantees beyond that (...and we don't do "unget" in this
+   *          program, so it's a moot point).
    *
    * ------------------------------------------------------------------------ **
    */
@@ -635,16 +628,24 @@ static RecvErrs QueuePath( int outSock, char const *pathname )
   } /* QueuePath */
 
 
-static RecvErrs QueryPath( int outSock, char const *pathname )
+static RecvErrs QueryPath( int         outSock,
+                           const int   vMajor,
+                           char const *pathname )
   /* ------------------------------------------------------------------------ **
    * Map a source file pathname to the matching cachefile name.
    *
    *  Input:  outSock   - Output socket, so we can communicate the results
    *                      to the client.
+   *          vMajor    - Requested PeerDist major version.
    *          pathname  - The pathname to be added to the queue.
    *
    *  Output: A <RecvErrs> error code.
    *
+   *  Notes:  This function, as written, does not accept a PeerDist minor
+   *          version number.  At the time of writing, the only PeerDist
+   *          defined PeerDist versions are 1.0 and 2.0.  It is not clear
+   *          how we would use the minor number.
+   *
    * ------------------------------------------------------------------------ **
    */
   {
@@ -671,9 +672,19 @@ static RecvErrs QueryPath( int outSock, char const *pathname )
       }
 
     /* We have mutex and a configuration entry.
-     *  Copy all of the config values so that we can release the mutex.
+     *  Look up the name of the matching cache file, based on PeerDist version.
+     *  Note:  We don't yet support PeerDistv2, so we don't test for it.
      */
-    tmpstr = pd_v1GenCacheName( pathname, entry->cacheDir );
+    switch( vMajor )
+      {
+      case 1:
+        tmpstr = pd_v1GenCacheName( pathname, entry->cacheDir );
+        break;
+      default:
+        tmpstr = NULL;
+      }
+
+    /* Did we map to a cachefile name?  */
     if( NULL == tmpstr )
       {
       (void)SendResponse( outSock, "ERROR: Queried file not found.\n" );
@@ -687,10 +698,91 @@ static RecvErrs QueryPath( int outSock, char const *pathname )
       }
     (void)pthread_mutex_unlock( &GlobalMutex );
     }
+
   return( result );
   } /* QueryPath */
 
 
+static char const *extractVersion( int vNumArray[], char const *src )
+  /* ------------------------------------------------------------------------ **
+   * Extract a version number from a QUERY request.
+   *
+   *  Input:  vNumArray - A pointer to an array of two integers.  The major
+   *                      and minor version numbers will be written into
+   *                      this array:
+   *                        vNumArray[0] == PeerDist Major Number
+   *                        vNumArray[1] == PeerDist Minor Number
+   *
+   *          src       - The source string from which to read the version
+   *                      number.  This should be beyond the
+   *
+   *  Output: A pointer to the position in the string following the version
+   *          information, if any.  If there is no version information in,
+   *          the string, the return value will be the same as <src>.
+   *
+   *  Notes:  This is an internal function, so it's not particularly
+   *          comprehensive.  It expects that the "QUERY " prefix of the
+   *          QUERY command has already been stripped off of the <src>
+   *          string.
+   *
+   *          The version number should be passed as:'
+   *            '[' <int> [ '.' <int> ] ']'
+   *          For example, "[2]" or "[1,0]".
+   *
+   * ------------------------------------------------------------------------ **
+   */
+  {
+  char const *c;
+  char       *endptr;
+  long int    tmp;
+
+  /* Initialize to default values.  */
+  vNumArray[0] = 1;
+  vNumArray[1] = 0;
+
+  /* Look for the square bracket, which indicates a version specifier.
+   *  Anything else will cause us to ignore the rest of the string.
+   */
+  while( ' ' == *src )  /* Should never happen, but eat spaces anyway.  */
+    src++;
+  if( '[' != *src )     /* Not an opening bracket?  */
+    return( src );
+
+  /* Looks good.  Let's try to parse out major and minor numbers. */
+  c = src + 1;
+  tmp = strtol( c, &endptr, 10 );
+  /* The major number must be 1 or greater.
+   *  strtol() returns zero on error, but we handle that the same way.
+   */
+  if( tmp > 0 )
+    {
+    c = endptr;           /* Move beyond the numeric string we've read. */
+    vNumArray[0] = tmp;
+    while( ' ' == *c )    /* Eat any erroneous spaces.  */
+      c++;
+    if( '.' == *c )       /* A dot indicates that a minor number exists.  */
+      {
+      /* Read the minor version number.
+       *  For the minor number, zero is the default.
+       */
+      c++;
+      tmp = strtol( c, &endptr, 10 );
+      c = endptr;
+      if( tmp > 0 )
+        vNumArray[1] = tmp;
+      }
+
+    /* Consume the closing bracket, and any additional spaces.  */
+    while( (' ' == *c) || (']' == *c) )
+      c++;
+    return( c );
+    }
+
+  /* No major number found, so return the (updated?) source pointer.  */
+  return( src );
+  } /* extractVersion */
+
+
 static RecvErrs ParseRequest( RecvBufr *Rb )
   /* ------------------------------------------------------------------------ **
    * Parse and respond to a client request.
@@ -711,9 +803,10 @@ static RecvErrs ParseRequest( RecvBufr *Rb )
    * ------------------------------------------------------------------------ **
    */
   {
-  char const *s;            /* General purpose string pointer.      */
-  Gstr        gsBufr[1];    /* A growable string to receive input.  */
-  RecvErrs    result;       /* Function call results.               */
+  char const *s;          /* General purpose string pointer.      */
+  Gstr        gsBufr[1];  /* A growable string to receive input.  */
+  RecvErrs    result;     /* Function call results.               */
+  int         vNum[2];    /* PeerDist major/minor version number. */
 
   /* Initialize the Gstr. */
   if( NULL == initGstr( gsBufr ) )
@@ -746,12 +839,18 @@ static RecvErrs ParseRequest( RecvBufr *Rb )
   else
     {
     if( 0 == strncasecmp( "QUERY ", s, 6 ) )
-      result = QueryPath( Rb->sock, &s[6] );
+      {
+      s = extractVersion( vNum, &s[6] );
+      result = QueryPath( Rb->sock, vNum[0], s );
+      }
     else
       {
       SendResponse( Rb->sock, "ERROR: Invalid request.\n" );
       if( Verbosity > 3 )
-        LockLog( "Error: Client sent invalid request: \"%s\".\n", s );
+        {
+        LockLog( "Error: Client sent invalid request: \"%s\".\n",
+                  strGstr( gsBufr ) );
+        }
       result = rv_invalid;
       }
     }