예제 #1
0
Unicode
Unicode_ReplaceRange(ConstUnicode destination,       // IN
                     UnicodeIndex destinationStart,  // IN
                     UnicodeIndex destinationLength, // IN
                     ConstUnicode source,            // IN
                     UnicodeIndex sourceStart,       // IN
                     UnicodeIndex sourceLength)      // IN
{
   UnicodeIndex destNumCodeUnits;
   UnicodeIndex resultLength;
   char *result;

   UnicodePinIndices(destination, &destinationStart, &destinationLength);
   UnicodePinIndices(source, &sourceStart, &sourceLength);

   destNumCodeUnits = Unicode_LengthInCodeUnits(destination);

   resultLength = destNumCodeUnits - destinationLength + sourceLength;

   result = Util_SafeMalloc(resultLength + 1);

   // Start with the destination bytes before the substring to be replaced.
   memcpy(result,
          destination,
          destinationStart);

   // Insert the substring of source in place of the destination substring.
   memcpy(result + destinationStart,
          (const char *)source + sourceStart,
          sourceLength);

   // Append the remaining bytes of destination after the replaced substring.
   memcpy(result + destinationStart + sourceLength,
          (const char *)destination + destinationStart + destinationLength,
          destNumCodeUnits - destinationStart - destinationLength);

   result[resultLength] = '\0';

   return (Unicode)result;
}
void *
FileLockIntrinsic(ConstUnicode pathName,   // IN:
                  Bool exclusivity,        // IN:
                  uint32 msecMaxWaitTime,  // IN:
                  const char *payload,     // IN:
                  int *err)                // OUT:
{
   FILELOCK_FILE_HANDLE handle;
   LockValues myValues;

   Unicode lockDir = NULL;
   Unicode entryFilePath = NULL;
   Unicode memberFilePath = NULL;
   Unicode entryDirectory = NULL;

   ASSERT(pathName);
   ASSERT(err);

   /* Construct the locking directory path */
   lockDir = Unicode_Append(pathName, FILELOCK_SUFFIX);

   /* establish our values */

   myValues.machineID = (char *) FileLockGetMachineID(); // don't free this!
   myValues.executionID = FileLockGetExecutionID();      // free this!
   myValues.payload = (char *) payload;
   myValues.lockType = exclusivity ? LOCK_EXCLUSIVE : LOCK_SHARED;
   myValues.lamportNumber = 0;
   myValues.locationChecksum = FileLockLocationChecksum(lockDir); // free this!
   myValues.waitTime = 0;
   myValues.msecMaxWaitTime = msecMaxWaitTime;
   myValues.memberName = NULL;

   LOG(1, ("Requesting %s lock on %s (%s, %s, %u).\n",
       myValues.lockType, UTF8(pathName), myValues.machineID,
       myValues.executionID, myValues.msecMaxWaitTime));

   /*
    * Attempt to create the locking and entry directories; obtain the
    * entry and member path names.
    */

   *err = CreateEntryDirectory(myValues.machineID, myValues.executionID,
                               lockDir,
                               &entryDirectory, &entryFilePath,
                               &memberFilePath, &myValues.memberName);

   switch (*err) {
   case 0:
      break;

   case EROFS:
      /* FALL THROUGH */
   case EACCES:
      if (!exclusivity) {
         /*
          * Lock is for read/shared access however the lock directory could
          * not be created. Grant an implicit read lock whenever possible.
          * The address of a private variable will be used for the lock token.
          */

         Warning(LGPFX" %s implicit %s lock succeeded on '%s'.\n",
                 __FUNCTION__, LOCK_SHARED, UTF8(pathName));

         *err = 0;
         memberFilePath = &implicitReadToken;
      }

      /* FALL THROUGH */
   default:
      goto bail;
   }

   ASSERT(Unicode_LengthInCodeUnits(memberFilePath) -
          Unicode_LengthInCodeUnits(pathName) <= FILELOCK_OVERHEAD);

   /* Attempt to create the entry file */
   *err = FileLockOpenFile(entryFilePath, O_CREAT | O_WRONLY, &handle);

   if (*err != 0) {
      /* clean up */
      FileRemoveDirectoryRobust(entryDirectory);
      FileRemoveDirectoryRobust(lockDir);

      goto bail;
   }

   /* what is max(Number[1]... Number[all lockers])? */
   *err = Scanner(lockDir, NumberScan, &myValues, FALSE);

   if (*err != 0) {
      /* clean up */
      FileLockCloseFile(handle);
      FileDeletionRobust(entryFilePath, FALSE);
      FileRemoveDirectoryRobust(entryDirectory);
      FileRemoveDirectoryRobust(lockDir);

      goto bail;
   }

   /* Number[i] = 1 + max([Number[1]... Number[all lockers]) */
   myValues.lamportNumber++;

   /* Attempt to create the member file */
   *err = CreateMemberFile(handle, &myValues, entryFilePath, memberFilePath);

   /* Remove entry directory; it has done its job */
   FileRemoveDirectoryRobust(entryDirectory);

   if (*err != 0) {
      /* clean up */
      FileDeletionRobust(entryFilePath, FALSE);
      FileDeletionRobust(memberFilePath, FALSE);
      FileRemoveDirectoryRobust(lockDir);

      goto bail;
   }

   /* Attempt to acquire the lock */
   *err = Scanner(lockDir, WaitForPossession, &myValues, TRUE);

   switch (*err) {
   case 0:
      break;

   case EAGAIN:
      /* clean up */
      FileDeletionRobust(memberFilePath, FALSE);
      FileRemoveDirectoryRobust(lockDir);

      /* FALL THROUGH */
   default:
      break;
   }

bail:

   Unicode_Free(lockDir);
   Unicode_Free(entryDirectory);
   Unicode_Free(entryFilePath);
   Unicode_Free(myValues.memberName);
   free(myValues.locationChecksum);
   free(myValues.executionID);

   if (*err != 0) {
      Unicode_Free(memberFilePath);
      memberFilePath = NULL;

      if (*err == EAGAIN) {
         *err = 0; // lock not acquired
      }
   }

   return (void *) memberFilePath;
}