Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
regen_metadata_schemas.php
1 <?php
26 if (ini_get('memory_limit') != '-1') ini_set('memory_limit', '-1');
27 error_reporting(E_ALL);
28 $metadata_schemas = Array();
29 
30 if (php_sapi_name() != 'cli') {
31  trigger_error("You can only run this script from the command line\n", E_USER_ERROR);
32 }
33 
34 // Check for valid system root
35 $SYSTEM_ROOT = (isset($_SERVER['argv'][1])) ? $_SERVER['argv'][1] : '';
36 if (empty($SYSTEM_ROOT)) {
37  echo "ERROR: You need to supply the path to the System Root as the first argument\n";
38  echo 'Usage: '.basename($_SERVER['argv'][0])." <system root> [schema ID]...\n";
39  exit();
40 }
41 
42 if (!is_dir($SYSTEM_ROOT) || !is_readable($SYSTEM_ROOT.'/core/include/init.inc')) {
43  echo "ERROR: Path provided doesn't point to a Matrix installation's System Root. Please provide correct path and try again.\n";
44  echo 'Usage: '.basename($_SERVER['argv'][0])." <system root> [schema ID]...\n";
45  exit();
46 }
47 
48 define('SQ_SYSTEM_ROOT', realpath($SYSTEM_ROOT));
49 define('BATCH_SIZE', 50); // The number of assets being processed in one thread.
50 define('MAX_CONCURRENCY', 3);
51 define('SYNCH_FILE', $SYSTEM_ROOT.'/data/private/logs/regen_metadata_by_schema.assetid');
52 
53 
54 $pid_prepare = pcntl_fork();
55  switch ($pid_prepare) {
56  case -1:
57  break;
58  case 0:
59 
60  require_once $SYSTEM_ROOT.'/core/include/init.inc';
61  // This ridiculousness allows us to workaround Oracle, forking and CLOBs
62  // if a query is executed that returns more than 1 LOB before a fork occurs,
63  // the Oracle DB connection will be lost inside the fork.
64  // have to place all queries inside a forked process, and store back results to a physical file
65 
66  // If user has specified schema ID's manually, use those
67  if (isset($_SERVER['argv'][2])) {
68  $metadata_schemas = $_SERVER['argv'];
69 
70  // Remove the first two arguments
71  array_shift($metadata_schemas);
72  array_shift($metadata_schemas);
73  } else {
74 
75  // Otherwise, get all the metadata schemas in the system
76  $metadata_schemas = $GLOBALS['SQ_SYSTEM']->am->getTypeAssetids('metadata_schema', TRUE);
77  }
78 
79 
80  $mm = $GLOBALS['SQ_SYSTEM']->getMetadataManager();
81  $total_assets = Array();
82  foreach ($metadata_schemas as $schemaid) {
83  $schema = $GLOBALS['SQ_SYSTEM']->am->getAsset($schemaid);
84  if (!$schema) {
85  trigger_error('Schema asset #'.$schemaid.' could not be found', E_USER_WARNING);
86  continue;
87  }
88  if (!($schema instanceof Metadata_Schema)) {
89  trigger_error('Asset #'.$schema->id.' is not a metadata schema', E_USER_WARNING);
90  continue;
91  }
92  $total_assets = array_merge($total_assets, $mm->getSchemaAssets($schemaid, TRUE));
93  }
94 
95  // Save the list into a file so we can access the list from the parent process
96  file_put_contents(SYNCH_FILE, implode(',', $total_assets));
97 
98 
99  exit(0);
100  // waiting for child exit signal
101  $status = null;
102  pcntl_waitpid(-1, $status);
103 
104  break;
105  default:
106  $status = null;
107  pcntl_waitpid(-1, $status);
108  break;
109  }//end switch
110 
111 
112  // restore the to-be-processed assetid from the physical file
113 $total_assets = Array();
114 if (file_exists(SYNCH_FILE)) {
115  $total_assets_str = file_get_contents(SYNCH_FILE);
116 } else {
117  trigger_error ("Unable to find Synch File, probably because the user executing this script does not have permission to write to this folder.", E_USER_WARNING);
118  exit(0);
119 }//end else
120 
121 $total_assets = explode(',', $total_assets_str);
122 $total_assets = array_unique($total_assets);
123 // Chunk them up so we can process each batch when forking
124 $chunk_assets = array_chunk($total_assets, BATCH_SIZE);
125 $current_asset_list = Array();
126 
127 
128  printUpdateStatus ("Total ".count($total_assets)." found");
129  $fork_num = 0; // Determine how many child process we have forked
130  while (!empty($chunk_assets)) {
131  // do 50 assets per process
132  // the main reason we need to chunk and fork is because memory leakage prevention
133  // call hipo job directly will cause slowly increasing memory usage, and eventually explode
134  $current_asset_list = array_pop($chunk_assets);
135  $pid = pcntl_fork();
136  $fork_num++;
137  switch ($pid) {
138  case -1:
139  trigger_error('Process failed to fork while regenerating metadata', E_USER_ERROR);
140  exit(1);
141  break;
142  case 0:
143 
144  require_once $SYSTEM_ROOT.'/core/include/init.inc';
145 
146  $mm = $GLOBALS['SQ_SYSTEM']->getMetadataManager();
147 
148  foreach ($current_asset_list as $assetid) {
149  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
150  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
151  $contextids = array_keys($GLOBALS['SQ_SYSTEM']->getAllContexts());
152  foreach ($contextids as $contextid) {
153  if (!$mm->regenerateMetadata($assetid, NULL)) {
154  trigger_error('Asset failed to regenrate metedata #'.$assetid.'', E_USER_WARNING);
155  continue;
156  }//end if
157  else {
158  printUpdateStatus('Regenerated Metadata for assetid '.$assetid);
159  }
160  }
161 
162  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
163  unset($asset);
164 
165  }//end foreach
166 
167  unset($current_asset_list);
168  exit(0);
169  // waiting for child exit signal
170  $status = null;
171  pcntl_waitpid(-1, $status);
172 
173  break;
174  default:
175  // We only want to fork a maximum number of child process, so if we've already reached the max num, sit and wait
176  if ($fork_num >= MAX_CONCURRENCY) {
177  $status = null;
178  pcntl_waitpid(-1, $status);
179  $fork_num--;
180  }//end if
181 
182  if (empty($chunk_assets)) {
183  // We wait for all the fork child to finish
184  while ($fork_num > 0) {
185  $status = null;
186  pcntl_waitpid(-1, $status);
187  $fork_num--;
188  }//end
189  }//end if
190 
191  break;
192 
193  }//end switch & thread
194  }//end while
195 
196 
197  if (file_exists(SYNCH_FILE)) {
198  unlink(SYNCH_FILE);
199  }//end if
200 
201  printUpdateStatus("Done");
202 
203  exit(0);
204 
205 
206 
207 
216 function printUpdateStatus($status)
217 {
218  echo "[ $status ]\n";
219 
220 }//end printUpdateStatus()
221 
222 
223 ?>