简体   繁体   English

C ++和PHP之间的文件锁定

[英]File locking between C++ and PHP

I'm creating a somewhat silly but effective way to create jobs in PHP, that C++ then picks up. 我正在创建一种有点愚蠢但有效的方法来在PHP中创建作业,然后C ++开始使用。 The job files created by PHP are simply text files that C++ reads out line by line, adding each line to a vector. PHP创建的作业文件是简单的文本文件,C ++逐行读取该文件,并将每一行添加到向量中。

Folders: 资料夹:

  1. "jobs" -> New job files end up in here “工作”->新的工作文件在这里结束
  2. "jobhold" -> Job files are moved here once C++ starts working on them. 一旦C ++开始对其进行处理,“ jobhold”->作业文件就会移到此处。
  3. "jobstime" -> Holds files with a name identical to the jobfile, containing EPOCH time so I can check how much time passed since last we did this job. “ jobstime”->保存的文件名称与jobfile相同,包含EPOCH时间,因此我可以检查自上次执行此操作以来经过了多少时间。

The problem: PHP assumes a file isn't being handled by C++ while it's in "jobhold" but C++ really only moved it there to prevent the job from being executed twice (as shown below). 问题:PHP假定文件不在“作业保持”中,但C ++并未处理该文件,但C ++实际上仅将其移至该位置以防止作业执行两次(如下所示)。 C++ still needs to read the file to put it's contents in a vector, so I need to prevent PHP from accessing this file while this happens. C ++仍然需要读取文件以将其内容放入向量中,因此在发生这种情况时,我需要防止PHP访问此文件。

Also, I need to disallow C++ from handling a job file in the "jobhold" folder while it's being edited by PHP. 另外,我需要禁止C ++在PHP编辑“ jobhold”文件夹中的作业文件时对其进行处理。

The C++ function that checks if enough time has passed since we last did this job : C ++函数,用于检查自上次完成此工作以来是否经过了足够的时间

  1. Open the jobstime file and determine if X seconds have passed since last we did this job 打开Jobstime文件,确定自上次执行此作业以来是否已过去X秒
  2. IF enough time passed: 如果经过了足够的时间:
  3. move jobfile from "jobhold" to "jobs" so the next function creates a thread for it that executes the job. 将Jobfile从“ jobhold”移动到“ jobs”,因此下一个函数为其创建一个线程来执行该作业。
  4. remove corresponding time file from "jobstime", it will be recreated in the thread, which is created in the next function. 从“ jobstime”中删除相应的时间文件,它将在线程中重新创建,该线程在下一个函数中创建。

-> I need to cancel these 2 steps (3 & 4) if PHP has a lock on the file . -> 如果PHP对该文件具有锁定,则需要取消这两个步骤(3和4) Which would mean the file is completely ignored until PHP is done with it. 这意味着文件将被完全忽略,直到PHP完成它为止。

The C++ function that handles the files in the "jobs" folder : 处理“ jobs”文件夹中文件的C ++函数:

  1. Moves the jobfile from "jobs" back to "jobhold", this prevents the thread from being created twice. 将作业文件从“作业”移回“作业保持”,这可以防止线程被创建两次。
  2. Creates time file in "jobstime" containign the current time (EPOCH) 在“ jobstime” containign中创建当前时间的时间文件(EPOCH)
  3. Creates new thread that's going to handle the file (just passes the filename to the new thread so it knows which file to handle) 创建将要处理文件的新线程(只需将文件名传递给新线程,以便知道要处理的文件)

-> I need to make sure PHP can't handle the file yet, even though it's in "jobhold" . -> 我需要确保PHP仍无法处理该文件,即使该文件位于“ jobhold”中也是如此 C++ needs to immediately lock it (after, during, before? ) so there is no chance whatsoever that PHP can pick the file up, and not release it until somewhere inside the thread. C ++需要立即锁定它(之后,期间, 之前? ),因此PHP绝不可能拾取该文件,并且直到线程内的某个地方才释放它。

C++ Thread that handles the jobfile: 处理作业文件的C ++线程:

  1. The jobfile (which is currently in the "jobhold" folder) is read out, and each line is added to a vector created by the thread. 读取作业文件(当前位于“ jobhold”文件夹中),并将每一行添加到该线程创建的向量中。

-> After this step, the file lock can be released , at which point PHP can lock the file so C++ won't handle it anymore. -> 在此步骤之后,可以释放文件锁定 ,这时PHP可以锁定文件,因此C ++将不再处理该文件。

PHP (currently only checks if the file in "jobhold" exists ): PHP (当前仅检查“ jobhold”中的文件是否存在 ):

<?php
if(isset($_GET['edit'])) 
{
    $filename = $startdir.'jobhold/'.$_GET['edit'];
    while (!file_exists($filename)) 
    {
        while(file_exists($startdir.'jobs/'.$_GET['edit']))
        {
            //Wait until C++ moves the file from "jobs" to "jobhold" by doing nothing
        }

        if(file_exists(filename)
        {
            break 1; //The file exists now, we may break the while.
        }

        //If we reached this point, the job simply doesn't exist.. so die.
        echo "The job $_GET[edit] doesn't exist. <br /><br />";
        die();
    }
}
/* Other code here, such as HTML form so user can edit the txt file */
?>

-> Need to add another check in PHP that checks if C++ has a lock on the jobfile in "jobhold". ->需要在PHP中添加另一项检查,以检查C ++是否在“ jobhold”中的作业文件上锁定了锁定。 If yes, wait until the lock is removed and then immediately lock the file so C++ can't handle it anymore. 如果是,请等到锁定被删除后再立即锁定文件,以使C ++无法再处理该文件。 Like so (silly example): 像这样(愚蠢的例子):

<?php
    while(file_locked_by_c++($startdir.'jobshold/'.$_GET['edit']))
    {
        //Wait until C++ releases the file by doing nothing
    }
    /* Lock file NOW */
?>

I did find this thread , and although I don't mind using C in my C++ code, I didn't manage to figure out how to apply that questions answer to my situation without a proper example. 我确实找到了这个线程 ,尽管我不介意在C ++代码中使用C,但是如果没有适当的例子,我也没有设法弄清楚如何将这些问题应用于我的情况。

PS : The reason I'm not posting any actual C++ code is because I'd get flamed for the (sometimes messy but mostly redundant) way I code because I'm new to C++, and that would just confuse other newbies and/or take away from what I'm trying to achieve here. PS :之所以没有发布任何实际的C ++代码,是因为我对C ++的使用(有时是凌乱但大多是多余的)方式感到恼火,因为我是C ++的新手,这只会使其他新手和/或混淆摆脱我在这里想要实现的目标。

If you insist on seeing some code, that's fine, but please don't mention the mess / redundancy because I already know , they're just cheap workarounds that I will "fix" in a later stage. 如果您坚持要看一些代码,那很好,但是请不要提及混乱/冗余,因为我已经知道了 ,它们只是便宜的解决方法,我在以后的阶段中进行“修复”。 And if you're a newbie, make sure not to copy these mistakes. 如果您是新手,请确保不要复制这些错误。

pastebin 糊盒

Sorry for such a long post for something so simple, but I need to get this 100% right or the entire application may break. 抱歉,这么长的篇幅太简单了,但我需要100%正确,否则整个应用程序可能会崩溃。

UPDATE: 更新:

I am currently doing this: 我目前正在这样做:

Added a new folder called "lock" which will contain files like php-jobnameX.txt and c-jobnameX.txt where jobnameX is the name of the current job. 添加了一个名为“ lock”的新文件夹,其中将包含php-jobnameX.txtc-jobnameX.txt ,其中jobnameX是当前作业的名称。

C++: C ++:

-. - When C++ checks if enough time has passed since last we did the jobfile in "jobhold", prior to moving the file from "jobhold" to "jobs" it first checks if php has created a file in "lock". 当C ++检查自上次以来是否经过了足够的时间时,我们在“ jobhold”中执行了jobfile,在将文件从“ jobhold”移至“ jobs”之前,它首先检查php是否已在“ lock”中创建了文件。 If it did, we skip the file. 如果是这样,我们将跳过文件。

//This function will check if PHP has created a lock-file
bool checkifphplock(char* filename)
{
    ifstream fin(filename);
    if (fin)
    {
       fin.close();
       return true;
    }
    return false;
}

int cont = 1;
if(checkifphplock(phplockfile))
{
    cont = 0; //php lock found, so we go byebye
}

if(cont == 1)
{
  /* Keep doing stuff */
}

-. - When php starts working on the jobfiles in "jobs", prior to moving the jobfile from "jobs" back to "jobhold", it creates a lock file in "lock" to notify php it's still working on the file. 当php开始在“作业”中的作业文件上工作时,在将作业文件从“作业”移回“作业持有”之前,它将在“锁”中创建一个锁定文件以通知php它仍在处理该文件。

ofstream myfileclock;
myfileclock.open (clockfile, fstream::in | fstream::out | fstream::app);
myfileclock << " ";
myfileclock.close();

-. - Once the c++ thread is done copying the file contents to a vector, the lock file is removed to notify PHP it's ready to be edited again. 一旦c ++线程完成了将文件内容复制到向量中,锁定文件将被删除以通知PHP它准备好再次进行编辑。

system("rm /path/to/program/lock/c-jobnameX.txt");

PHP: PHP:

-. - Upon edit, obtain lock immediately by creating a file in "lock". 编辑后,通过在“ lock”中创建文件来立即获得锁定。

//Obtain lock immediately:
$file = $startdir."lock/php-$_GET[edit]";
if(!is_file($file)){ file_put_contents_atomic($file," "); chmod($file,0777);} //Make file if there is none
if(!is_writable($file)){chmod($file.'/',0777);} //Chmod file if not writable
if(!is_writable($file)){die("File \"$file\" not writable.");} //Die if not writable

-. - After obtaining the lock, double check if c++ doesn't have a lock file as well (in case both C++ and PHP requested the jobfile at the exact same time) 获取锁定后,再次检查c ++是否也没有锁定文件(以防C ++和PHP都在同一时间请求了作业文件)

while (file_exists($startdir."lock/c-$_GET[edit]")) 
{
    //Do nothing while c/c++ has a lock
}

-. - In case c++ already moved the file from "jobhold" to "jobs", we wait until it's moved back. 如果c ++已将文件从“ jobhold”移到“ jobs”,我们将等到文件移回。

//Wait for filename to exist in jobhold. Or die if it doesn't exist in any folder.
$filename = $startdir.'jobhold/'.$_GET['edit'];
while (!file_exists($filename)) 
{
    while(file_exists($startdir.'jobs/'.$_GET['edit']))
    {
        //Wait until C++ moves the file from "jobs" to "jobhold" by doing nothing
    }

    if(file_exists($filename))
    {
        break 1; //The file exists now, we may break the while.
    }

    //If we reached this point, the job simply doesn't exist.. so die.
    echo "The job $_GET[edit] doesn't exist. <br /><br />";
    unlink($file); //Remove lock for this non-existing job
    die();
}
/* Continue creating form to edit the file etc. */

Technically that last step should never be possible because the file can't (shouldn't) be in "jobs" if C/C++ doesn't have a lock, but it doesn't hurt to check. 从技术上讲,最后一步永远是不可能的,因为如果C / C ++没有锁,则文件不能(不应该)处于“作业”中,但是检查不会受到损害。

Will doing this make 100% sure PHP and C/C++ can't both handle the file at the same time? 这样是否可以100%确保PHP和C / C ++不能同时处理文件?

An extremely simple method of file locking is to have a line at the top of the files which reads locked or what ever you like. 一种非常简单的文件锁定方法是在文件顶部有一行,显示读取的锁定内容或您喜欢的内容。 Each piece of code checks to see if that line is there before doing anything. 在执行任何操作之前,每段代码都会检查该行是否存在。 The first and last action on the file is to lock/unlock the file by adding the word locked. 文件的第一个也是最后一个动作是通过添加“已锁定”一词来锁定/解锁文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM