Changeset 504


Ignore:
Timestamp:
08/12/2010 03:20:49 AM (18 months ago)
Author:
ofer
Message:

Support backend caching with xcache in addition to apc

Location:
trunk/WordPress/plugin/transposh
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WordPress/plugin/transposh/core/constants.php

    r500 r504  
    1818define('EDIT_PARAM', 'edit'); 
    1919 
    20 //Enable apc usage 
    21 define('ENABLE_APC', TRUE); 
     20//Enable in memory cache usage, APC, xcache 
     21define('TP_ENABLE_CACHE', TRUE); 
     22//What is the cache items TTL 
     23define('TP_CACHE_TTL', 3600); 
    2224 
    2325//Class marking a section not be translated. 
  • trunk/WordPress/plugin/transposh/wp/transposh_db.php

    r500 r504  
    4444 
    4545    /** 
     46     * Function to return a value from memory cache 
     47     * @param string $original string we want translated 
     48     * @param string $lang language we want it translated to 
     49     * @return mixed array with translation or false on cache miss 
     50     */ 
     51    function cache_fetch($original, $lang) { 
     52        if (!TP_ENABLE_CACHE) return false; 
     53        $cached = false; 
     54        $key = $original . '___' . $lang; 
     55        if (function_exists('apc_fetch')) { 
     56            $cached = apc_fetch($key, $rc); 
     57            if ($rc === false) return false; 
     58            logger('apc', 5); 
     59        } 
     60        elseif (function_exists('xcache_get')) { 
     61            $rc = xcache_isset($key); 
     62            if ($rc === false) return false; 
     63            $cached = xcache_get($key); 
     64            logger('xcache', 5); 
     65        } 
     66        logger("Cached: $original", 5); 
     67        return $cached; 
     68    } 
     69 
     70    /** 
     71     * Function to store translation in memory cache 
     72     * @param string $original 
     73     * @param string $lang 
     74     * @param array $translated 
     75     * @param int $ttl time to live in the cache 
     76     * @return boolean true if stored successfully 
     77     */ 
     78    function cache_store($original, $lang, $translated, $ttl) { 
     79        if (!TP_ENABLE_CACHE) return false; 
     80        $key = $original . '___' . $lang; 
     81        $cache_entry = $translated; 
     82        //If we don't have translation still we want to have it in cache 
     83        //update cache FIXME, do we really need this null to ""? 
     84        if ($cache_entry == NULL) { 
     85            $cache_entry = ""; 
     86        } 
     87        if (function_exists('apc_store')) { 
     88            $rc = apc_store($key, $cache_entry, $ttl); 
     89        } elseif (function_exists('xcache_set')) { 
     90            $rc = xcache_set($key, $cache_entry, $ttl); 
     91        } 
     92        if ($rc) { 
     93            logger("Stored in cache: $original => {$translated[0]},{$translated[1]}", 3); 
     94        } 
     95        return $rc; 
     96    } 
     97 
     98    /** 
     99     * Remove a value from memory cache 
     100     * @param string $original 
     101     * @param string $lang 
     102     */ 
     103    function cache_delete($original, $lang) { 
     104        if (!TP_ENABLE_CACHE) return; 
     105        $key = $original . '___' . $lang; 
     106        if (function_exists('apc_delete')) { 
     107            apc_delete($key); 
     108        } elseif (function_exists('xcache_unset')) { 
     109            xcache_unset($key); 
     110        } 
     111    } 
     112 
     113    /** 
     114     * Clean the memory cache 
     115     */ 
     116    function cache_clean() { 
     117        if (!TP_ENABLE_CACHE) return; 
     118        if (function_exists('apc_clear_cache')) apc_clear_cache('user'); 
     119        elseif (function_exists('xcache_unset_by_prefix')) 
     120                xcache_unset_by_prefix(); 
     121    } 
     122 
     123    /** 
    46124     * Allow fetching of multiple translation requests from the database with a single query 
    47125     * @param array $originals 
     
    50128    function prefetch_translations($originals, $lang) { 
    51129        if (!$originals) return; 
     130        logger($originals, 4); 
    52131        foreach ($originals as $original) { 
    53132            $original = $GLOBALS['wpdb']->escape(html_entity_decode($original, ENT_NOQUOTES, 'UTF-8')); 
    54             if (ENABLE_APC && function_exists('apc_fetch')) { 
    55                 $cached = apc_fetch($original . '___' . $lang, $rc); 
    56                 if ($rc === TRUE) { 
    57                     logger("Cached: $original", 4); 
    58                     continue; 
    59                 } 
     133            $cached = $this->cache_fetch($original, $lang); 
     134            // if $cached is not false, there is something in the cache, so no need to prefetch 
     135            if ($cached !== false) { 
     136                continue; 
    60137            } 
    61138            $where .= ( ($where) ? ' OR ' : '') . "original = '$original'"; 
    62139        } 
     140        // If we have nothing, we will do nothing 
    63141        if (!$where) return; 
    64142        $table_name = $GLOBALS['wpdb']->prefix . TRANSLATIONS_TABLE; 
     
    66144        $rows = $GLOBALS['wpdb']->get_results($query, ARRAY_A); 
    67145        if (empty($rows)) return; 
     146        // we are saving in the array and not directly to cache, because cache might not exist... 
    68147        foreach ($rows as $row) { 
    69148            $this->translations[$row['original']] = array(stripslashes($row['translated']), $row['source']); 
     
    83162        $translated = NULL; 
    84163        logger("Enter: $original", 4); 
    85  
    86164        //The original is saved in db in its escaped form 
    87165        $original = $GLOBALS['wpdb']->escape(html_entity_decode($original, ENT_NOQUOTES, 'UTF-8')); 
    88  
    89         if (ENABLE_APC && function_exists('apc_fetch')) { 
    90             $cached = apc_fetch($original . '___' . $lang, $rc); 
    91             if ($rc === TRUE) { 
    92                 logger("Exit from cache: $cached", 4); 
    93                 return $cached; 
    94             } 
    95         } 
    96  
     166        // first we look in the cache 
     167        $cached = $this->cache_fetch($original, $lang); 
     168        if ($cached !== false) { 
     169            logger("Exit from cache: {$cached[0]} {$cached[1]}", 4); 
     170            return $cached; 
     171        } 
     172        // then we look for a prefetch 
    97173        if ($this->translations[$original]) { 
    98174            $translated = $this->translations[$original]; 
     
    111187            } 
    112188        } 
    113  
    114         if (ENABLE_APC && function_exists('apc_store')) { 
    115             //If we don't have translation still we want to have it in cache 
    116             $cache_entry = $translated; 
    117             if ($cache_entry == NULL) { 
    118                 $cache_entry = ""; 
    119             } 
    120  
    121             //update cache 
    122             $rc = apc_store($original . '___' . $lang, $cache_entry, 3600); 
    123             if ($rc === TRUE) { 
    124                 logger("Stored in cache: $original => {$translated[0]},{$translated[1]}", 4); 
    125             } 
    126         } 
    127  
    128         logger("Exit: $translated", 4); 
     189        // we can store the result in the cache (or the fact we don't have one) 
     190        $this->cache_store($original, $lang, $translated, TP_CACHE_TTL); 
     191 
    129192        return $translated; 
    130193    } 
     
    142205        logger("Enter: $translation", 4); 
    143206 
    144         //The original is saved in db in its escaped form 
     207        // The translation is saved in db in its escaped form 
    145208        $translation = $GLOBALS['wpdb']->escape(html_entity_decode($translation, ENT_NOQUOTES, 'UTF-8')); 
    146  
    147         if (ENABLE_APC && function_exists('apc_fetch')) { 
    148             $cached = apc_fetch($translation . '_r_r_' . $lang, $rc); 
    149             if ($rc === TRUE) { 
    150                 logger("Exit from cache: $cached", 4); 
    151                 return $cached; 
    152             } 
    153         } 
    154  
     209        // The translation might be cached (notice the additional postfix) 
     210        $cached = $this->cache_fetch($translation . '_R_', $lang); 
     211        if ($cached !== false) { 
     212            logger("Exit from cache: $cached", 4); 
     213            return $cached; 
     214        } 
     215        // FIXME - no prefetching for originals yet... 
    155216        if ($this->translations[$translation]) { 
    156217            $original = $this->translations[$translation]; 
    157             logger("prefetch result for $translation >>> {$this->translations[$translation][0]} ({$this->translations[$translation][1]})", 4); 
     218            logger("prefetch result for $translation >>> {$this->translations[$translation][0]} ({$this->translations[$translation][1]})", 3); 
    158219        } else { 
    159  
    160220            $table_name = $GLOBALS['wpdb']->prefix . TRANSLATIONS_TABLE; 
    161221            $query = "SELECT * FROM $table_name WHERE translated = '$translation' and lang = '$lang' "; 
     
    168228        } 
    169229 
    170         if (ENABLE_APC && function_exists('apc_store')) { 
    171             //If we don't have translation still we want to have it in cache 
    172             $cache_entry = $original; 
    173             if ($cache_entry == NULL) { 
    174                 $cache_entry = ""; 
    175             } 
    176  
    177             //update cache 
    178             $rc = apc_store($translation . '_r_r_' . $lang, $cache_entry, 3600); 
    179             if ($rc === TRUE) { 
    180                 logger("Stored in cache: $translation => $original", 4); 
    181             } 
    182         } 
    183  
    184         logger("Exit: $translation/$original", 3); 
     230        // we can store the result in the cache (or the fact we don't have one) 
     231        $this->cache_store($translation . '_R_', $lang, $original, TP_CACHE_TTL); 
     232 
     233        logger("Exit: $translation/$original", 4); 
    185234        return $original; 
    186235    } 
     
    218267            } 
    219268        } 
    220  
    221269        if (!($all_editable && 
    222270                ($this->transposh->is_translator() || ($source == 1 && $this->transposh->options->get_enable_auto_translate())))) { 
     
    229277        header("Transposh: v-" . TRANSPOSH_PLUGIN_VER . " db_version-" . DB_VERSION); 
    230278 
    231         // transaction log stuff 
     279        // translation log stuff 
    232280        global $user_ID; 
    233281        get_currentuserinfo(); 
     
    239287            $loguser = $user_ID; 
    240288        } 
    241         // end tl 
    242         // We are now passing all posted items 
     289 
     290        // We are now processing all posted items 
    243291        for ($i = 0; $i < $items; $i++) { 
    244292            if (isset($_POST["tk$i"])) { 
    245293                $original = transposh_utils::base64_url_decode($_POST["tk$i"]); 
    246                 //The original content is encoded as base64 before it is sent (i.e. token), after we 
    247                 //decode it should just the same after it was parsed. 
     294                // The original content is encoded as base64 before it is sent (i.e. token), after we 
     295                // decode it should just the same after it was parsed. 
    248296                $original = $GLOBALS['wpdb']->escape(html_entity_decode($original, ENT_NOQUOTES, 'UTF-8')); 
    249297            } 
    250298            if (isset($_POST["tr$i"])) { 
    251299                $translation = $_POST["tr$i"]; 
    252                 //Decode & remove already escaped character to avoid double escaping 
     300                // Decode & remove already escaped character to avoid double escaping 
    253301                $translation = $GLOBALS['wpdb']->escape(htmlspecialchars(stripslashes(urldecode($translation)))); 
    254302            } 
     
    259307                $source = $_POST["sr$i"]; 
    260308            } 
    261             // should we backup? 
     309 
     310            // should we backup? - yes on any human translation 
    262311            if ($source == 0) $backup_immidiate_possible = true; 
    263312 
     
    266315            if ($translated_text) { 
    267316                if ($source > 0) { 
    268                     logger("Warning auto-translation for already translated: $original $lang", 0); 
     317                    logger("Warning auto-translation for already translated: $original $lang", 1); 
    269318                    continue; 
    270319                    //return; // too harsh, we just need to get to the next in for 
    271320                } 
    272321                if ($translation == $GLOBALS['wpdb']->escape(htmlspecialchars(stripslashes(urldecode($translated_text)))) && $old_source == $source) { 
    273                     logger("Warning attempt to retranslate with same text: $original, $translation", 0); 
     322                    logger("Warning attempt to retranslate with same text: $original, $translation", 1); 
    274323                    continue; 
    275324                    //return; // too harsh, we just need to get to the next in for 
     
    283332 
    284333            // If we have caching - we remove previous entry from cache 
    285             if (ENABLE_APC && function_exists('apc_delete')) { 
    286                 apc_delete($original . '___' . $lang); 
    287             } 
    288         } 
    289  
    290         // avoid empty work 
     334            $this->cache_delete($original, $lang); 
     335        } 
     336 
     337        // avoid empty database work 
    291338        if (!$values) return; 
    292339        // perform insertion to the database, with one query :) 
    293         // since we have no primary key, replace made no sense 
     340        // since we no longer have a primary key, replacement made no sense 
    294341        /* $update = "REPLACE INTO ".$GLOBALS['wpdb']->prefix . TRANSLATIONS_TABLE." (original, translated, lang, source) 
    295342          VALUES $values"; */ 
     
    302349        $result = $GLOBALS['wpdb']->query($update); 
    303350 
     351        // if the insertion worked, we will update the transaction log 
    304352        if ($result !== FALSE) { 
    305             // update the transaction log too 
    306353            $log = "INSERT INTO " . $GLOBALS['wpdb']->prefix . TRANSLATIONS_LOG . " (original, translated, lang, translated_by, source) " . 
    307354                    "VALUES $logvalues"; 
    308355            $result = $GLOBALS['wpdb']->query($log); 
    309  
    310356            logger("Inserted to db '$values'", 3); 
    311357        } else { 
     
    315361        } 
    316362 
    317         if ($source == 0) { // if its a human translation 
     363        // if its a human translation we will call the action, this takes the assumption of a single human translation in 
     364        // a function call, which should probably be verified (FIXME move up?) 
     365        if ($source == 0) { 
    318366            do_action('transposh_human_translation', $translation, $original, $lang); 
    319367        } 
     
    346394        logger("Passed check for $lang", 4); 
    347395 
    348         //Check permissions, first the lanugage must be on the edit list. Then either the user 
    349         //is a translator or automatic translation if it is enabled. 
     396        // Check permissions, first the lanugage must be on the edit list. Then either the user 
     397        // is a translator or automatic translation if it is enabled. 
    350398        if (!($this->transposh->options->is_editable_language($lang) && $this->transposh->is_translator())) { 
    351399            logger("Unauthorized history request " . $_SERVER['REMOTE_ADDR'], 1); 
     
    358406        logger("table is $table_name", 4); 
    359407 
    360         //The original content is encoded as base64 before it is sent (i.e. token), after we 
    361         //decode it should just the same after it was parsed. 
     408        // The original content is encoded as base64 before it is sent (i.e. token), after we 
     409        // decode it should just the same after it was parsed. 
    362410        $original = $GLOBALS['wpdb']->escape(html_entity_decode($original, ENT_NOQUOTES, 'UTF-8')); 
    363411 
    364         //add our own custom header - so we will know that we got here 
     412        // add our own custom header - so we will know that we got here 
    365413        header('Transposh: v-' . TRANSPOSH_PLUGIN_VER . ' db_version-' . DB_VERSION); 
    366414 
     
    373421 
    374422        $rows = $GLOBALS['wpdb']->get_results($query); 
    375         logger($rows, 4); // trying 
     423        logger($rows, 4); 
     424        // TODO: work with json 
    376425        //header("Content-type: text/javascript"); 
    377426        //echo json_encode($rows); 
     
    405454        logger("table is $table_name", 4); 
    406455 
    407         //add  our own custom header - so we will know that we got here 
    408 //        header("Transposh: v-".TRANSPOSH_PLUGIN_VER." db_version-". DB_VERSION); 
    409  
    410456        if ($date != "null") 
    411457                $dateterm = "and UNIX_TIMESTAMP(timestamp) > $date"; 
     
    444490                    KEY original (original(6),lang) 
    445491                    ) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci"; 
    446             /*            $sql = "CREATE TABLE $table_name (original VARCHAR(255) NOT NULL,". 
    447               "lang CHAR(5) NOT NULL,". 
    448               "translated VARCHAR(255),". 
    449               "source TINYINT NOT NULL,". 
    450               "PRIMARY KEY (original, lang)) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci"; */ 
    451492 
    452493            dbDelta($sql); 
     
    466507                    KEY original (original(6),lang,timestamp) 
    467508                    ) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci"; 
    468             /*            $sql = "CREATE TABLE $table_name (original VARCHAR(255) NOT NULL,". 
    469               "lang CHAR(5) NOT NULL,". 
    470               "translated VARCHAR(255),". 
    471               "translated_by VARCHAR(15),". 
    472               "source TINYINT NOT NULL,". 
    473               "timestamp TIMESTAMP,". 
    474               "PRIMARY KEY (original, lang, timestamp)) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci"; */ 
    475509 
    476510            dbDelta($sql); 
     
    507541        foreach ($rows as $row) { 
    508542            $td = mysql2date(get_option('date_format') . ' ' . get_option('time_format'), $row->timestamp); 
    509             //the_date(); 
    510543            echo "<p>On <strong>{$td}</strong><br/>user <strong>{$row->translated_by}</strong> translated<br/>" . 
    511544            "\"<strong>{$row->original}</strong>\"<br/>to " . 
     
    568601                ' WHERE ' . $GLOBALS['wpdb']->prefix . TRANSLATIONS_TABLE . '.source > 0' . 
    569602                " AND timestamp < SUBDATE(NOW(),$days)"; 
     603        $result = $GLOBALS['wpdb']->query($cleanup); 
     604        logger($cleanup, 4); 
    570605        // clean up cache so that results will actually show 
    571         if (ENABLE_APC && function_exists('apc_clear_cache')) 
    572                 apc_clear_cache('user'); 
    573  
    574         $result = $GLOBALS['wpdb']->query($cleanup); 
     606        $this->cache_clean(); 
    575607        exit; 
    576608    } 
     
    581613        // if there is a newer auto translation, remove it 
    582614        // update it 
     615        // TODO - change this part to use the update_translation function 
     616        $original = $GLOBALS['wpdb']->escape(html_entity_decode($original, ENT_NOQUOTES, 'UTF-8')); 
     617        $translation = $GLOBALS['wpdb']->escape(html_entity_decode($translation, ENT_NOQUOTES, 'UTF-8')); 
    583618        $source = 0; 
    584619        // for now - just update it... 
Note: See TracChangeset for help on using the changeset viewer.