以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 XML在语音技术中的应用 』   (http://bbs.xml.org.cn/list.asp?boardid=47)
----  [求助] 大家有没有对openVXI的缓存实现机制比较了解的?【悬赏分数:20】  (http://bbs.xml.org.cn/dispbbs.asp?boardid=47&rootid=&id=39970)


--  作者:cmoaciopm
--  发布时间:11/13/2006 3:50:00 PM

--  [求助] 大家有没有对openVXI的缓存实现机制比较了解的?【悬赏分数:20】
刚接触openVXI不久,需要做cache模块,看到版主发了一篇关于cache模块下md5的研究。
想问一下对cache模块有更深的了解么?


[此贴子已经被zhu_ruixian于2006-11-15 21:10:12编辑过]

--  作者:zhu_ruixian
--  发布时间:11/13/2006 6:29:00 PM

--  
cache模块人家都已经封装好了,感觉里面的代码不用看。实现他们的4接口就可以了。然后把client做成一个服务(window下),或多线程的一个软件就可以了。
--  作者:cmoaciopm
--  发布时间:11/13/2006 9:06:00 PM

--  
sf上下载的openVXI代码直接编译后,就直接有缓存功能了吧!
看了DocumentParser的FetchDocument方法,发现并没有用到VXIcacheInterface,
觉得很奇怪,版主能解释一下么?

--  作者:zhu_ruixian
--  发布时间:11/14/2006 10:37:00 AM

--  
昨天晚上看了一下有关cache的代码。
DocumentParser的FetchDocument方法的声明如下:
int DocumentParser::FetchDocument(const VXIchar * url,
                                  const VXIMapHolder & properties,
                                  VXIinetInterface * inet,
                                  VXIcacheInterface * cache,
                                  SimpleLogger & log,
                                  VXMLDocument & document,
                                  VXIMapHolder & docProperties,
                                  bool isDefaults,
                                  bool isRootApp,
                                  VXIbyte **content,
                                  VXIulong *size);
很明显声明用到了VXIcacheInterface,但是继续阅读代码,却没有发现使用了参数cache。就是参数中虽有VXIcacheInterface,但是函数中并没有用到。浏览一下函数FetchDocument,里面有这样的注释:
// (1) Load the VXML DTD for validation.  This will override an externally
  // specified DTD if the user provides a link.
// (2) Load the url into memory.
// (3) Pull the document from cache.
// (4) Not in cache; parse buffer into our VXML document representation
// (5) Write the compiled form out to the cache.
// (6) Parse was successful, process document.  We want only the top level <vxml> node.

看一下// (3) Pull the document from cache.下面的代码,会发现是从一个叫DocumentStorageSingleton的变量里面。
DocumentStorageSingleton::Instance()->Retrieve(doc, buffer, bufSize, docURL.c_str())
看一下DocumentStorageSingleton里面有个成员变量 DOC_STORAGE storage;其实是map类型的。注释所指的cache就是DocumentStorageSingleton。也就是说DocumentParser用到的cache的功能是由DocumentStorageSingleton实现的。

看一下VXIcache.h开头的注释:
/* Abstract interface for accessing caching functionality, which
* permits writing arbitrary data into the cache with a client
* supplied key name, then retrieving that data from the cache one or
* more times by reading against that key name. <p>
*
* Normally the cache implementation can choose to discard the data
* between the write and the read when necessary (due to running out
* of cache space, etc.), but it is also possible for clients to lock
* data in the cache to support built-in grammars and other data that
* is explicitly provisioned by system administrators and thus must
* not be removed unless by explicit system administrator command. <p>

* The interface is a synchronous interface based on the ANSI/ISO C
* standard file I/O interface. The client of the interface may use this in
* an asynchronous manner by using non-blocking I/O operations,
* creating threads, or by invoking this from a separate server
* process. <p>
*
* Typically the key name specified by clients will be the URL to the
* source form of the data that is being written back, such as the URL
* to the grammar text being used as the key name for the compiled
* grammar. In the case where the VXIinet and VXIcache implementations
* share the same underlying cache storage, it is thus necessary to
* use prefixes or some other namespace mechanism to avoid collisions
* with the cache entry for the original URL. <p>
*
* However, the key names specified by clients may be very large in
* some cases. This is most common when writing back data generated
* from in-memory source text, such as when writing back the compiled
* grammar for a VoiceXML document in-line grammar.  One possible
* VXIcache implementation approach is to use the MD5 algorithm as
* used in HTTP message headers (specified in RFC 1321 with a full
* implementation provided) to convert long key names to a 16 byte MD5
* value for indexing purposes, using Base64 encoding to convert the
* binary MD5 value to ASCII text if desired (as done in HTTP message
* headers). <p>
*
* There is one cache interface per thread/line. <p>
*/

大意是说可以放进去任意的数据,并可以用URL检索出来。URL如果太长,会用md5和base64处理。那cache模块中的功能在那儿用到了那?在VXIclient.cpp的第1088行(左右)有下面的内容:
/* Create the cache resource.  The cache resource will be used by
     the recognizer and prompting components for caching of computed
     data like compiled grammars and text-to-speech prompts. */
  cacheResult = SBcacheCreateResource(newPlatform->VXIlog, &newPlatform->VXIcache);

注释的意思是cache是recognizer和prompting 组件用到的。在VXIprompt和VXIrec中,仅仅有
VXIpromptResult VXIpromptCreateResource (
  VXIlogInterface     *log,
  VXIinetInterface    *inet,
  VXIcacheInterface   *cache,
  VXIpromptInterface **prompt)

VXIREC_API VXIrecResult VXIrecCreateResource(VXIlogInterface   *log,
        VXIinetInterface  *inet,
          VXIcacheInterface *cache,
          VXIpromptInterface *prompt,
          VXItelInterface *tel,
        VXIrecInterface  **rec)
用到了,而且函数里面参数cache并没有用到,感觉要实现者自己写代码吧。代码没再继续往下看。


--  作者:tainw
--  发布时间:12/11/2006 11:46:00 AM

--  
版主,请问那个<prompt>元素之间被解析后的文本,被Openvxi放到哪里去了?
--  作者:zhu_ruixian
--  发布时间:12/11/2006 12:34:00 PM

--  
OpenVXI没有保存里面的内容,需要自己实现。示例代码如下,粗体代码为手动添加的部分。你需要做的是,备份VXIprompt模块下的VXIprompt.cpp,然后把下面的代码替换掉原来VXIprompt下面VXIprompt.cpp里面的内容,然后编译即可(如果编译有错误,去掉[B][/B],这是编辑帖子的时候加的):

/****************License************************************************
* Vocalocity OpenVXI
* Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*  
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
* Vocalocity, the Vocalocity logo, and VocalOS are trademarks or
* registered trademarks of Vocalocity, Inc.
* OpenVXI is a trademark of Scansoft, Inc. and used under license
* by Vocalocity.
***********************************************************************/

#include <cstdio>
#include <string>
#include <cstring>
#define VXIstrcmp wcscmp
#include "..\include\VXIvalue.h"
#include "..\include\VXIpromptAPI.h"
#include "../swichar/include/swistring.h"
// Global for the base diagnostic tag ID
//
static VXIunsigned gblDiagLogBase = 0;

// Constants for diagnostic logging tags
//
static const VXIunsigned DIAG_TAG_PROMPTING = 1;
static const VXIunsigned DIAG_TAG_PREFETCHING = 2;


// VXIprompt implementation of the VXIprompt interface
//
#include <list>
using namespace std;

extern "C" {
struct VXIpromptImpl {
  // Base interface, must be first
  VXIpromptInterfaceEx intf;

  // Log interface for this resource
  VXIlogInterface *log;

  // Internet fetch interface for this resource
  VXIinetInterface *inet;
list<vxistring>  ttstexts;
};
}


// A few conversion functions...

static inline VXIpromptImpl * ToVXIpromptImpl(VXIpromptInterface * i)
{ return reinterpret_cast<VXIpromptImpl *>(i); }

static inline VXIpromptImpl * ToVXIpromptImpl(VXIpromptInterfaceEx * i)
{ return reinterpret_cast<VXIpromptImpl *>(i); }


/*******************************************************
*
* Utility functions
*
*******************************************************/

/**
* Log an error
*/
static VXIlogResult Error(VXIpromptImpl *impl, VXIunsigned errorID,
     const VXIchar *format, ...)
{
  VXIlogResult rc;
  va_list arguments;

  if ((! impl) || (! impl->log))
    return VXIlog_RESULT_NON_FATAL_ERROR;
  
  if (format) {
    va_start(arguments, format);
    rc = (*impl->log->VError)(impl->log, COMPANY_DOMAIN L".VXIprompt",
         errorID, format, arguments);
    va_end(arguments);
  } else {
    rc = (*impl->log->Error)(impl->log, COMPANY_DOMAIN L".VXIprompt",
        errorID, NULL);
  }

  return rc;
}


/**
* Log a diagnostic message
*/
static VXIlogResult Diag(VXIpromptImpl *impl, VXIunsigned tag,
    const VXIchar *subtag, const VXIchar *format, ...)
{
  VXIlogResult rc;
  va_list arguments;

  if ((! impl) || (! impl->log))
    return VXIlog_RESULT_NON_FATAL_ERROR;

  if (format) {
    va_start(arguments, format);
    rc = (*impl->log->VDiagnostic)(impl->log, tag + gblDiagLogBase, subtag,
       format, arguments);
    va_end(arguments);
  } else {
    rc = (*impl->log->Diagnostic)(impl->log, tag + gblDiagLogBase, subtag,
      NULL);
  }

  return rc;
}


/*******************************************************
*
* Method routines for VXIpromptInterface structure
*
*******************************************************/

// Get the VXIprompt interface version supported
//
static VXIint32 VXIpromptGetVersion(void)
{
  return VXI_CURRENT_VERSION;
}


// Get the implementation name
//
static const VXIchar* VXIpromptGetImplementationName(void)
{
  static const VXIchar IMPLEMENTATION_NAME[] = COMPANY_DOMAIN L".VXIprompt";
  return IMPLEMENTATION_NAME;
}


// Begin a session
//
static
VXIpromptResult VXIpromptBeginSession(VXIpromptInterface * pThis, VXIMap *)
{
  return VXIprompt_RESULT_SUCCESS;
}


// End a session
//
static
VXIpromptResult VXIpromptEndSession(VXIpromptInterface *pThis, VXIMap *)
{
  return VXIprompt_RESULT_SUCCESS;
}


// Start playing queued prompts. This call is non-blocking.
//
static VXIpromptResult VXIpromptPlay(VXIpromptInterface * vxip)
{
  VXIpromptImpl *impl = ToVXIpromptImpl(vxip);
vxistring tts;
  if( impl->ttstexts.size()>0){
   tts=impl->ttstexts.front();
   impl->ttstexts.pop_front();
   printf("****************VXIpromptPlay语音内容********************\n");
  for(int in=0;in<tts.length();in++){
   printf("%c",tts[in]);[/B]
  }
  printf("\n****************VXIpromptPlay语音内容********************\n");
  };
  Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Playing queued prompts");
  return VXIprompt_RESULT_SUCCESS;
}


// Start the special play of a filler prompt. This call is non-blocking.
//
static
VXIpromptResult VXIpromptPlayFiller(VXIpromptInterface * vxip,
        const VXIchar *type,
        const VXIchar *src,
        const VXIchar *text,
        const VXIMap* properties,
        VXIlong minPlayMsec)
{
  return VXIprompt_RESULT_SUCCESS;
}


static
VXIpromptResult VXIpromptPrefetch(VXIpromptInterface * vxip,
      const VXIchar *type,
      const VXIchar *src,
      const VXIchar *text,
      const VXIMap* properties)
{
  VXIpromptImpl *impl = ToVXIpromptImpl(vxip);

  Diag(impl, DIAG_TAG_PREFETCHING, L"VXIpromptPrefetch", L"%s",
      (text ? text : L"NULL"));
 //printf("************%s************%s",src,text);
  return VXIprompt_RESULT_SUCCESS;
}


// Queue prompt for playing. This call is non-blocking. The prompt
//  is not played until VXIpromptPlay( ) is called.
//
static
VXIpromptResult VXIpromptQueue(VXIpromptInterface* vxip,
          const VXIchar *raw_type,
          const VXIchar *raw_src,  /* no longer used */
          const VXIchar *raw_text,
          const VXIMap  *properties)
{
  VXIpromptImpl *impl = ToVXIpromptImpl(vxip);
  
  vxistring type(L""), text(L"");
  if (raw_type)
    type = raw_type;
  if (raw_text){
   text = raw_text;
  }

  // Handle the resolved information to queue.

  if (text.empty())
    return VXIprompt_RESULT_INVALID_ARGUMENT;

  // currently, vxi only queues SSML
  if (type == VXI_MIME_SSML) {
    vxistring bargein;
    const VXIValue *val = VXIMapGetProperty(properties, L"bargein");
 if (val != NULL)
      bargein = VXIStringCStr(reinterpret_cast<const VXIString*>(val));

    vxistring bargeintype;
    val = VXIMapGetProperty(properties, L"bargeintype");
 if (val != NULL)
      bargeintype = VXIStringCStr(reinterpret_cast<const VXIString*>(val));
 impl->ttstexts.push_back(text);
  printf("****************语音内容********************\n");
  for(int in=0;in<text.length();in++){
   printf("%c",text[in]);
  }
  printf("\n****************语音内容********************\n");
 Diag(impl, DIAG_TAG_PROMPTING, NULL, L"Queuing TTS: bargein=%s, bargeintype=%s, ssml=%s",
         bargein.c_str(), bargeintype.c_str(), text.c_str());
  }
  else {
    Diag(impl, DIAG_TAG_PROMPTING, NULL,
         L"Queuing Unknown type text (%s): %s" , type.c_str(), text.c_str());
    return VXIprompt_RESULT_UNSUPPORTED;
  }

  return VXIprompt_RESULT_SUCCESS;
}

             
// Wait until all queued prompts finish playing.
//
static VXIpromptResult VXIpromptWait(VXIpromptInterface* vxip,
                                     VXIpromptResult* playResult)
{
  VXIpromptImpl *impl = ToVXIpromptImpl(vxip);
  Diag(impl, DIAG_TAG_PROMPTING, NULL,
       L"%s" , L"VXIpromptWait");
  *playResult = VXIprompt_RESULT_SUCCESS;
  return VXIprompt_RESULT_SUCCESS;
}

// Stop the current playing prompt.
//
static VXIpromptResult VXIpromptStop (VXIpromptInterfaceEx *prompt)
{
  if (prompt == NULL)
    return VXIprompt_RESULT_INVALID_ARGUMENT;
  VXIpromptImpl* promptImpl = reinterpret_cast<VXIpromptImpl*>(prompt);
  return VXIprompt_RESULT_SUCCESS;  
}

/*******************************************************
* Global init and factory methods
*******************************************************/

VXIPROMPT_API VXIpromptResult VXIpromptInit (VXIlogInterface  *log,
          VXIunsigned       diagLogBase,
          const VXIVector   *resources,
          VXIMap            *args)
{
  if (! log) return VXIprompt_RESULT_INVALID_ARGUMENT;

  gblDiagLogBase = diagLogBase;
  return VXIprompt_RESULT_SUCCESS;
}


VXIPROMPT_API VXIpromptResult VXIpromptShutDown (VXIlogInterface  *log)
{
  if (! log) return VXIprompt_RESULT_INVALID_ARGUMENT;

  return VXIprompt_RESULT_SUCCESS;
}

VXIPROMPT_API
VXIpromptResult VXIpromptCreateResource (
  VXIlogInterface     *log,
  VXIinetInterface    *inet,
  VXIcacheInterface   *cache,
  VXIpromptInterface **prompt)
{  
  if ((! log) || (! inet)) return VXIprompt_RESULT_INVALID_ARGUMENT;

  VXIpromptImpl* pp = new VXIpromptImpl();
  if (pp == NULL) return VXIprompt_RESULT_OUT_OF_MEMORY;

  pp->log = log;
  pp->inet = inet;
  pp->intf.vxiprompt.GetVersion            = VXIpromptGetVersion;
  pp->intf.vxiprompt.GetImplementationName = VXIpromptGetImplementationName;
  pp->intf.vxiprompt.BeginSession          = VXIpromptBeginSession;
  pp->intf.vxiprompt.EndSession            = VXIpromptEndSession;
  pp->intf.vxiprompt.Play                  = VXIpromptPlay;
  pp->intf.vxiprompt.PlayFiller            = VXIpromptPlayFiller;
  pp->intf.vxiprompt.Prefetch              = VXIpromptPrefetch;
  pp->intf.vxiprompt.Queue                 = VXIpromptQueue;
  pp->intf.vxiprompt.Wait                  = VXIpromptWait;
  pp->intf.Stop                            = VXIpromptStop;
  
  *prompt = &pp->intf.vxiprompt;
  return VXIprompt_RESULT_SUCCESS;
}

VXIPROMPT_API
VXIpromptResult VXIpromptDestroyResource (VXIpromptInterface **prompt)
{
  if (prompt == NULL || *prompt == NULL)
    return VXIprompt_RESULT_INVALID_ARGUMENT;
  VXIpromptImpl* promptImpl = reinterpret_cast<VXIpromptImpl*>(*prompt);

  delete promptImpl;
  *prompt = NULL;

  return VXIprompt_RESULT_SUCCESS;
}


--  作者:WanMingliang
--  发布时间:5/18/2007 11:59:00 AM

--  
我也想知道.强烈关注中!!!!
--  作者:WanMingliang
--  发布时间:5/18/2007 12:10:00 PM

--  
我很郁闷.在我的IE里输入http://www.ieee.org.cn/后显示:HTTP 500 - 内部服务器错误.但显示其它的网站一点问题都没有.问xiangxiet,他说没问题.是我的IE出问题了吗?我都好几天没上论坛了.

W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
78.125ms