PHP extension and Embedding--resource data type 2

Source: Internet
Author: User
Tags copy key variables requires resource return socket thread
Complex data types stored in resource variables typically require some memory allocations, CPU time, or network traffic when initializing. However, keeping the resource similar to the database connection between requests must be sustained. The sustainability of resources is a factor that must be taken into account.
first look at the memory allocation problem:When using PHP, the bias is to use emalloc because it is a malloc version with recycled. However, persistent resources must exist between requests. For a resource for a file handle class, if you want to add a requirement for a stored file name, you must include the following code in the header file:
typedef struct _PHP_SAMPLE_DESCRIPTOR_DATA {
    char *filename;
    FILE *fp;
} Php_sample_descriptor_data;
Using this structure, you can store file name and file handle resources so that you can share them among different requests.
Corresponding, to make the appropriate changes in the source file:
The static void Php_sample_descriptor_dtor (//) is a callback function for resource reclamation, defined at the initialization of the resource.
                    zend_rsrc_list_entry *rsrc tsrmls_dc)
{
    Php_sample_descriptor_data *fdata =
                (php_sample_descriptor_data*) rsrc->ptr;
    Fclose (FDATA->FP);
    Efree (fdata->filename);
    Efree (Fdata);
}
This static function is used to recycle resources and requires a specified callback when the resource is initialized.
The modified file opening function requires increased operations to allocate space to the resource:
Php_function (Sample_fopen)//modified fopen {php_sample_descriptor_data *fdata;
    FILE *FP;
    Char *filename, *mode;
    int Filename_len, Mode_len;
                        if (Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SS", &filename, &filename_len,
    &mode, &mode_len) = = failure) {//Get filename and file length return_null (); } if (!filename_len!mode_len) {php_error_docref (NULL tsrmls_cc, e_warning, "Invalid Filenam
        E or mode length ");
    Return_false;
    fp = fopen (filename, mode);
                if (!FP) {php_error_docref (NULL tsrmls_cc, e_warning, unable to open%s using mode%s),
        filename, mode);
    Return_false; }fdata = emalloc (sizeof (php_sample_descriptor_data));//Assign space to the structure that contains the file resource and file name FDATA->FP = FP; Fdata->filename = estrndup (filename, filename_len);Zend_register_resource (Return_value, Fdata, le_sample_descriptor); Registering Resources}

Fwrite also needs to be modified for file write functions:
Php_function (Sample_fwrite)
{
    php_sample_descriptor_data *fdata;
    Zval *file_resource;
    char *data;
    int Data_len;
    if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "rs",
            &file_resource, &data, &data_len) = = Failure) {
        return_null ();
    }
    Zend_fetch_resource (Fdata, php_sample_descriptor_data*,
        &file_resource,-1,
        Php_sample_ Descriptor_res_name, le_sample_descriptor);
    Return_long (fwrite (data, 1, Data_len, FDATA->FP));

There is no need to change anything for the Sample_fclose function because it does not manipulate the actual resources. The following function can get the original file name from the resource:
Php_function (sample_fname)
{
    php_sample_descriptor_data *fdata;
    Zval *file_resource;
    if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "R",
            &file_resource) = = failure) {
        return_null ();
    }
    Zend_fetch_resource (Fdata, php_sample_descriptor_data*,
        &file_resource,-1,
        Php_sample_ Descriptor_res_name, le_sample_descriptor);
    Return_string (Fdata->filename, 1);


After the memory allocation has been completed, because it must be persisted, you must deferred destructor
For Non-persistent resources, once the variables containing the resource IDs are unset or fallen out of scope, they are removed from eg (regular_list). The index used in eg (persistent_list) is the key-value class, and the element is not automatically removed at the end of the request. It is only eliminated if the Zend_hash_del () call or the thread/process is completely closed. EG (Persistent_list) also has a dtor method, but is the second parameter of ZEND_REGISTER_LIST_DESCRUCTORS_EX (). In general, non-durable and persistent resources are registered in two types, and sometimes they can be combined. Now add a persistent resource type to the SAMPLE.C.
    static int le_sample_descriptor_persist;
    static void Php_sample_descriptor_dtor_persistent (
                    zend_rsrc_list_entry *rsrc tsrmls_dc)
{// This is a persistent resource destructor
    php_sample_descriptor_data *fdata =
                (php_sample_descriptor_data*) rsrc->ptr;
    fclose (FDATA->FP);
    Pefree (Fdata->filename, 1);
    Pefree (Fdata, 1);
}
Php_minit_function (sample)
{
    le_sample_descriptor =     zend_register_list_destructors_ex (
            php_ Sample_descriptor_dtor, NULL,
            php_sample_descriptor_res_name, module_number);
    le_sample_descriptor_persist =
                        zend_register_list_destructors_ex (
            NULL, Php_sample_descriptor_ Dtor_persistent,
            php_sample_descriptor_res_name, Module_number)//Register a persisted resource return
    SUCCESS;
} 

The following fopen function is compatible with two resource types that are persistent and not persistent:
Php_function (sample_fopen) {Php_sample_descriptor_data *fdata;
    FILE *FP;
    Char *filename, *mode;
    int Filename_len, Mode_len;
    Zend_bool persist = 0; if (Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SSB", &filename, &filename_len, &mode, &A
    Mp;mode_len, &persist) = = failure) {return_null (); } if (!filename_len!mode_len) {php_error_docref (NULL tsrmls_cc, e_warning, "Invalid Filenam
        E or mode length ");
    Return_false;
    fp = fopen (filename, mode);
                if (!FP) {php_error_docref (NULL tsrmls_cc, e_warning, unable to open%s using mode%s),
        filename, mode);
    Return_false;
        } if (!persist) {//non-persisted resource fdata = Emalloc (sizeof (php_sample_descriptor_data));
        Fdata->filename = estrndup (filename, filename_len);//This did the application memory and assignment two-step operation FDATA->FP = FP; Zend_register_resource (Return_value, Fdata, Le_sample_descriptor);
        else {//persistent resource list_entry le;          
        Char *hash_key;
        int Hash_key_len;
        Fdata =pemalloc (sizeof (Php_sample_descriptor_data), 1);
        Fdata->filename = Pemalloc (Filename_len + 1, 1);
        memcpy (fdata->filename, filename, Filename_len + 1);
        FDATA->FP = FP;

        Zend_register_resource (Return_value, Fdata, le_sample_descriptor_persist);
        /* Store a copy in the Persistent_list stores a copy in Persistent_list * * Le.type = le_sample_descriptor_persist;
        Le.ptr = Fdata;
        Hash_key_len = spprintf (&hash_key, 0, "sample_descriptor:%s:%s", filename, mode); Zend_hash_update (&eg (persistent_list), Hash_key, Hash_key_len + 1, (void*) &le, sizeof (list
        _entry), NULL);
    Efree (Hash_key);  }
}

For non-persistent Resources, the index of a number is given and stored in a list that is dependent on the request. For a persisted resource, a key value type is given, which can be hashkey in the next request. Then put the resources into the persistentlist. When a persistent resource out of scope, the destructor of EG (Regular_list) examines registerlist for le_sample_descriptro_persist. If the discovery is null, there will be no action. This ensures that lasting resources are not released. When the resource is removed from eg (persistent_list), either the thread process ends or is deleted intentionally. This is the time to find the persistent destructor.

The reason the resource is requested to be persisted is to be able to Reuse
If you want to reuse a persisted resource, you must use Hash_key, and when Sample_fopen is invoked, the function will recreate the Hash_key with the file name and schema of the request, and then try to find it in persistent_list.
Php_function (sample_fopen) {Php_sample_descriptor_data *fdata;
    FILE *FP;
    Char *filename, *mode, *hash_key;
    int Filename_len, Mode_len, Hash_key_len; Zend_bool persist = 0;
    To judge whether the persistent List_entry *existing_file; if (Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SSB", &filename, &filename_len, &mode, &A
    Mp;mode_len, &persist) = = failure) {return_null (); } if (!filename_len!mode_len) {php_error_docref (NULL tsrmls_cc, e_warning, "Invalid Filenam
        E or mode length ");
    Return_false;
     }/* Try to find an open file by getting a hash_key * * Hash_key_len = spprintf (&hash_key, 0, "sample_descriptor:%s: %s ", filename, mode); if (Zend_hash_find &eg (persistent_list), Hash_key, Hash_key_len + 1, (void * * *) &existin G_file = = SUCCESS) {/* successfully found this open file handle resource/Zend_register_resource (Return_value, Existing_ File->ptr, le_sample_descriptor_persist); Efree (Hash_key); Return }
    fp = fopen (filename, mode);
                if (!FP) {php_error_docref (NULL tsrmls_cc, e_warning, unable to open%s using mode%s),
        filename, mode);
    Return_false;
        } if (!persist) {fdata = Emalloc (sizeof (php_sample_descriptor_data));
        Fdata->filename = estrndup (filename, filename_len);
        FDATA->FP = FP;
    Zend_register_resource (Return_value, Fdata, le_sample_descriptor);
        else {list_entry le;
        Fdata =pemalloc (sizeof (Php_sample_descriptor_data), 1);
        Fdata->filename = Pemalloc (Filename_len + 1, 1);
        memcpy (data->filename, filename, Filename_len + 1);
        FDATA->FP = FP;
        Zend_register_resource (Return_value, Fdata, le_sample_descriptor_persist);
        /* Store a copy in the persistent_list * * Le.type = le_sample_descriptor_persist;
        Le.ptr = Fdata; /* Hash_key has alreadybeen created by now/Zend_hash_update (&eg (persistent_list), Hash_key, Hash_key_len + 1,
    (void*) &le, sizeof (list_entry), NULL);
} efree (Hash_key); }

Note that because all extensions use the same hash table to store resources, naming is important. Typically, the extension and resource type names are used as prefixes.

Check resource availability:
Although resources like files can be opened for long periods of time, similar remote network resources are problematic if they are not used for long periods between requests. So before using a persistent resource, you need to determine availability.
if (Zend_hash_find &eg (persistent_list), Hash_key,
        Hash_key_len + 1, (void**) &socket) = = SUCCESS) {
    if (Php_sample_socket_is_alive (SOCKET->PTR)) {
        Zend_register_resource (return_value,
                    socket->ptr, le_sample_socket);
        return;
    }
    Zend_hash_del (&eg (persistent_list),
                            Hash_key, Hash_key_len + 1);//This will go to the call before the registration of a good destructor
}











Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.