PHP Sessions and Data Persistence Storing Arbitrary Data in Shared Memory - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript PHP Sessions and Data Persistence Storing Arbitrary Data in Shared Memory - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript

Breaking

Post Top Ad

Post Top Ad

Thursday, June 13, 2019

PHP Sessions and Data Persistence Storing Arbitrary Data in Shared Memory

PHP Sessions and Data Persistence




Storing Arbitrary Data in Shared Memory


Problem

You want a chunk of data to be available to all server processes through shared memory.

Solution

If you want to share data only amongst PHP processes, use APC, as described in Recipe. If you want to share data with other processes as well, use the pc_Shm class shown in Example.

For example, to store a string in shared memory, use the pc_Shm::write() method, which accepts a key, a length, and a value:

         $shm = new pc_Shm();
         $secret_code = 'land shark';
         $shm->write('mysecret', strlen($secret_code), $secret_code);

Discussion

Example  Storing arbitrary data in shared memory

         class pc_Shm {

               protected $tmp;

               public function __construct($tmp = '') {
                      if (!function_exists('shmop_open')) {
                           trigger_error('pc_Shm: shmop extension is required.', E_USER_ERROR);
                           return;
                      }

                      if ($tmp != '' && is_dir($tmp) && is_writable($tmp)) {
                           $this->tmp = $tmp;
                      } else {
                           $this->tmp = '/tmp';
                      }
               }

               public function read($id, $size) {
                      $shm = $this->open($id, $size);
                      $data = shmop_read($shm, 0, $size);
                      $this->close($shm);
                      if (!$data) {
                           trigger_error('pc_Shm: could not read from shared memory block',
                                                      E_USER_ERROR);
                           return false;
                      }
                      return $data;
               }


               public function write($id, $size, $data) {
                      $shm = $this->open($id, $size);
                      $written = shmop_write($shm, $data, 0);
                      $this->close($shm);
                      if ($written != strlen($data)) {
                           trigger_error('pc_Shm: could not write entire length of data',
                                                      E_USER_ERROR);
                           return false;
                      }
                      return true;
               }


               public function delete($id, $size) {
                      $shm = $this->open($id, $size);
                      if (shmop_delete($shm)) {
                           $keyfile = $this->getKeyFile($id);
                           if (file_exists($keyfile)) {
                                unlink($keyfile);
                           }
                      }
                      return true;
               }

               protected function open($id, $size) {
                      $key = $this->getKey($id);
                      $shm = shmop_open($key, 'c', 0644, $size);
                      if (!$shm) {
                           trigger_error('pc_Shm: could not create shared memory segment',
                                                      E_USER_ERROR);
                           return false;
                      }
                      return $shm;
               }

               protected function close($shm) {
                      return shmop_close($shm);
               }

               protected function getKey($id) {
                      $keyfile = $this->getKeyFile($id);
                      if (! file_exists($keyfile)) {
                           touch($keyfile);
                      }
                      return ftok($keyfile, 'R');
               }

               protected function getKeyFile($id) {
                      return $this->tmp . DIRECTORY_SEPARATOR . 'pcshm_' . $id;
               }
         }

Because pc_Shm uses standard system functions for accessing shared memory, other programs (no matter what language they’re written in) can access that data as well. For example, shows a short C program that can read data written by pc_Shm.

Example  Reading shared memory data from C

         #include <sys/ipc.h>
         #include <sys/shm.h>

         #include <stdio.h>

         int main(int argc, char **argv) {
                char *id;
                size_t size;

                if (argc != 3) {
                     fprintf(stderr, "Usage: %s ID SIZE\n", argv[0]);
                     return -1;
                }

                id = argv[1];
                size = atoi(argv[2]);

                char *path;
                asprintf(&path, "/tmp/pcshm_%s", id);
                key_t token = ftok(path, (int) 'R');
                int shmid = shmget(token, size, 0);
                void *ptr = shmat(shmid, 0, SHM_RDONLY);
                printf("%*s\n", (int) size, (char *) ptr);
                shmdt(ptr);
                free(path);
         }

Compiling that program and then invoking it with arguments mysecret and 10 (or any sufficiently long length) will print the data inserted into shared memory by the PHP code.

It’s important to remember that, unlike setting a key/value pair in a regular PHP array, the shmop functions need to allocate a specific amount of space that the data stored there is expected to consume. That is why the read and write operations require a size to be passed to them.


No comments:

Post a Comment

Post Top Ad