コード例 #1
0
    long long MmapV1ExtentManager::fileSize() const {
        long long size = 0;
        for (int n = 0; boost::filesystem::exists(_fileName(n)); n++) {
            size += boost::filesystem::file_size(_fileName(n));
        }

        return size;
    }
コード例 #2
0
    DataFile* MmapV1ExtentManager::_addAFile(OperationContext* txn,
                                             int sizeNeeded,
                                             bool preallocateNextFile) {

        // Database must be stable and we need to be in some sort of an update operation in order
        // to add a new file.
        invariant(txn->lockState()->isDbLockedForMode(_dbname, MODE_IX));

        const int allocFileId = _files.size();

        int minSize = 0;
        if (allocFileId > 0) {
            // Make the next file at least as large as the previous
            minSize = _files[allocFileId - 1]->getHeader()->fileLength;
        }

        if (minSize < sizeNeeded + DataFileHeader::HeaderSize) {
            minSize = sizeNeeded + DataFileHeader::HeaderSize;
        }

        {
            unique_ptr<DataFile> allocFile(new DataFile(allocFileId));
            const string allocFileName = _fileName(allocFileId).string();

            Timer t;

            allocFile->open(txn, allocFileName.c_str(), minSize, false);
            if (t.seconds() > 1) {
                log() << "MmapV1ExtentManager took "
                      << t.seconds()
                      << " seconds to open: "
                      << allocFileName;
            }

            // It's all good
            _files.push_back(allocFile.release());
        }

        // Preallocate is asynchronous
        if (preallocateNextFile) {
            unique_ptr<DataFile> nextFile(new DataFile(allocFileId + 1));
            const string nextFileName = _fileName(allocFileId + 1).string();

            nextFile->open(txn, nextFileName.c_str(), minSize, false);
        }

        // Returns the last file added
        return _files[allocFileId];
    }
コード例 #3
0
    Status MmapV1ExtentManager::init(OperationContext* txn) {
        invariant(_files.empty());

        for (int n = 0; n < DiskLoc::MaxFiles; n++) {
            const boost::filesystem::path fullName = _fileName(n);
            if (!boost::filesystem::exists(fullName)) {
                break;
            }

            const std::string fullNameString = fullName.string();

            {
                // If the file is uninitialized we exit the loop because it is just prealloced. We
                // do this on a bare File object rather than using the DataFile because closing a
                // DataFile triggers dur::closingFileNotification() which is fatal if there are any
                // pending writes. Therefore we must only open files that we know we want to keep.
                File preview;
                preview.open(fullNameString.c_str(), /*readOnly*/ true);
                invariant(preview.is_open());

                // File can't be initialized if too small.
                if (preview.len() < sizeof(DataFileHeader)) {
                    break;
                }

                // This is the equivalent of DataFileHeader::uninitialized().
                int version;
                preview.read(0, reinterpret_cast<char*>(&version), sizeof(version));
                invariant(!preview.bad());
                if (version == 0) {
                    break;
                }
            }

            unique_ptr<DataFile> df(new DataFile(n));

            Status s = df->openExisting(fullNameString.c_str());
            if (!s.isOK()) {
                return s;
            }

            invariant(!df->getHeader()->uninitialized());

            // We only checkUpgrade on files that we are keeping, not preallocs.
            df->getHeader()->checkUpgrade(txn);

            _files.push_back( df.release() );
        }

        // If this is a new database being created, instantiate the first file and one extent so
        // we can have a coherent database.
        if (_files.empty()) {
            WriteUnitOfWork wuow(txn);
            _createExtent(txn, initialSize(128), false);
            wuow.commit();

            // Commit the journal and all changes to disk so that even if exceptions occur during
            // subsequent initialization, we won't have uncommited changes during file close.
            getDur().commitNow(txn);
        }

        return Status::OK();
    }
コード例 #4
0
ファイル: SharedMemory.cpp プロジェクト: jfriesne/muscle
status_t SharedMemory :: SetArea(const char * keyString, uint32 createSize, bool returnLocked)
{
   UnsetArea();  // make sure everything is deallocated to start with

#if defined(MUSCLE_FAKE_SHARED_MEMORY)
   if (createSize > 0)
   {
      _area = muscleAlloc(createSize);
      if (_area) 
      {
         memset(_area, 0, createSize);
         _areaName         = keyString;
         _areaSize         = createSize; 
         _isCreatedLocally = true;
         _isLocked         = returnLocked;
         _isLockedReadOnly = false;
         return B_NO_ERROR;
      }
      else WARN_OUT_OF_MEMORY;   
   }
#elif defined(WIN32)
   char buf[64];
   if (keyString == NULL)
   {
      muscleSprintf(buf, INT32_FORMAT_SPEC, GetTickCount());  // No user-supplied name?  We'll pick an arbitrary name then
      keyString = buf;
   }
   _areaName = keyString;

   // For windows we only use a Mutex, because even a Windows semaphore isn't enough to
   // do shared read locking.  When I figure out how to do interprocess shared read locking
   // under Windows I will implement that, but for now it's always exclusive-locking.  :^(
   _mutex = CreateMutexA(NULL, true, (_areaName+"__mutex")());
   if (_mutex != NULL)
   {
      bool ok = true;
      if (GetLastError() == ERROR_ALREADY_EXISTS) ok = (LockAreaReadWrite() == B_NO_ERROR);
      else
      {
         // We created it in our CreateMutex() call, and it's already locked for us
         _isLocked = true;
         _isLockedReadOnly = false;
      }
      if (ok)
      {
         char buf[MAX_PATH];
         if (GetTempPathA(sizeof(buf), buf) > 0)
         {
            _fileName = _areaName.Prepend(buf)+"__file";
            _file = CreateFileA(_fileName(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH|FILE_FLAG_RANDOM_ACCESS, NULL);
            if (_file != INVALID_HANDLE_VALUE)
            {
               _isCreatedLocally = (GetLastError() != ERROR_ALREADY_EXISTS);
               if (createSize == 0) createSize = GetFileSize(_file, NULL);
               _areaSize = createSize;  // assume the file will be resized automagically for us
               if (_areaSize > 0)
               {
                  _map = CreateFileMappingA(_file, NULL, PAGE_READWRITE, 0, createSize, (_areaName+"__map")());
                  if (_map)
                  {
                     _area = MapViewOfFile(_map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
                     if (_area)
                     {
                        if (returnLocked == false) UnlockArea();
                        return B_NO_ERROR;
                     }
                  }
               }
            }
         }
      }
   }
#else
   key_t requestedKey = IPC_PRIVATE;
   if (keyString)
   {
      requestedKey = (key_t) CalculateHashCode(keyString, (uint32)strlen(keyString));
      if (requestedKey == IPC_PRIVATE) requestedKey++;
      _areaName = keyString;
   }

   DECLARE_SEMCTL_ARG(semopts);
   const int permissionBits = 0777;

   // Try to create a new semaphore to control access to our area
   _semID = semget(requestedKey, 1, IPC_CREAT|IPC_EXCL|permissionBits);
   if (_semID >= 0)
   {
      // race condition here!?
      semopts.val = LARGEST_SEMAPHORE_DELTA;
      if (semctl(_semID, 0, SETVAL, semopts) < 0) _semID = -1; // oops!
   }
   else _semID = semget(requestedKey, 1, permissionBits);  // Couldn't create?  then get the existing one

   if (_semID >= 0)
   {
      _key = requestedKey;

      // If we requested a private key, we still need to know the actual key value
      if (_key == IPC_PRIVATE)
      {
         struct semid_ds semInfo = {};  // the braces zero-initialize the struct for us, to keep clang++SA happy
         semopts.buf = &semInfo;
         if (semctl(_semID, 0, IPC_STAT, semopts) == 0) 
         {
# ifdef __linux__
            _key = semInfo.sem_perm.__key;

// Mac os-x leopard uses '_key' by default. Both Tiger and Leopard may use _key if the following condition is true, otherwise they use 'key'.
# elif (defined(__APPLE__) && (defined(__POSIX_C_SOURCE) || defined(__LP64__))) || __DARWIN_UNIX03
            _key = semInfo.sem_perm._key;
# else
            _key = semInfo.sem_perm.key;
# endif
         }
         _areaName = "private";  // sorry, it's the best I can do short of figuring out how to invert the hash function!
      }

      if ((_key != IPC_PRIVATE)&&(LockAreaReadWrite() == B_NO_ERROR))
      {
         _areaID = shmget(_key, 0, permissionBits);
         if ((_areaID < 0)&&(createSize > 0)) 
         {
            _areaID = shmget(_key, createSize, IPC_CREAT|IPC_EXCL|permissionBits);
            _isCreatedLocally = true;
         }
         if (_areaID >= 0)
         {
            _area = shmat(_areaID, NULL, 0);
            if ((_area)&&(_area != ((void *)-1)))  // FogBugz #7294
            {
               // Now get the stats on our area
               struct shmid_ds buf;
               if (shmctl(_areaID, IPC_STAT, &buf) == 0)
               {
                  _areaSize = (uint32) buf.shm_segsz;
                  if (returnLocked == false) UnlockArea();
                  return B_NO_ERROR;
               }
            }
         }
      }
   }
#endif

   UnsetArea();  // oops, roll back everything!
   return B_ERROR;
}