예제 #1
0
파일: scan.c 프로젝트: irrdnet/irrd
/* Write to disk the current serial value for DB (db->name).
 *
 * Function was rewritten to return a value to indicate if
 * there were any errors in writing the serial value and also
 * to avoid buffering issues.  This is part of our support for 
 * atomic transactions.
 *
 * Note: Later we should write the current serial value as the
 * first line in the DB in a fixed field.  The original choice to
 * have a seperate current serial file was (IMHO) a poor choice.
 *
 * Input:
 *  -pointer to the DB struct so we know the name of the DB 
 *   and the current serial value to write to disk (db)
 *
 * Return:
 *  -1 if the current serial value was written to disk without error.
 *  -0 otherwise.
 */
int write_irr_serial (irr_database_t *db) {
  int ret_code = 0;
  char dbname[BUFSIZE], file[BUFSIZE], serial[20];
  int fd;

  /* make the current serial file name */
  strcpy (dbname, db->name);
  convert_toupper (dbname);
  sprintf (file, "%s/%s.CURRENTSERIAL", IRR.database_dir, dbname);

  /* now write the current serial to file */
  if ((fd = open (file, O_WRONLY|O_TRUNC|O_CREAT, 0644)) >= 0) {
    sprintf (serial, "%u", db->serial_number);
    if (write (fd, serial, strlen (serial)) > 0)  {
      SetStatusString (IRR.statusfile, dbname, "currentserial", serial);
      ret_code = 1;
    } else
      trace (ERROR, default_trace, "write_irr_serial (): file write error: (%s)\n",
	     strerror (errno));

    close (fd);
  }
  else
    trace (ERROR, default_trace, "write_irr_serial (): file open error: (%s)\n",
	   strerror (errno));

  return ret_code;
}
예제 #2
0
void Defragment::Stop (void)
{
    Lock ();
    SetStatusString (L"Stopping ...");
    PleaseStop = true;
    Unlock ();

    return;
}
예제 #3
0
void Defragment::TogglePause (void)
{
    Lock ();
    SetStatusString (L"Pausing ...");
    PleasePause = true;
    Unlock ();

    return;
}
예제 #4
0
Defragment::Defragment (wstring Name, DefragType DefragMethod)
{
    Method = DefragMethod;
    DoLimitLength = true;
    Error = false;
    Done = false;
    PleaseStop = false;
    PleasePause = false;
    DriveName = Name;
    StatusPercent = 0.0f;
    LastBMPUpdate = GetTickCount ();

    SetStatusString (L"Opening volume " + Name);
    if (!Volume.Open (Name))
    {
        SetStatusString (L"Error opening volume " + Name);
        Error = true;
        Done = true;
        StatusPercent = 100.0f;
    }

    return;
}
예제 #5
0
Defragment::~Defragment ()
{
    if (!IsDoneYet ())
    {
        Stop ();
        while (!IsDoneYet()  &&  !HasError())
        {
            SetStatusString (L"Waiting for thread to stop ...");
            Sleep (150);
        }
    }

    Volume.Close ();
    return;
}
예제 #6
0
파일: scan.c 프로젝트: irrdnet/irrd
void write_irr_serial_export (uint32_t serial, irr_database_t *database) {
  char db[BUFSIZE], file[BUFSIZE], serial_out[20];
  FILE *fp;

  if (database->export_filename != NULL) 
    strcpy (db, database->export_filename);
  else
    strcpy (db, database->name);
  convert_toupper(db);

  sprintf (file, "%s/%s.CURRENTSERIAL", IRR.ftp_dir, db);
  if ((fp = fopen (file, "w")) != NULL) {
    sprintf (serial_out, "%u", serial);
    fwrite (serial_out, 1, strlen (serial_out), fp);
    fclose (fp);
  }
  SetStatusString (IRR.statusfile, db, "lastexport", serial_out);
}
예제 #7
0
void Defragment::Start (void)
{
    uint32 i;
    uint64 FirstFreeLCN;
    uint64 TotalClusters;
    uint64 ClustersProgress;
    wchar_t PrintName[80];
    int Width = 70;

    if (Error)
        goto DoneDefrag;

    // First thing: build a file list.
    SetStatusString (L"Getting volume bitmap");
    if (!Volume.GetBitmap())
    {
        SetStatusString (L"Could not get volume " + DriveName + L" bitmap");
        Error = true;
        goto DoneDefrag;
    }

    LastBMPUpdate = GetTickCount ();

    if (PleaseStop)
        goto DoneDefrag;

    SetStatusString (L"Obtaining volume geometry");
    if (!Volume.ObtainInfo ())
    {
        SetStatusString (L"Could not obtain volume " + DriveName + L" geometry");
        Error = true;
        goto DoneDefrag;
    }

    if (PleaseStop)
        goto DoneDefrag;

    SetStatusString (L"Building file database for volume " + DriveName);
    if (!Volume.BuildFileList (PleaseStop, StatusPercent))
    {
        SetStatusString (L"Could not build file database for volume " + DriveName);
        Error = true;
        goto DoneDefrag;
    }

    if (PleaseStop)
        goto DoneDefrag;

    SetStatusString (L"Analyzing database for " + DriveName);
    TotalClusters = 0;
    for (i = 0; i < Volume.GetDBFileCount(); i++)
    {
        TotalClusters += Volume.GetDBFile(i).Clusters;
    }

    // Defragment!
    ClustersProgress = 0;

    // Find first free LCN for speedier searches ...
    Volume.FindFreeRange (0, 1, FirstFreeLCN);

    if (PleaseStop)
        goto DoneDefrag;

    // Analyze?
    if (Method == DefragAnalyze)
    {
        uint32 j;

        Report.RootPath = Volume.GetRootPath ();

        Report.FraggedFiles.clear ();
        Report.UnfraggedFiles.clear ();
        Report.UnmovableFiles.clear ();

        Report.FilesCount = Volume.GetDBFileCount () - Volume.GetDBDirCount ();
        Report.DirsCount = Volume.GetDBDirCount ();
        Report.DiskSizeBytes = Volume.GetVolumeInfo().TotalBytes;

        Report.FilesSizeClusters = 0;
        Report.FilesSlackBytes = 0;
        Report.FilesSizeBytes = 0;
        Report.FilesFragments = 0;

        for (j = 0; j < Volume.GetDBFileCount(); j++)
        {
            FileInfo Info;

            Info = Volume.GetDBFile (j);

            Report.FilesFragments += max ((size_t)1, Info.Fragments.size()); // add 1 fragment even for 0 bytes/0 cluster files

            if (Info.Attributes.Process == 0)
                continue;

            SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name);

            Report.FilesSizeClusters += Info.Clusters;
            Report.FilesSizeBytes += Info.Size;

            if (Info.Attributes.Unmovable == 1)
                Report.UnmovableFiles.push_back (j);

            if (Info.Fragments.size() > 1)
                Report.FraggedFiles.push_back (j);
            else
                Report.UnfraggedFiles.push_back (j);

            StatusPercent = ((double)j / (double)Report.FilesCount) * 100.0f;
        }

        Report.FilesSizeOnDisk = Report.FilesSizeClusters * (uint64)Volume.GetVolumeInfo().ClusterSize;
        Report.FilesSlackBytes = Report.FilesSizeOnDisk - Report.FilesSizeBytes;
        Report.AverageFragments = (double)Report.FilesFragments / (double)Report.FilesCount;
        Report.PercentFragged = 100.0f * ((double)(signed)Report.FraggedFiles.size() / (double)(signed)Report.FilesCount);

        uint64 Percent;
        Percent = (10000 * Report.FilesSlackBytes) / Report.FilesSizeOnDisk;
        Report.PercentSlack = (double)(signed)Percent / 100.0f;
    }
    else
        // Go through all the files and ... defragment them!
        for (i = 0; i < Volume.GetDBFileCount(); i++)
        {
            FileInfo Info;
            bool Result;
            uint64 TargetLCN;
            uint64 PreviousClusters;

            // What? They want us to pause? Oh ok.
            if (PleasePause)
            {
                SetStatusString (L"Paused");
                PleasePause = false;

                while (PleasePause == false)
                {
                    Sleep (50);
                }

                PleasePause = false;
            }

            if (PleaseStop)
            {
                SetStatusString (L"Stopping");
                break;
            }

            //
            Info = Volume.GetDBFile (i);

            PreviousClusters = ClustersProgress;
            ClustersProgress += Info.Clusters;

            if (Info.Attributes.Process == 0)
                continue;

            if (!DoLimitLength)
                SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name);
            else
            {
                FitName (PrintName, Volume.GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str(), Width);
                SetStatusString (PrintName);
            }

            // Calculate percentage complete
            StatusPercent = 100.0f * double((double)PreviousClusters / (double)TotalClusters);

            // Can't defrag directories yet
            if (Info.Attributes.Directory == 1)
                continue;

            // Can't defrag 0 byte files :)
            if (Info.Fragments.empty())
                continue;

            // If doing fast defrag, skip non-fragmented files
            // Note: This assumes that the extents stored in Info.Fragments
            //       are consolidated. I.e. we assume it is NOT the case that
            //       two extents account for a sequential range of (non-
            //       fragmented) clusters.
            if (Info.Fragments.size() == 1  &&  Method == DefragFast)
                continue;

            // Otherwise, defrag0rize it!
            int Retry = 3;  // retry a few times
            while (Retry > 0)
            {
                // Find a place that can fit the file
                Result = Volume.FindFreeRange (FirstFreeLCN, Info.Clusters, TargetLCN);

                // If yes, try moving it
                if (Result)
                {
                    // If we're doing an extensive defrag and the file is already defragmented
                    // and if its new location would be after its current location, don't
                    // move it.
                    if (Method == DefragExtensive  &&  Info.Fragments.size() == 1  &&
                            TargetLCN > Info.Fragments[0].StartLCN)
                    {
                        Retry = 1;
                    }
                    else
                    {
                        if (Volume.MoveFileDumb (i, TargetLCN))
                        {
                            Retry = 1; // yay, all done with this file.
                            Volume.FindFreeRange (0, 1, FirstFreeLCN);
                        }
                    }
                }

                // New: Only update bitmap if it's older than 15 seconds
                if ((GetTickCount() - LastBMPUpdate) < 15000)
                    Retry = 1;
                else if (!Result  ||  Retry != 1)
                {   // hmm. Wait for a moment, then update the drive bitmap
                    //SetStatusString (L"(Reobtaining volume " + DriveName + L" bitmap)");

                    if (!DoLimitLength)
                    {
                        SetStatusString (GetStatusString() + wstring (L" ."));
                    }

                    if (Volume.GetBitmap ())
                    {
                        LastBMPUpdate = GetTickCount ();

                        if (!DoLimitLength)
                            SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name);
                        else
                            SetStatusString (PrintName);

                        Volume.FindFreeRange (0, 1, FirstFreeLCN);
                    }
                    else
                    {
                        SetStatusString (L"Could not re-obtain volume " + DriveName + L" bitmap");
                        Error = true;
                    }
                }

                Retry--;
            }

            if (Error == true)
                break;
        }

DoneDefrag:
    wstring OldStatus;

    OldStatus = GetStatusString ();
    StatusPercent = 99.999999f;
    SetStatusString (L"Closing volume " + DriveName);
    Volume.Close ();
    StatusPercent = 100.0f;

    // If there was an error then the wstring has already been set
    if (Error)
        SetStatusString (OldStatus);
    else if (PleaseStop)
        SetStatusString (L"Volume " + DriveName + L" defragmentation was stopped");
    else
        SetStatusString (L"Finished defragmenting " + DriveName);

    Done = true;

    return;
}