Aussi bien que fournir des moyens fournisseur-indépendants de la création, recherchant, modifiant et supprimant XSets, les spécifications de SNIA XAM v1.0 définissent également un langage d'interrogation (XAM QL), basé sur un sous-ensemble de la langue de SQL, parce que de choisir et de rechercher le XUIDs de XSets basé sur des critères contenu-définis.
L'ensemble de mots réservés pour ce langage d'interrogation est tout à fait petit : choisissez, où, et, ou, pas, comme, existe, lier, inaltérable, typeof, longueur, date, VRAIS, FAUX, avant que, après, contienne, et en dedans. Par conception, les questions de XAM ressemblent à un rapport choisi de SQL. Le langage d'interrogation est ne distinguant pas majuscules et minuscules et emploie le jeu de caractères d'ASCII.
Voici un exemple d'une question simple de XAM :
select ".xset.xuid" where "com.example.name" = ’Tuckers Plantation'
La version 1.0 des spécifications de XAM définit deux niveaux d'appui de langage d'interrogation, le niveau 1 c.-à-d. du niveau 1 et du niveau 2. définit des questions sur des propriétés et des attributs de champ dans XSets et est obligatoire. N'importe quelles valeurs d'une propriété de XSet qui sont accessibles à un programme d'application par l'intermédiaire de la bibliothèque de XAM peuvent être questionnées. Le niveau 2 prolonge le niveau 1 aux questions de soutien sur XStreams et est facultatif. Les deux niveaux de question sont accédés par un type simple et défini du travail que tous les fournisseurs de XAM doivent soutenir. Puisqu'aucun fournisseur que je me rends compte de n'a des questions du niveau réellement mis en application 2, le reste des foyers de ce poteau sur des questions du niveau 1.
Une instruction du langage de requêtes de XAM se compose d'une clause choisie obligatoire suivie d'un facultatif où clause. Pour XAM v1.0 la seule clause choisie valide est le `choisi .xset.xuid'. Ceci spécifie que l'application demande une liste de valeurs de XUID. Par exemple
select ".xset.xuid "
renverra une liste de chaque XSet qui est lisible à l'heure de la question.
Où la clause est employée pour spécifier un sous-ensemble de XSets à assortir. Pour des questions du niveau 1 elle est limitée aux comparaisons entre les propriétés de XSet et les valeurs et/ou les attributs de champ littéraux et les valeurs littérales.
select ".xset.xuid" where ".xam.time.xuid" > date(’2009-02-01T00:00:00.0’)
renverra la liste de tout le Xsets qui ont été créés dessus ou après le 1er février 2009.
Les expositions suivantes de table qui mettent en place et des types littéraux peuvent être bien comparés.
| xam_int | xam_double | xam_string | xam_datetime | xam_xuid | |
|---|---|---|---|---|---|
| international | * | * | |||
| double | * | * | |||
| corde | * | ||||
| date-heure | * | ||||
| XUID | * |
La bibliothèque de XAM valide que les cordes et les libéraux de cordes sont les cordes UTF-8 de conformation. Les constantes de chaîne UTF-8 non conformes produisent d'une erreur de syntaxe non fatale de question de XAM. Les issues telles que simple contre les caractères multiples de glyph et les caractères non imprimables sont non spécifiées et sont exécution et dépendantes de l'application. Les comparaisons de corde distinguent les majuscules et minuscules et les opérateurs de comparaison opèrent une base de byte-par-byte. Pour des opérateurs de relation les rapports sont définis par les valeurs de byte. Toute la normalisation de données est la responsabilité de l'application.
Les séquences d'échappement soutenues sont les suivantes. N'importe quelle autre séquence d'échappement produira d'une erreur non fatale.
| \ \ | Barre oblique inverse (\) |
| \ « | Guillemets (") |
| \ ' | Apostrophe (') |
| \ uxxxx | Un caractère d'Unicode dans le format hexadécimal (xxxx) |
Des constantes de chaîne doivent être citées avec des apostrophes. Les constantes de chaîne qui contiennent un ou plusieurs caractères d'apostrophe doivent échapper à chaque caractère d'apostrophe utilisant une barre oblique inverse. Par exemple, la constante de chaîne de 'ceci est un literal de corde serait représentée dans une question As
select ".xset.xuid" where "com.example.string-property" = ’This is a string literal’
Pour employer une apostrophe dans une corde, gardez-la avec une barre oblique inverse
select ".xset.xuid" where "com.example.claimed.ownership" = ’Tucker\’s’
Tous les exemples des noms de champ dans une corde de question de XAM doivent être cités avec des guillemets. Si un nom de champ contient des caractères de guillemets, chaque caractère de guillemets doit être échappé utilisant une barre oblique inverse. Par exemple, le nom de champ pour la propriété xam_boolean com.example. » qstring » devrait être représenté dans une question As
select ".xam.xuid" where "com.example.\"qstring\"" = TRUE
Si un nom de champ contient un caractère de barre oblique inverse, la barre oblique inverse elle-même doit être échappée avec une autre barre oblique inverse. Par exemple, le nom de champ pour la propriété xam_double com.example.file \ rapport devrait être représenté dans une question As
select ".xam.xuid" where "com.example.file\\ratio" = 100.1
Le langage d'interrogation accepte date-heure et les coquilles XUID-évaluées utilisant les fonctions de sélecteur datent () et xuid () respectivement. La fonction de date () prend une valeur date-heure correctement formée, spécifique car une corde littérale qui est compatible aux spécifications de date-heure de XAM.
select ".xset.xuid" where ".xam.time.xuid" = date(’2009-06-01T00:00:00.0’)
La fonction de xuid () attend un XUID qui est sous forme de constante de chaîne codée par base64. Une constante de chaîne incorrectement formée produit d'une erreur non fatale pendant l'analyse de question.
Des attributs de champ sont accédés utilisant existe, typeof, inaltérable, attache, et fonctions d'accédant d'attribut de champ de longueur. Existe () les essais de fonction pour l'existence d'un attribut de zone identification (propriété) dans un XSet. Il évalue POUR RECTIFIER si un XSet contient la zone identification autrement qu'elle évalue FAUX.
select ".xset.xuid" where exists("com.example.name")
La fonction de typeof () renvoie le type de MIME d'une zone identification dans un XSet qui est une propriété corde-évaluée.
select ".xset.xuid" where typeof("com.example.data") = ’text/plain’
select ".xset.xuid" where typeof("com.example.data") like ’text%’
Cette fonction peut être employée toutes les fois qu'une application pourrait employer une référence de champ à une propriété corde-évaluée. Notez que les comparaisons avec n'importe quelle valeur littérale de non-corde produisent d'une erreur non fatale pendant l'analyse de la question.
() La fonction inaltérable évalue POUR RECTIFIER quand un champ dans un XSet est marqué comme inaltérable.
select ".xset.xuid" where readonly("com.example.flag")
select ".xset.xuid" where not readonly("com.example.name")
() La fonction obligatoire évalue POUR RECTIFIER quand un champ dans un XSet est marqué comme liant.
select ".xset.xuid" where binding("com.example.case_id")
select ".xset.xuid" where not binding("com.example.subject")
La fonction de longueur () renvoie la longueur, en bytes, d'une zone identification.
select ".xset.xuid" where length("com.example.data") > 1024
Une fois utilisé sur la propriété met en place des retours de cette fonction la longueur comme définie pour des stypes. Notez que cette fonction ne devrait pas être employée pour comparer le nombre de caractères dans une corde pendant que cette comparaison dépend du codage de caractère étant employé.
Se tourner maintenant vers les opérateurs logiques. Paragraphes dans où la clause peut être combinée et modifiée en employant les opérateurs logiques et, ou et pas. Ces opérateurs sont semblables à leurs contre-parties de SQL.
Et opérateur exige des deux paragraphes d'évaluer POUR RECTIFIER avant comprenant un XSet dans les résultats. Par exemple
select ".xset.xuid" where typeof("com.example.stream") = ’image/gif’ and length("com.example.stream") > 4096
choisit seulement ces XSets contenant les images de GIF dont la taille est plus grande que 4096 bytes. Ou opérateur évalue POUR RECTIFIER si l'un ou l'autre paragraphe évalue POUR RECTIFIER. Par exemple
select ".xset.xuid" where typeof("com.example.stream") = ’image/jpeg’ or typeof("com.example.stream") = ’image/gif’
choisit seulement ces XSets contenant un jet appelé du type JPEG ou GIF d'image. Pas l'opérateur nie une expression booléenne. Par exemple
select ".xset.xuid" where not binding("com.example.property")
choisit tout le XSets avec la propriété non contraignante com.example.property.
Comme dans certains opérateurs de SQL ayez la priorité au-dessus d'autres opérateurs dans les questions. La priorité d'opérateur de XAM QL est comme suit :
| PRIORITÉ | OPÉRATEUR |
|---|---|
| 1 | existe, inaltérable, typeof, longueur, attache, +, - |
| 2 | = <>, >, >=, <> |
| 3 | pas |
| 4 | et |
| 5 | ou |
Les opérateurs de la même priorité sont de gauche à droite évalué dans une question. Cependant la priorité d'opérateur peut être dépassée utilisant des parenthèses comme montrée par l'exemple suivant.
select ".xset.xuid" where not "com.example.bool-prop" and "com.example.int-prop" = 64
select ".xset.xuid" where not ("com.example.bool-prop" and "com.example.int-prop" = 64)
Dans le premier exemple, pas l'opérateur s'applique seulement à la propriété de com.example.bool-prop. Dans le deuxième exemple, pas l'opérateur s'applique à com.example.bool-prop et à com.example.int-prop = 42.
Maintenant que nous sommes quelque peu au courant de la syntaxe de XAM QL, la prochaine question à répondre est comment nous disons un système de stockage de XAM d'exécuter une question et de nous renvoyer les résultats. Bien elle s'avère qu'une question est exécutée comme un type particulier de travail de XAM a appelé un travail de question. L'entrée à un travail de question est un XSet que vous devez créer. Ce XSet doit contenir deux articles - le mand d'org.snia.xam.job.com de champ qui est toujours placé au `xam.job.query et à un mand de XStream xam.job.query.com qui est un jet des textes UTF-8 (type texte de MIME de `/plat ; charset=utf-8') contenir la corde réelle d'expression de question.
Un travail de question peut sur option être commis avant ou pendant l'exécution du travail, mais ceci commettent n'est pas exigé. La capacité de commettre un JOB en cours d'exécution est personne à charge facultative et d'exécution. Une application peut déterminer si le travail commettent est soutenu en vérifiant la propriété booléenne .xsystem.job.com mit.supported de XSystem. Le manque de commettre un travail de question avant que la fermeture du XSet signifie les résultats du travail de question ne sont pas constamment stockés.
Un travail de question est exécuté en appelant le submitJob. Si l'un ou l'autre des deux articles exigés dans le travail XSet de question n'est pas correctement complété, le champ standard .xam.job.error d'erreur du travail est ajouté au travail XSet de question et c'est valeur est placé à l'un ou l'autre org.snia.xam : : not_a_job ou org.snia.xam : : l'unspecified_command et le travail de question est avorté. Suivant les indications de l'application d'échantillon ci-dessous, l'état d'un travail de question peut être déterminé en examinant la valeur de .xam.job.status.
Quand un travail de question est réussi, les résultats sont stockés dans le travail XSet de question sous forme de nouveau XStream appelé xam.job.query.results. Ce XStream a un type de MIME d'application/vnd.snia.xam.query.xuid_list et contient le XUIDs pour l'ensemble de XSets résultant de l'évaluation de la question. Chaque XUID est stocké dans un format binaire en tant qu'élément d'un disque de 80 octets. Si un XUID est plus court que 80 bytes, le disque est zéro capitonné à 80 bytes.
Un certain nombre d'autres propriétés concernant les résultats XStream sont également installées. La propriété xam.job.query.results.count de xam_int contient le compte courant des disques de XUID dans les résultats XStream. Cette propriété est mise à jour comme résultat sont écrits dans les résultats XStream pendant le traitement de question. Une application peut employer ceci pour fournir des informations de statut aux utilisateurs pendant que le travail de question s'exécute. La propriété xam_string xam.job.query.level indique le niveau de question qui assortit les résultats. Sa valeur est org.snia.xam.job.query.level.1 ou org.snia.xam.job.query.level.2.
Il est important de se rappeler qu'un travail de question fonctionne dans les rôles et les permissions accordés au raccordement. Cela signifie que les résultats XStream inclut seulement ces XSets qui sont évidents et accessibles à une application, au moins d'une perspective lue, selon le rôle sous lequel le travail de question est exécuté.
Le travail de question peut placer les codes d'erreur suivants dans .xam.job.error :
| xam.job.query : : level_not_supported | Le système de stockage de XAM ne peut pas soutenir le niveau de question spécifique dans le travail de question. Une erreur non fatale. |
| xam.job.query : : invalid_command_syntax | Une erreur de syntaxe non fatale s'est produite tout en analysant la corde de question |
| xam.job.query : : insufficient_permission | L'utilisateur actuellement authentifié n'a pas suffisamment permission d'exécuter le travail de question |
| xam.job.query : : insufficient_resources | Le système de stockage de XAM n'a pas les ressources suffisantes pour accomplir le travail de question |
Quand un travail de question est arrêté pour quelque raison, la santé standard du travail et des zones STATUS, c.-à-d. .xam.job.errorhealth et .xam.job.status, soit placée pour s'approprier des valeurs et le système de stockage de XAM peut placer XUIDs zéro ou plus additionnels dans les résultats XStream. Ainsi une application devrait toujours voir des valeurs complètes de XUID dans les résultats XStream. La reprise d'un travail arrêté de question n'est pas soutenue.
Notez que, à la différence d'un RDBMS traditionnel, il n'y a aucun verrouillage d'un système de stockage de XAM pendant l'exécution d'un travail de question. Ainsi un résultat de question n'est pas un instantané instantané d'un système de stockage de XAM. Le contenu d'un système de stockage de XAM peut ou peut ne pas changer tandis qu'un travail de question est exécuté. La règle générale est qu'aucun XSet qui a été stocké avant que le début du travail de question soit inclus dans les résultats XStream s'il répond aux critères de question, et aucun XSet qui a été stocké après que le travail de question ait accompli ne doit être inclus dans les résultats XStream. XSets qui sont stockés pendant l'exécution d'une tâche de question peut ou peut ne pas être inclus. Les mêmes critères s'applique aux résultats XStream. Il peut inclure XUIDs de XSets qui ne sont plus dans le système de stockage de XAM et le XUIDs de XSets qui ne répondent plus aux critères de recherche dus à un changement du XSet après que le détail XSet ait été questionné.
Voici une application de Java simple qui questionne un système de stockage de XAM pour le déterminer est niveau de soutien des questions de XAM.
import org.snia.xam.XAMException;
import org.snia.xam.XAMLibrary;
import org.snia.xam.XSystem;
import org.snia.xam.toolkit.XAMXUID;
import org.snia.xam.util.XAMLibraryFactory;
public class CheckQuerySupport
{
private static XAMLibrary xamLib;
private static XSystem xSystem;
public static void main(String[] args)
{
String xri = "snia-xam://centera_vim!XXX.XXXX.XXX.XXX?/home/fpm/xam/xamconnect.pea";
long exitCode = 0;
boolean isSupported = false;
try
{
xamLib = XAMLibraryFactory.newXAMLibrary();
System.out.println("Connecting to XSystem: " + xri + "\n");
xSystem = xamLib.connect(xri);
// support job commit?
isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_COMMIT_SUPPORTED);
System.out.println("Support job commit? " + (isSupported ? "Yes" : "No"));
// support continuance of job?
isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_QUERY_CONTINUANCE_SUPPORTED);
System.out.println("Support job continuance? " + (isSupported ? "Yes" : "No"));
// support level 1 query?
isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_QUERY_LEVEL1_SUPPORTED);
System.out.println("Support level 1 query? " + (isSupported ? "Yes" : "No"));
// support level 2 query?
isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_QUERY_LEVEL2_SUPPORTED);
System.out.println("Support level 2 query? " + (isSupported ? "Yes" : "No"));
xSystem.close();
System.out.println("\nClosed connection to XSystem");
} catch (XAMException xe) {
exitCode = xe.getStatusCode();
System.err.println("XAM Error occured: " + xe.getMessage());
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
e.printStackTrace();
exitCode = 1;
}
System.exit((int) exitCode);
}
}
Voici le rendement de cette application une fois relié à un système de stockage d'EMC Centera XAM
Connecting to XSystem: snia-xam://centera_vim!XXX.XXX.XXX.XXX?/home/fpm/xam/xamconnect.pea Support job commit? No Support job continuance? No Support level 1 query? Yes Support level 2 query? No Closed connection to XSystem
Voici une plus longue application de Java qui met en application trois l'échantillon XSets et les questions d'échantillon qui sont discutés dans la section 10.8 du document de l'architecture V1.0 de XAM.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.snia.xam.XAMException;
import org.snia.xam.XAMLibrary;
import org.snia.xam.XSet;
import org.snia.xam.XStream;
import org.snia.xam.XSystem;
import org.snia.xam.XUID;
import org.snia.xam.toolkit.XAMXUID;
import org.snia.xam.util.XAMLibraryFactory;
public class QueryExample
{
private static XAMLibrary xamLib;
private static XSystem xSystem;
private static void CreateXset(int parm1, String parm2, double parm3)
throws XAMException
{
System.out.print("Create XSet 1 .... ");
XSet xSet = xSystem.createXSet(XSet.MODE_UNRESTRICTED);
xSet.createProperty("com.example.rhc", false, true);
xSet.createProperty("com,example.foo", false, parm1);
xSet.createProperty("com.example.bar", false, parm2);
xSet.createProperty("com.example.num", false, parm3);
XUID xuID = xSet.commit();
System.out.println("XUID: " + xuID.toString());
xSet.close();
}
private static void CreateXset(int parm1, int parm2, int parm3)
throws XAMException
{
System.out.print("Create XSet 2 .... ");
XSet xSet = xSystem.createXSet(XSet.MODE_UNRESTRICTED);
xSet.createProperty("com.example.rhc", false, true);
xSet.createProperty("com,example.foo", false, parm1);
xSet.createProperty("com.example.bar", false, parm2);
xSet.createProperty("com.example.num", false, parm3);
XUID xuID = xSet.commit();
System.out.println("XUID: " + xuID.toString());
xSet.close();
}
private static void CreateXset(int parm1, int parm2)
throws XAMException
{
System.out.print("Create XSet 3 .... ");
XSet xSet = xSystem.createXSet(XSet.MODE_UNRESTRICTED);
xSet.createProperty("com.example.rhc", false, true);
xSet.createProperty("com,example.foo", false, parm1);
xSet.createProperty("com.example.num", false, parm2);
XUID xuID = xSet.commit();
System.out.println("XUID: " + xuID.toString());
xSet.close();
}
private static void QueryXsystem(String queryString)
throws XAMException
{
boolean finished = false;
final int XAM_MAX_XUID = 80;
int resultCount = 0;
String status;
System.out.println("Create query XSet. Query string: " + queryString);
XSet query = xSystem.createXSet(XSet.MODE_UNRESTRICTED);
query.createProperty(XSet.XAM_JOB_COMMAND, true, XSet.XAM_JOB_QUERY);
byte[] buffer = queryString.getBytes();
XStream queryStream = query.createXStream(XSet.XAM_JOB_QUERY_COMMAND, true, XAMLibrary.TEXT_PLAIN_MIME_TYPE);
queryStream.write(buffer);
queryStream.close();
System.out.println("Submit query job ....");
query.submitJob();
System.out.println("Wait for query job to finish ....");
while (!finished)
{
// check status of query job
status = query.getString(XSet.XAM_JOB_ERRORHEALTH);
if (status.equals(XSet.XAM_JOB_ERRORHEALTH_ERROR))
{
System.out.println("ERROR: Errorhealth - " + query.getString(XSet.XAM_JOB_ERROR));
query.haltJob();
System.out.println("ERROR: Job halted");
break;
}
status = query.getString(XSet.XAM_JOB_STATUS);
resultCount = (int) query.getLong(XSet.XAM_JOB_QUERY_RESULTS_COUNT);
// uncomment if you want continuous job status
// System.out.println("Job Status: " + status + " Result count: " + resultCount);
// exit loop if job complete
if (status.equals(XSet.XAM_JOB_STATUS_COMPLETE))
{
finished = true;
}
}
System.out.println("Query job completed ....");
System.out.println("Result set final count is: " + resultCount);
if (resultCount > 0)
{
// open query job result stream
XStream results = query.openXStream(XSet.XAM_JOB_QUERY_RESULTS, XStream.MODE_READ_ONLY);
byte rawXUID[] = new byte[XAM_MAX_XUID];
long bytesRead = 0;
// output XUIDs in result set
while( (bytesRead = results.read(rawXUID, XAM_MAX_XUID)) >= 0 )
{
XAMXUID resultXUID = new XAMXUID(rawXUID);
System.out.println("XUID: " + resultXUID.toString());
}
results.close();
}
query.close();
}
public static void main(String[] args)
{
String xri = "snia-xam://centera_vim!XXX.XXX.XXX.XXX?/home/fpm/xam/xamconnect.pea";
long exitCode = 0;
try
{
xamLib = XAMLibraryFactory.newXAMLibrary();
// uncomment next 2 lines if you want extensive XAM Library logging
// xamLib.setProperty(XAMLibrary.XAM_LOG_VERBOSITY, 1);
// xamLib.setProperty(XAMLibrary.XAM_LOG_LEVEL, 5);
System.out.println("Connecting to XSystem " + xri + "\n");
xSystem = xamLib.connect(xri);
xSystem.setProperty(".xsystem.log.verbosity", 1);
xSystem.setProperty(".xsystem.log.level", 5);
CreateXset(1, "string", 123.55);
CreateXset(77, 42, 100);
CreateXset(6, 200);
xSystem.close();
System.out.println("\nClose/reopen XSystem\n");
xSystem = xamLib.connect(xri);
// uncomment one or more of the following queries
// QueryXsystem("select \".xset.xuid\"");
QueryXsystem("select \".xset.xuid\" where (\"com.example.foo\" > 0) and (\"com.example.foo\" < 50)");
// QueryXsystem("select \".xset.xuid\" where (\"com.example.bar\" > 0) and (\"com.example.bar\" < 100)");
// QueryXsystem("select \".xset.xuid\" where exists (\"com.example.bar\")");
// QueryXsystem("select \".xset.xuid\" where \"com.example.bar\" like '%ing%'");
// QueryXsystem("select \".xset.xuid\" where \"com.example.num\" >= 124");
// QueryXsystem("select \".xset.xuid\" where \"com.example.num\" >= 124.6 ");
// QueryXsystem("select \".xset.xuid\" where (\"com.example.num\" >= 123) and typeof(\"com.example.num\") = 'application/vnd.snia.xam.int'");
xSystem.close();
System.out.println("\nClosed connection to XSystem");
} catch (XAMException xe) {
exitCode = xe.getStatusCode();
System.err.println("XAM Error occured: " + xe.getMessage() + "("
+ exitCode + ")");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
e.printStackTrace();
exitCode = -1;
}
System.exit((int) exitCode);
}
}
Notez que des résultats XStream produit par un travail de question peuvent être consommés par une application avant que le système de stockage de XAM ait fini de stocker tout les XUIDs dans les résultats XStream si XStream.asyncRead est employé au lieu de XStream.read.
Bien je pense que j'ai fourni assez d'information et d'exemples pour te permettre d'aller jeu avec le langage d'interrogation de XAM par vous-même. Il vous a besoin de l'aide je suis sûr que le groupe de réalisateur de XAM sur des groupes de Google sera davantage qu'heureux de vous aider.
Dans le départ je préciserais que puisque des fournisseurs de système de stockage de XAM actuellement sont seulement exigés pour mettre en application le soutien des questions au-dessus des méta-données contentes, je suspecte que le soutien des recherches complètement contenu-basées réelles utilisant XAM puisse ne pas se produire pendant quelque temps.






















