Changes for page How to read Train IDs at FLASH
Last modified by sndueste on 2024/03/13 14:48
Summary
-
Page properties (2 modified, 0 added, 0 removed)
-
Attachments (0 modified, 0 added, 11 removed)
Details
- Page properties
-
- Tags
-
... ... @@ -1,1 +1,0 @@ 1 -how-to|favourite - Content
-
... ... @@ -1,7 +1,6 @@ 1 -(% class="twikiTocTitle" %)Content 1 +== 2 + == 2 2 3 - 4 - 5 5 {{toc/}} 6 6 7 7 == Introduction == ... ... @@ -21,9 +21,7 @@ 21 21 * using a provided program (AdvancedIDServer.exe) running on the user's machine, that synchronizes with the Train ID sender and uses the local clock of the user computer to lower the jitter in reading the ID significantly. The user program connects then locally to the AdvancedIDServer program to get the ID ... 22 22 * direct reading of the ID via TCP socket 23 23 24 -[[image:attach:aids_principle.png||height="400"]] 25 - 26 - 23 +[[~[~[image:url:http://hasfweb.desy.de/pub/Setup/TrainID/aids_principle.png~|~|alt="aids_principle.png" width="440" height="289"~]~]>>attach:aids_principle.png]] 27 27 Basic pinciple of Train ID distribution at Flash1 with TIDS and AIDS 28 28 29 29 See also this [[sketch>>attach:timing.png]] of the sequence with miliseconds attached to it, to see when the ID updates relative to the beam. ... ... @@ -36,22 +36,23 @@ 36 36 37 37 === What does //Advanced ID Server// do? === 38 38 39 -It connects to the TCP based TIDS server and continuously gets the Ethernet packets with the IDs. These packets are time stamped with microsecond resolution and stored. This runs all the time. Because we have a lot of data we can correlate the local time on that machine (that generated the local time stamps) and the IDs. If the Ethernet connection lags sometimes, chokes, hick ups and messes around with our packets, even drops some... Who cares. By closely monitoring all data we can define a function to calculate the Train ID from the local time on that machine. 36 +It connects to the TCP based TIDY or TIDS server and continuously gets the Ethernet packets with the IDs. These packets are time stamped with microsecond resolution and stored. This runs all the time. Because we have a lot of data we can correlate the local time on that machine (that generated the local time stamps) and the IDs. If the Ethernet connection lags sometimes, chokes, hick ups and messes around with our packets, even drops some... Who cares. By closely monitoring all data we can define a function to calculate the Train ID from the local time on that machine. 40 40 41 -[[image: attach:AIDS_running.png||height="189"]]38 +[[~[~[image:url:http://hasfweb.desy.de/pub/Setup/TrainID/AIDS_running.png~|~|alt="Advanced ID Server running"~]~]>>attach:AIDS_running.png]] 42 42 40 +* Short presentation by Fini 43 43 44 44 Here it is running on Windows, but of course you can also use it on your Linux machine (build it from the source). 45 45 44 +\\ 46 46 47 47 The users can access this server via a socket. Use localhost:58051. Connect your program to that socket and you get immediately the actual Train ID for this very moment. (e.g. in the CMD window with {{code language="none"}}telnet localhost 58051{{/code}} ... note:telnet is usually deactivated in win10 and has to be activated) The packet you get looks like this: 48 48 49 -{{code language="none"}} 50 -3437004.37997 O 818 853 51 -{{/code}} 48 +{{code language="none"}}3437004.37997 O 818 853{{/code}} 52 52 53 53 You get a new calculated ID every time you send any data to the server. So normally your program looks like this and should not close and open the socket all the time: 54 54 52 +\\ 55 55 56 56 * Connect to AdvancedIDServer. 57 57 * Check the state flag and jitter number in the first packet. Ignore the ID. ... ... @@ -62,8 +62,8 @@ 62 62 ** save your aquired data with that ID 63 63 * until shift finished or FLASH lost beam 64 64 65 -{{code language="none"}}3437004.37997 O 818 853{{/code}} 66 -{{code language="none"}}3437005.37997 O 851 889{{/code}} 63 +{{code language="none"}}3437004.37997 O 818 853{{/code}} 64 +{{code language="none"}}3437005.37997 O 851 889{{/code}} 67 67 {{code language="none"}}3437006.35997 O 885 925{{/code}} 68 68 69 69 About the format: More abstract you get a number, dot, a second number. A character. A third and fourth number. ... ... @@ -88,13 +88,15 @@ 88 88 89 89 [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]]{{code language="none"}}AdvancedIDServer.exe :58050{{/code}} //(for Flash1)// or [[flash2cpuxgmd2.desy.de>>url:http://flash2cpuxgmd2.desy.de||shape="rect"]]{{code language="none"}}AdvancedIDServer.exe :58050{{/code}} //(for Flash2)// 90 90 89 +\\ 91 91 92 92 === Resources: === 93 93 94 94 * [[attach:AdvancedIDServer.exe]] 95 95 * [[attach:AdvancedIDServer-inline.vi]]: Example how to use the Advanced ID Server with Labview (LV11) 96 -* [[AdvancedIDServer on github>>url:https://github.com/Finii/AdvancedIDServer||shape="rect"]] 95 +* [[AdvancedIDServer on github~[~[image:url:http://hasfweb.desy.de/pub/TWiki/TWikiDocGraphics/external-link.gif~|~|width="13" height="12"~]~]>>url:https://github.com/Finii/AdvancedIDServer||shape="rect"]] 97 97 97 +[[Contents>>doc:||anchor="Contents"]] 98 98 99 99 == Direct reading of Train ID == 100 100 ... ... @@ -105,6 +105,7 @@ 105 105 106 106 * [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]]:58050 (TIDY (//for Flash1//)) 107 107 * [[flash2cpuxgmd2.desy.de>>url:http://flash2cpuxgmd2.desy.de||shape="rect"]]:58050 (TIDY (//for Flash2//)) 108 +* [[hasfhvctrl.desy.de>>url:http://hasfhvctrl.desy.de||shape="rect"]]:58050 (TIDS) (obsolete) 108 108 109 109 Please see also the sample code for [[C>>attach:bunch-id_readout.c]] and [[LabView 14>>attach:bunch-id_readout.vi]]. Example how to embed the ethernet Train ID code into your Labview project (LV 8.6): [[attach:BunchID-inline.vi]]. We have also [[C++ code>>attach:event-reader.hh]] which can be used to be integrate into existing projects. 110 110 ... ... @@ -135,8 +135,24 @@ 135 135 136 136 The time and date have leading zeros as necessary to ensure a constant field width. The ID number is not zero padded and thus has a varying field width. 137 137 139 +[[Contents>>doc:||anchor="Contents"]] 138 138 141 +== Train ID sender program (TIDS) //obsolete// == 139 139 143 +The sender program is currently running on [[hasfhvctrl.desy.de>>url:http://hasfhvctrl.desy.de||shape="rect"]]. It can be restarted if there are problems (Event_ID_Server). It can be changed to continuously delivers Train IDs (uncheck "fast shutter eventIDs") or deliver IDs only if the fast shutter is open at this moment (check "fast shutter eventIDs" as in the example below). 144 + 145 +Address: 146 + 147 +* [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]]:58050 148 + 149 +Do not enable "fast shutter eventIDs" if you want to use the Advanced ID Server. 150 + 151 +[[~[~[image:url:http://hasfweb.desy.de/pub/Setup/TrainID/Clipboard02.png~|~|alt="Clipboard02.png" width="470" height="420"~]~]>>attach:Clipboard02.png]] 152 + 153 +The TIDY: known issues also apply here. 154 + 155 +[[Contents>>doc:||anchor="Contents"]] 156 + 140 140 == Train ID Yelling server (TIDY) == 141 141 142 142 As alternative to the Train ID sender you can use this server. These are the differences: ... ... @@ -154,6 +154,8 @@ 154 154 * [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]]:58050 //(for Flash1)// 155 155 * [[flash2cpuxgmd2.desy.de>>url:http://flash2cpuxgmd2.desy.de||shape="rect"]]:58050 //(for Flash2)// 156 156 174 +\\ 175 + 157 157 === Known Issues === 158 158 159 159 * If you write code to read the train-ID please make sure you close the socket properly. Otherwise it can happen that you eat up all available connections. ... ... @@ -160,9 +160,12 @@ 160 160 ** If you can not guaranty that the socket will be closed properly the best solution is to use always the same (client-)port number. 161 161 ** You can also change your system-settings to let the OS handle it (see tcp_keepalive_time). 162 162 182 +\\ 183 + 163 163 * 20.9.18: The .exe always try [[hasfhvctrl.desy.de>>url:http://hasfhvctrl.desy.de||shape="rect"]] first. So start with additional parameter via the commandline. 164 164 [[attach:AdvancedIDServer.exe]] [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]] 165 165 187 +[[Contents>>doc:||anchor="Contents"]] 166 166 167 167 == Short presentation by Fini == 168 168
- AIDS_running.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -5.4 KB - Content
- AdvancedIDServer-inline.vi
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -16.2 KB - Content
- AdvancedIDServer.exe
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -129.9 KB - Content
- BunchID-inline.vi
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -32.1 KB - Content
- Clipboard02.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -103.0 KB - Content
- aids_principle.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -40.5 KB - Content
- bunch-id_readout.c
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -5.3 KB - Content
-
... ... @@ -1,226 +1,0 @@ 1 -/* 2 - * Copyright 2014, DESY 3 - * 4 - * This program is free software; you can redistribute it and/or modify it 5 - * under the terms of the GNU General Public License as published by the 6 - * Free Software Foundation; either version 2 of the License, or (at your 7 - * option) any later version. 8 - */ 9 - 10 -#ifdef WIN32 11 -# ifdef _MSC_VER 12 -# undef UNICODE 13 -# define _CRT_SECURE_NO_WARNINGS 14 -# define snprintf _snprintf_s 15 -# pragma comment(lib, "ws2_32.lib") 16 -# endif 17 -# include <winsock2.h> 18 -# include <ws2tcpip.h> 19 -# include <stdio.h> 20 -# include <stdlib.h> 21 -# include <string.h> 22 -# include <errno.h> 23 -#else 24 -# include <errno.h> 25 -# include <stdio.h> 26 -# include <stdlib.h> 27 -# include <string.h> 28 -# include <unistd.h> 29 -# include <sys/types.h> 30 -# include <sys/socket.h> 31 -# include <netinet/in.h> 32 -# include <netdb.h> 33 -#endif 34 - 35 -/* SO_REUSEPORT is not supported by older systems 36 - * 37 - * see http://stackoverflow.com/questions/3261965/so-reuseport-on-linux 38 - * > On Linux, SO_REUSEADDR provide most of what SO_REUSEPORT 39 - * > provides on BSD. */ 40 -#ifndef SO_REUSEPORT 41 -#define SO_REUSEPORT SO_REUSEADDR 42 -#endif 43 - 44 -#ifndef ARRAY_SIZE 45 -#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) 46 -#endif 47 - 48 -#define MAX_HOSTNAME_LEN 128 49 -#define MAX_SERVICE_LEN 32 50 - 51 -#define DEFAULT_HOSTNAME "hasfhvctrl" 52 -#define DEFAULT_SERVICE "58050" 53 - 54 -static int parse_and_print(const char *str) 55 -{ 56 - int hour = 0, minute = 0, second = 0, msecond = 0; 57 - int year = 0, month = 0, day = 0; 58 - int eventid = 0; 59 - int ret; 60 - 61 - ret = sscanf(str, "%2d%2d%2d %2d%2d%2d.%3d %x\n", 62 - &year, &month, &day, &hour, &minute, &second, &msecond, 63 - &eventid); 64 - if (ret != 8) { 65 - fprintf(stderr, "Parsing [%s] failed\n", str); 66 - return -EINVAL; 67 - } 68 - 69 - printf("%02d%02d%02d %02d%02d%02d.%03d %X\n", 70 - year, month, day, hour, minute, second, msecond, 71 - eventid); 72 - return 0; 73 -} 74 - 75 -/* 76 - * This sample shows the basic steps needed to receive the Event-ID. 77 - * 78 - * 0) Do some commanline parsing 79 - * 1) Open a socket to the server providing the data 80 - * a) Resolve the hostname 81 - * b) Create the socket 82 - * c) Bind to specific local port (optional) 83 - * d) Connect to the remote machine 84 - * 2) Wait for data 85 - * 3) Read the data and parse it 86 - * 4) Do something with it (print them) 87 - * 5) Back to step 2 88 - * 89 - * To build it under linux type: 90 - * gcc -o bunchid bunch-id_readout.c 91 - */ 92 -int main(int argc, char *argv[]) 93 -{ 94 -#ifdef WIN32 95 - WSADATA wsaData; 96 -#endif 97 - char hostname[MAX_HOSTNAME_LEN]; 98 - char service[MAX_SERVICE_LEN]; 99 - struct addrinfo *ai = NULL; 100 - struct sockaddr_in local; 101 - struct addrinfo hints; 102 - struct timeval to; 103 - char buffer[128]; 104 - fd_set fdset; 105 - int opt = 1; 106 - int sockfd; 107 - int ret; 108 - int i; 109 - 110 - /* check for user input */ 111 - switch (argc) { 112 - case 1: 113 - /* no arguments given */ 114 - strcpy(hostname, DEFAULT_HOSTNAME); 115 - strcpy(service, DEFAULT_SERVICE); 116 - break; 117 - case 2: 118 - snprintf(hostname, ARRAY_SIZE(hostname), "%s", argv[1]); 119 - strcpy(service, DEFAULT_SERVICE); 120 - break; 121 - case 3: 122 - snprintf(hostname, ARRAY_SIZE(hostname), "%s", argv[1]); 123 - snprintf(service, ARRAY_SIZE(service), "%s", argv[2]); 124 - break; 125 - default: 126 - printf("usage: %s [hostname] [port]\n", argv[0]); 127 - return 1; 128 - } 129 - 130 -#ifdef WIN32 131 - memset(&wsaData, 0, sizeof(wsaData)); 132 - ret = WSAStartup(MAKEWORD(2, 2), &wsaData); 133 - if (ret != 0) { 134 - printf("Init winsock failed\r\n"); 135 - return 1; 136 - } 137 -#endif 138 - 139 - printf("Connecting to %s:%s...\n", hostname, service); 140 - 141 - /* prepare variables */ 142 - memset(buffer, 0, ARRAY_SIZE(buffer)); 143 - memset(&hints, 0, sizeof(hints)); 144 - hints.ai_family = AF_INET; 145 - hints.ai_socktype = SOCK_STREAM; 146 - 147 - /* resolve hostname */ 148 - ret = getaddrinfo(hostname, service, &hints, &ai); 149 - if (ret < 0) { 150 - fprintf(stderr, "Unable to resolve: %s: %s\n", 151 - hostname, gai_strerror(-ret)); 152 - return -ENOENT; 153 - } 154 - /* open tcp socket */ 155 - sockfd = socket(AF_INET, SOCK_STREAM, 0); 156 - if (sockfd < 0) { 157 - fprintf(stderr, "socket failed: %s\n", 158 - strerror(errno)); 159 - goto cleanup; 160 - } 161 - 162 - /* allow port reuse (optional, linux only) */ 163 - ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt)); 164 - if (ret < 0) 165 - fprintf(stderr, "setsockopt failed: %s\n", strerror(errno)); 166 - 167 - /* bind to specific local port (optional) */ 168 - memset(&local, 0, sizeof(local)); 169 - local.sin_family = AF_INET; 170 - local.sin_addr.s_addr = INADDR_ANY; 171 - local.sin_port = htons(atoi(DEFAULT_SERVICE)); 172 - 173 - ret = bind(sockfd, (const struct sockaddr *)&local, sizeof(local)); 174 - if (ret < 0) { 175 - fprintf(stderr, "bind to port " DEFAULT_SERVICE 176 - " failed: %s\n", strerror(errno)); 177 - goto cleanup; 178 - } 179 - 180 - /* connect to remote machine */ 181 - ret = connect(sockfd, ai->ai_addr, ai->ai_addrlen); 182 - if (ret < 0) { 183 - fprintf(stderr, "connect to %s:%s failed: %s\n", 184 - hostname, service, strerror(errno)); 185 - goto cleanup; 186 - } 187 - 188 - FD_ZERO(&fdset); 189 - 190 - /* enter receive loop */ 191 - printf("YYMMDD HHMMSS.mmm BUNCHID\n"); 192 - for (i = 0; i < 3; i++) { 193 - /* reset timeout, see select recommendations */ 194 - to.tv_sec = 10; 195 - to.tv_usec = 0; 196 - FD_SET(sockfd, &fdset); 197 - /* wait for data */ 198 - ret = select(sockfd+1, &fdset, NULL, NULL, &to); 199 - if (ret < 0) { 200 - fprintf(stderr, "select failed with: %d -> %d -> %s\n", 201 - ret, errno, strerror(errno)); 202 - break; 203 - } 204 - /* read bunch-id */ 205 - ret = recv(sockfd, buffer, ARRAY_SIZE(buffer), 0/*flags*/); 206 - if (ret < 0) { 207 - fprintf(stderr, "receive from %s:%s failed: %s\n", 208 - hostname, service, strerror(errno)); 209 - goto cleanup; 210 - } 211 - /* print bunch-id */ 212 - parse_and_print(buffer); 213 - } 214 - 215 -cleanup: 216 - freeaddrinfo(ai); 217 - if (sockfd) 218 -#ifdef WIN32 219 - closesocket(sockfd); 220 - WSACleanup(); 221 -#else 222 - close(sockfd); 223 -#endif 224 - return 0; 225 -} 226 -
- bunch-id_readout.vi
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -7.3 KB - Content
- event-reader.hh
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -3.7 KB - Content
-
... ... @@ -1,165 +1,0 @@ 1 -/* 2 - * Copyright 2015-2016, DESY 3 - * 4 - * This program is free software; you can redistribute it and/or modify it 5 - * under the terms of the GNU General Public License as published by the 6 - * Free Software Foundation; either version 2 of the License, or (at your 7 - * option) any later version. 8 - * 9 - * NOTE: 10 - * Under windows a recent PSDK is required. Feb 2003 is last known to 11 - * work with WinXP and VC6. 12 - */ 13 - 14 -#ifdef WIN32 15 -# include <winsock2.h> // struct timeval 16 -#else 17 -# include <stdint.h> 18 -#endif 19 - 20 -#include <time.h> 21 -#include <string> 22 - 23 -#pragma once 24 - 25 -/** 26 - * This interface can be used to pass messages from the event reader 27 - * to the embedding application. 28 - */ 29 -struct ILogger { 30 - 31 - /** message severity */ 32 - enum Level { 33 - LEVEL_ERROR, 34 - LEVEL_WARNING, 35 - LEVEL_INFO, 36 - LEVEL_DEBUG 37 - }; 38 - 39 - virtual ~ILogger() {} 40 - 41 - /** 42 - * Writes a message from the EventReader. 43 - * 44 - * @param lvl[in] The severity of the message 45 - * @param msg[in] The message to print 46 - */ 47 - virtual void log(enum Level in, const char *msg) = 0; 48 -}; 49 - 50 -#if defined(WIN32) && (_MSC_VER < 1300) 51 -typedef signed __int64 int64_t; 52 -typedef unsigned __int64 uint64_t; 53 -#endif 54 - 55 -/** 56 - * This collects all event data 57 - */ 58 -struct EventInfo { 59 - /** The event id */ 60 - uint64_t id; 61 - /** When did the event appear */ 62 - struct timeval time; 63 - 64 - /** Create a blank info object */ 65 - EventInfo() : id(-1) { } 66 -}; 67 - 68 -/** 69 - * This is the interface definition for event listeners. 70 - * 71 - * Implement this interface to register at the event-source 72 - * and become notified. 73 - */ 74 -struct IEventIDListener 75 -{ 76 - virtual ~IEventIDListener() {} 77 - /** 78 - * Called when-ever a new event-id is available. 79 - * 80 - * @param event[in] The new event-info 81 - */ 82 - virtual void updateEventInfo(const struct EventInfo &) = 0; 83 - /** 84 - * Called if we have lost the connection and the will be no more 85 - * event notifications. 86 - * 87 - * @param err[in] The error code leading to the problem 88 - */ 89 - virtual void connectionLost(int) { /* dummy */ } 90 -}; 91 - 92 -/** 93 - * This class wraps the required code to receive event notifications. 94 - * 95 - * It is implemented as singleton, so it is easy to handle within existing 96 - * code bases. Please note that the notification is not async, so if your 97 - * listener is blocking or delaying the call you will run into trouble. 98 - * 99 - * Usage: 100 - * 101 - * Implement you own IEventIDListener 102 - * Register your listener on the reader 103 - * Connect the reader to the source 104 - * 105 - * Now you will receive updated event information 106 - */ 107 -class EventReader 108 -{ 109 - EventReader() {} 110 - /* Do not allow to create a copy of the instance */ 111 - EventReader(const EventReader&) { } 112 - EventReader& operator=(const EventReader&) { return *this; } 113 - 114 -public: 115 - ~EventReader() {} 116 - /** 117 - * Returns the only allowed instance. 118 - */ 119 - static EventReader* getInstance(); 120 - 121 - /** 122 - * (Un/)Register listeners from the event reader. 123 - * 124 - * @param listener[in] The listener to (un-)register. 125 - * 126 - * @see #enableNotification 127 - */ 128 - void registerListener(IEventIDListener *); 129 - void unregisterListener(IEventIDListener *); 130 - /** 131 - * (Re)connect to the event source 132 - * 133 - * @param host[in] The host to connect to. 134 - * @param port[in] The server to use. 135 - * 136 - * @return 0 on success, otherwise negative error code. 137 - * 138 - * @see #enableNotification 139 - */ 140 - int connect(const std::string &, unsigned); 141 - 142 - /** 143 - * Enable or disable the notification 144 - */ 145 - void enableNotification(bool enable = true); 146 - bool notificationEnabled() const; 147 - 148 - /** 149 - * Requests the latest available info set. This provides 150 - * the same information as the callback, but on request. 151 - * The notification can be set to off. 152 - * 153 - * @param event[out] The info to fill. 154 - */ 155 - void getRecent(struct EventInfo &event); 156 - 157 - /** 158 - * Assigns the logger to be used to write messages. If NULL is 159 - * passed, the default logger is used again. 160 - * 161 - * @param logger[in] The new logger to use 162 - */ 163 - void setLogger(struct ILogger *logger); 164 -}; 165 -
- eventid.pdf
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -1.4 MB - Content
- timing.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.XWikiGuest - Size
-
... ... @@ -1,1 +1,0 @@ 1 -211.5 KB - Content