Beispiel #1
0
/**respond the cache to client
 * which contains BOTH the HTTP Response Header
 * AND the Response Body
 * i.e. the whole HTTP Response from the server
 */
int respondCache(char* URL, int client_sd)
{
  char filename[23];
  memset(filename, 0, sizeof(filename));
  hashURL(filename, URL);
  char filepath[50];
  memset(filepath, 0, sizeof(filepath));
  strcpy(filepath, cachePath);
  strcat(filepath, filename);

  char block[512];

  pthread_mutex_lock(&mutex);
  FILE* fp = fopen(filepath, "rb");
  if (fp == NULL) return -1;

  int readSize = 0;
  int totalSize = 0;
  do {
    memset(block, 0, sizeof(block));
    readSize = fread(block, 1, 512, fp);
    if (readSize > 0)
      if (send(client_sd, block, readSize, MSG_NOSIGNAL) <= 0)
        return -1;
    totalSize+=readSize;
  } while(readSize > 0);
  printf("%srespondCache(): Totally respond %d bytes back to client. %s\n", BG_GREEN, totalSize, DEFAULT);

  fclose(fp);
  pthread_mutex_unlock(&mutex);
  return 0;
}
Beispiel #2
0
/**If the file does not exist, return -1
 * Otherwise, return the raw long time of the Last Modified Time of this file
 */
time_t getFileModificationTime(char* URL)
{
  // First, hash the URL to filename
  char filename[23];
  memset(filename, 0, sizeof(filename));
  hashURL(filename, URL);

  // Then check if the file, whose name is filename, exists
  struct stat statbuf;
  int statReturnValue = stat(cachePath, &statbuf);
  if (statReturnValue == -1)
  {
    mkdir(cachePath, 0777);
    return -1;
  }

  char filepath[50];
  memset(filepath, 0, sizeof(filepath));
  strcpy(filepath, cachePath);
  strcat(filepath, filename);

  //debug
  printf("getFileModificationTime(): filepath is |%s%s%s|\n", BG_PURPLE, filepath, DEFAULT);

  memset(&statbuf, 0, sizeof(statbuf));
  statReturnValue = stat(filepath, &statbuf);
  if (statReturnValue == -1) // The file does not exist
    return -1;
  return statbuf.st_mtime;
}
Beispiel #3
0
inline unsigned int Find_longURLSerial(char * shortURL,int * found)
{
  *found = 0;
  if (loaded_links==0) { return 0; }

  unsigned long our_hash = hashURL(shortURL);
  int i=loaded_links-1;
  while ( i > 0 )
   {
     if (our_hash==links[i].shortURLHash)
          {
            *found = 1;
            return i;
          }
      --i;
   }

   if (our_hash==links[0].shortURLHash)
          {
            *found = 1;
            return 0;
          }

  return 0;
}
Beispiel #4
0
unsigned long Add_MyURL(char * longURL,char * shortURL,int saveit)
{
  int shortURL_AlreadyExists=0;
  Find_longURL(shortURL,&shortURL_AlreadyExists);
  if (shortURL_AlreadyExists) { return 0; }

  if (loaded_links>=MAX_LINKS) { return 0; }
  allocateLinksIfNeeded();

  unsigned int long_url_length = strlen(longURL);
  if (long_url_length>=MAX_LONG_URL_SIZE) { return 0; }
  unsigned int sort_url_length = strlen(shortURL);
  if (sort_url_length>=MAX_TO_SIZE) { return 0; }

  pthread_mutex_lock (&db_addIDLock); // LOCK PROTECTED OPERATION -------------------------------------------
  //it might not seem like it but here we are doing two seperate operations
  //first we give our_index the loaded_links value , and then we increment loaded_links
  //of course this is a potential race condition where two threads assign themselves the same link
  //and we have an empty record after that , solved using a lock protection
  unsigned int our_index=loaded_links++;
  pthread_mutex_unlock (&db_addIDLock); // LOCK PROTECTED OPERATION -------------------------------------------

  links[our_index].longURL = ( char * ) malloc (sizeof(char) * (long_url_length+1) );  //+1 for null termination
  if ( links[our_index].longURL == 0 ) { AmmServer_Warning("Could not allocate space for a new string \n "); return 0; }
  links[our_index].shortURL = ( char * ) malloc (sizeof(char) * (sort_url_length+1) ); //+1 for null termination
  if ( links[our_index].shortURL == 0 ) { AmmServer_Warning("Could not allocate space for a new string \n "); return 0; }

  links[our_index].shortURLHash=hashURL(shortURL);

  strncpy(links[our_index].longURL,longURL,long_url_length);
  links[our_index].longURL[long_url_length]=0;  // null terminator :P

  strncpy(links[our_index].shortURL,shortURL,sort_url_length);
  links[our_index].shortURL[sort_url_length]=0;  // null terminator :P

  if (saveit) { Append2MyURLDBFile(db_file,longURL,shortURL); }

  if ( REGROUP_AFTER_X_UNSORTED_LINKS <= loaded_links-sorted_links )
  {
      ResortDB(db_file,links,loaded_links);
  }

  return 1;
}
Beispiel #5
0
//Binary Search
inline unsigned int Find_longURL(char * shortURL,int * found)
{
  #if USE_BINARY_SEARCH
  *found = 0;
  if (shortURL==0) { return 0; }
  if (loaded_links==0) { return 0; }

  if (sorted_links!=0)
  {
   unsigned long our_hash = hashURL(shortURL);
   unsigned int binarySearchLastElement = sorted_links;
   unsigned int beg=0,mid=0,fin=binarySearchLastElement-1;
   while ( beg <= fin )
   {
     mid=(unsigned int) beg + ( (fin-beg)/2 );
     if (mid >= binarySearchLastElement)
        { AmmServer_Error("Binary Search overflowed ( beg %u mid %u fin %u ) , binarySearchLastElement %u \n",beg,mid,fin,binarySearchLastElement); break; } else
     if (our_hash<links[mid].shortURLHash) { fin=mid-1; } else
     if (our_hash>links[mid].shortURLHash) { beg=mid+1; } else
                                           {
                                             *found = 1;
                                             AmmServer_Success("Found %s using binary search\n",shortURL);
                                             return mid;
                                           }
   }
  }
  //TODO : Remove this message in the future -------------
  AmmServer_Warning("Binary Search couldn't find result , extending search to unsorted list\n");
  return Find_longURLSerial(shortURL,found);
  //----------------------------------------
  #else // USE_BINARY_SEARCH
   return Find_longURLSerial(shortURL,found);
  #endif

  return 0;
}
Beispiel #6
0
/** Simutaneously cache the whole server response
 *  and forward the response back to the client
 */
int cacheServerResponse(char* responseHeader, char* URL, int server_sd, int client_sd, int has_no_body)
{
  char responseHeaderCopy[MAX_RESPONSE_SIZE];
  strcpy(responseHeaderCopy, responseHeader);

  char filename[23];
  memset(filename, 0, sizeof(filename));
  hashURL(filename, URL);
  char filepath[50];
  memset(filepath, 0, sizeof(filepath));
  strcpy(filepath, cachePath);
  strcat(filepath, filename);

  // First write the header part of the response to cache file
  pthread_mutex_lock(&mutex);
  FILE* fp = fopen(filepath, "wb");
  int byteWritten = fwrite(responseHeaderCopy, 1, strlen(responseHeaderCopy), fp);
  if (byteWritten == 0)
    return -1; // fwrite error?

  // Then forward the header part to client
  if (send(client_sd, responseHeaderCopy, strlen(responseHeaderCopy), MSG_NOSIGNAL) <= 0)
    return -1;
  int totalSize = strlen(responseHeaderCopy);

  // Then if the response has body, continue to write the body part to cache
  // And forward it back to client at the same time
  if (!has_no_body)
  {
    char block[1024];
    // Read body from server block by block
    while(1)
    {
      memset(block, 0, sizeof(block));
      int readSize = read(server_sd, block, sizeof(block));

      //debug
      // printf("cacheServerResponse(): readSize is now: /%s%d%s/\n", BG_YELLOW, readSize, DEFAULT);

      if (readSize < 0) // read error?
        return -1;
      if (readSize == 0) // has read up the response body
        break;

      // Write the body block to cache
      fwrite(block, 1, readSize, fp);

      // Send the body block back to client
      if (send(client_sd, block, readSize, MSG_NOSIGNAL) <= 0)
        return -1;

      totalSize += readSize;
    }
  }

  printf("%scacheServerResponse(): Cached and forwarded %d bytes in total%s\n", BG_PURPLE, totalSize, DEFAULT);

  fclose(fp);
  pthread_mutex_unlock(&mutex);
  return 0;
}