TFS Meltdown - How can I recover shelved changes - visual-studio-2010
I had my working folder set to a RAM drive. During the night there was an extended power outage, the UPS ran out and my machine went down. Thankfully I shelved my changes before I went home and that shelveset is visible in Team Explorer. The changeset includes the project file and some new files which have not yet been added to source control.
I'm attempting to recover the affected files but am getting errors:
Attempting to view the shelved files gives TF10187 (or a general, unnumbered) The system cannot find the file specified even though I can see them in the Pending Changes list.
Attempting to unshelve the set in its entirety gives errors relating to incompatible changes which I can't resolve.
I'm guessing TFS cached the shelveset locally on the RAM disc which has since reinitialised itself and therefore lost the cache, but I'm hoping I'm wrong.
Can anyone assist?
I had someone come to me and ask the same question yesterday, fortunately they had a backup of the TFS Project database (tfs_) so we restored that to another database and I poked around and figured it out (so, if you have a backup then yes, you can recover all the files).
First of all a little info on the tables in the database.
A Shelveset can be identified by querying the tbl_Workspace table and looking for all records with Type=1 (Shelveset), you can of course also filter by name with the WorkspaceName column.
The other tables of interest are:
tbl_PendingChanges (which references the WorkspaceId from tbl_Workspace) - which files are part of the ShelveSet
tbl_VersionedItem (linked via ItemId column to tbl_PendingChanges) - parent path and name of files
tbl_Content (linked via FileId to PendingChanges) - this is where your file content is stored in as compressed (gzip) data
Now for the solution; the following query can show you your files:
SELECT c.[CreationDate], c.[Content], vi.[ChildItem], vi.ParentPath
FROM [dbo].[tbl_Content] c
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = c.FileId
INNER JOIN [dbo].[tbl_Workspace] w ON w.WorkspaceId = pc.WorkspaceId
INNER JOIN [dbo].[tbl_VersionedItem] vi ON vi.ItemId = pc.ItemId
WHERE w.WorkspaceName = '<YOUR SHELVESET NAME>'
With that I wrote some code to get the data back from SQL and then decompress the content with the GZipStream class and save the files off to disk.
A week of work was back in an hour or so.
This was done with TFS 2010.
Hope this helps!
Here is an updated response for TFS2015, which had another schema change. Below is a C# Console application for writing the txt files to Desktop. Make sure to fill in connString and shelvesetName variables.
using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.IO.Compression;
namespace RestoreTFSShelve
{
internal class Program
{
private static void Main(string[] args)
{
string shelvesetName = "";
string connString = "";
SqlConnection cn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(#"
SELECT c.[CreationDate], c.[Content], v.FullPath
FROM [dbo].[tbl_Content] c
INNER JOIN [dbo].tbl_FileMetadata f ON f.ResourceId = c.ResourceId
INNER JOIN [dbo].tbl_FileReference b ON f.ResourceId = b.ResourceId
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = b.FileId
INNER JOIN [dbo].[tbl_Workspace] w ON w.WorkspaceId = pc.WorkspaceId
INNER JOIN [dbo].[tbl_Version] v ON v.ItemId = pc.ItemId AND v.VersionTo = 2147483647
WHERE w.WorkspaceName = '#ShelvesetName'", cn);
cmd.Parameters.AddWithValue("#ShelvesetName", shelvesetName);
DataTable dt = new DataTable();
new SqlDataAdapter(cmd).Fill(dt);
foreach (DataRow row in dt.Rows)
{
string[] arrFilePath = row[2].ToString().Split('\\');
string fileName = arrFilePath[arrFilePath.Length - 2];
byte[] unzippedContent = Decompress((byte[])row[1]);
File.WriteAllBytes(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), fileName), unzippedContent);
}
}
private static byte[] Decompress(byte[] gzip)
{
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using (MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return memory.ToArray();
}
}
}
}
}
I had something similar happen to me with a TFS 2012 instance. My SQL query was a bit different since the schema changed for TFS 2012. Hope this helps someone.
SELECT c.[CreationDate], c.[Content], v.FullPath
FROM [dbo].[tbl_Content] c
INNER JOIN [dbo].[tbl_File] f ON f.ResourceId = c.ResourceId
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = f.FileId--c.FileId
INNER JOIN [dbo].[tbl_Workspace] w ON w.WorkspaceId = pc.WorkspaceId
INNER JOIN [dbo].[tbl_Version] v ON v.ItemId = pc.ItemId AND v.VersionTo = 2147483647
WHERE w.WorkspaceName = #ShelvesetName
2147483647 seems to be 2^32 - 1 which I think may stand for "latest" in TFS 2012. I then also wrote a C# widget to decompress the Gzip-encoded stream and dump it to disk with the proper file name. I am not preserving hierarchy.
string cnstring = string.Format("Server={0};Database={1};Trusted_Connection=True;", txtDbInstance.Text, txtDbName.Text);
SqlConnection cn = new SqlConnection(cnstring);
SqlCommand cmd = new SqlCommand(#"
SELECT c.[CreationDate], c.[Content], v.FullPath
FROM [dbo].[tbl_Content] c
INNER JOIN [dbo].[tbl_File] f ON f.ResourceId = c.ResourceId
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = f.FileId--c.FileId
INNER JOIN [dbo].[tbl_Workspace] w ON w.WorkspaceId = pc.WorkspaceId
INNER JOIN [dbo].[tbl_Version] v ON v.ItemId = pc.ItemId AND v.VersionTo = 2147483647
WHERE w.WorkspaceName = #ShelvesetName", cn);
cmd.Parameters.AddWithValue("#ShelvesetName", txtShelvesetName.Text);
DataTable dt = new DataTable();
new SqlDataAdapter(cmd).Fill(dt);
listBox1.DisplayMember = "FullPath";
listBox1.ValueMember = "FullPath";
listBox1.DataSource = dt;
if(!Directory.Exists(txtOutputLocation.Text)) { Directory.CreateDirectory(txtOutputLocation.Text); }
foreach (DataRow row in dt.Rows)
{
string[] arrFilePath = row[2].ToString().Split('\\');
string fileName = arrFilePath[arrFilePath.Length - 2];
byte[] unzippedContent = Decompress((byte[])row[1]);
File.WriteAllBytes(Path.Combine(txtOutputLocation.Text, fileName), unzippedContent);
}
}
static byte[] Decompress(byte[] gzip)
{
using(GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using(MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if(count > 0)
{
memory.Write(buffer, 0, count);
}
}
while(count > 0);
return memory.ToArray();
}
}
}
Related
Context Free Grammar for English Sounding Names
I am currently writing an application that will generate random data; specifically, random names. I have made some decent progress, but am not satisfied with many of the generated names. The problem lies in my production rules, which I've attached to the bottom of this post. The basic idea is: consonant, vowel, consonant, vowel, but some consonants themselves map to vowels (such as b< VO >). I have not fully created the rules yet, but the final idea would follow the format shown below. However, rather than finishing it, I would like to make a better basis for the production rules. I have tried to find a reference that discusses either: a CFG already created for English-sounding words, or an English reference that disassembles the basic format of letter combinations for words. Unfortunately, I have not been able to find a useful resource to help me advance farther than I already have. Does anyone know of a place I should look, or a reference I can look at? ALSO: in your opinion, do you believe a context-sensitive grammar might work better? //the following will deal with single vowels and consonants var CO = ['b','c','d','f','g','h','j','k','l','m','n','p','qu','r','s','t','v','w','x','y','z']; CO.probabilities = [2.41,4.49,6.87,3.59,3.25,9.84,0.24,1.24,6.5,3.88,10.9,3.11,0.153,9.67,10.2,14.6,1.58,3.81,0.242,3.19,0.12]; CO.name = "CO"; var VO = ['a','e','i','o','u']; VO.probabilities = [21.43,33.33,18.28,19.7,7.23]; VO.name = "VO"; var LETTER = ['<VO>','<CO>']; LETTER.probabilities = [38.1,61.9]; LETTER.name = "LETTER"; //the following deal with connsonant pairs var BH = ['c','p','r','s','t']; //the fisrt part of a th, ph, sh, pair (before H) BH.probabilities = [20,10,20,25,25]; BH.name = "BH"; var BL = ['b','c','f','g','p','s']; //before letter l BL.probabilities = [10,20,10,10,25,25] BL.name = "BL"; var COP = ['<BH>h','<BL>l'] //consonant pairs COP.probabilities = [50,50]; COP.name = "COP"; //this is a generic syllable, that does not take grammar rules into consideration var SYL = ['<CO><VO>','<VO><CO>','<CO><VO><VO>']; SYL.probabilities = [50,20,30]; SYL.name = "SYL"; //the following deal with mid word syllablse var CLOSED = ['<CO><VO><CO>','<CO><VO><CO><CO>']; CLOSED.probabilities = [75,25]; CLOSED.name = "CLOSED"; var OPEN = ['<CO><VO>','<CO><CO><VO>']; OPEN.probabilities = [60,40]; OPEN.name = "OPEN"; var VR = ['<VO>r']; //vowel-r VR.probabilities = [100]; VR.name = "VR"; var MID = ['<CLOSED>','<OPEN>','<VR>']; MID.probabilities = [33,33,33]; MID.name = "MID"; //the following will deal with ending syllables var VCE = ['<VO><CO>e','<LETTER><VO><CO>e']; VCE.probabilities = [75,25]; VCE.name = "VCE"; var CLE = ['<CO>le']; CLE.probabilities = [100]; CLE.name = "CLE"; var OE = ['tion','age','ive']; //other endings OE.probabilities = [33,33,33]; OE.name = "OE"; var ES = ['<VCE>','<CLE>','<OE>','<VR>']; //contains all ending syllables ES.probabilities = [40,40,20]; ES.name = "ES"; var rules = [CO,VO,BH,BL,COP,LETTER,SYL,CLOSED,OPEN,VR,MID,VCE,CLE,OE,ES]; //These are some highly-defined production rules var streetSuffix = ['road','street','way','avenue','drive','grove','lane','gardens','place','crescent','close','square','hill','circus','mews','vale','rise','mead']; streetSuffix.probabilities = [15,15,5,10,5,2.7,2.7,2.7,2.7,2.7,2.7,2.7,2.7,2.7,2.7,2.7,2.7,2.7]; var states = ['Alabama','Alaska','American Samoa','Arizona','Arkansas','California','Colorado','Connecticut','Delaware','Florida','Georgia','Guam','Hawaii','Idaho','Illinois','Indiana','Iowa','Kansas','Kentucky','Louisiana','Maine','Marshall Islands','Maryland','Massachusetts','Michigan','Minnesota','Mississippi','Missouri','Montana','Nebraska','Nevada','New Hampshire','New Jersey','New Mexico','New York','North Carolina','North Dakota','Ohio','Oklahoma','Oregon','Palau','Pennsylvania','Puerto Rico','Rhode Island','South Carolina','South Dakota','Tennessee','Texas','Utah','Vermont','Virgin Island','Virginia','Washington','West Virginia','Wisconsin','Wyoming']; var cityNewWordSuffix = ['city','town','']; var cityEndWordSuffix = ['polis','ville','ford','furt','forth','shire','berg','gurg','borough','brough','field','kirk','bury','stadt','']; var siteSuffix = ['com','org','net','edu']; /** This will generate a random name of Length length */ function generateRandomName() { //string will be random length of CO VO pattern for now var result; result = "<COP><VO><MID><VO><ES>"; while (hasNonTerminal(result)) { result = replaceFirstNonTerminal(result); } return result; } Here are a few words generated by the machine in its current state: "cheiroene", "sloeraase", "sledehgeute", "rhaorenone", "rheerisute", "chaereehe", "sletraoege", "sluureese", "chaheyleete", "chierauhe", "ploclooate", "glawofhaice", "thanisgoage", "slelaodose", "blaereode", "shihudeife", "slaereene", "pleheaele", "rhepicsaile", "ploeruoge", "sliareuhe", "thaereafe", "thaaraeke", "cheoreate", "shofetniote", "phiraoese", "clilniueye", "slepceikede", "cligloueohe", "phitleoime",
SUM, AVG, in Pig are not working
I am analyzing Cluster user log files with the following code in pig: t_data = load 'log_flies/*' using PigStorage(','); A = foreach t_data generate $0 as (jobid:int), $1 as (indexid:int), $2 as (clusterid:int), $6 as (user:chararray), $7 as (stat:chararray), $13 as (queue:chararray), $32 as (projectName:chararray), $52 as (cpu_used:float), $55 as (efficiency:float), $59 as (numThreads:int), $61 as (numNodes:int), $62 as (numCPU:int),$72 as (comTime:int), $73 as (penTime:int), $75 as (runTime:int), $52/($62*$75) as (allEff: float), SUBSTRING($68, 0, 11) as (endTime: chararray); ---describe A; A = foreach A generate jobid, indexid, clusterid, user, cpu_used, numThreads, runTime, allEff, endTime; B = group A by user; f_data = foreach B { grp = group; count = COUNT(A); avg = AVG(A.cpu_used); generate FLATTEN(grp), count, avg; }; f_data = limit f_data 10; dump f_data; Code works for group and COUNT but when I includes AVG and SUM, it shows the errors: ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1066: Unable to open iterator for alias f_data I checked data types. All are fine. Do you have any suggestions where I missed it?. Thank you in advance for your help.
Its an syntax error. Read http://chimera.labs.oreilly.com/books/1234000001811/ch06.html#more_on_foreach (section : Nested foreach) for details. Pig Script A = LOAD 'a.csv' USING PigStorage(',') AS (user:chararray, cpu_used:float); B = GROUP A BY user; C = FOREACH B { cpu_used_bag = A.cpu_used; GENERATE group AS user, AVG(cpu_used_bag) AS avg_cpu_used, SUM(cpu_used_bag) AS total_cpu_used; }; Input : a.csv a,3 a,4 b,5 Output : (a,3.5,7.0) (b,5.0,5.0)
Your pig is full of errors do not use same Alias at both side of = ; using PigLoader() as (mention your schema appropriately ); A = foreach A generate jobid, indexid, clusterid, user, cpu_used, numThreads, runTime, allEff, endTime; CHANGE THIS TO F = foreach A generate jobid, indexid, clusterid, user, cpu_used, numThreads, runTime, allEff, endTime; f_data = limit f_data 10; CHANGE left F_data with someother name . Stop making your life complex. General rule of debugging Pigscript run in local mode dump after everyline Wrote a sample pig to mimic ur pig :(working) t_data = load './file' using PigStorage(',') as (jobid:int,cpu_used:float); C = foreach t_data generate jobid, cpu_used ; B = group C by jobid ; f_data = foreach B { count = COUNT(C); sum = SUM(C.cpu_used); avg = AVG(C.cpu_used); generate FLATTEN(group), count,sum,avg; }; never_f_data = limit f_data 10; dump never_f_data;
jdbcTemplate.queryForList returns list of Map where all column values are NULL
Any calls using jdbcTemplate.queryForList returns a list of Maps which have NULL values for all columns. The columns should've had string values. I do get the correct number of rows when compared to the result I get when I run the same query in a native SQL client. I am using the JDBC ODBC bridge and the database is MS SQL server 2008. I have the following code in my DAO: public List internalCodeDescriptions(String listID) { List rows = jdbcTemplate.queryForList("select CODE, DESCRIPTION from CODE_DESCRIPTIONS where LIST_ID=? order by sort_order asc", new Object[] {listID}); //debugcode start try { Connection conn1 = jdbcTemplate.getDataSource().getConnection(); Statement stat = conn1.createStatement(); boolean sok = stat.execute("select code, description from code_descriptions where list_id='TRIGGER' order by sort_order asc"); if(sok) { ResultSet rs = stat.getResultSet(); ResultSetMetaData rsmd = rs.getMetaData(); String columnname1=rsmd.getColumnName(1); String columnname2=rsmd.getColumnName(2); int type1 = rsmd.getColumnType(1); int type2 = rsmd.getColumnType(2); String tn1 = rsmd.getColumnTypeName(1); String tn2 = rsmd.getColumnTypeName(2); log.debug("Testquery gave resultset with:"); log.debug("Column 1 -name:" + columnname1 + " -typeID:"+type1 + " -typeName:"+tn1); log.debug("Column 2 -name:" + columnname2 + " -typeID:"+type2 + " -typeName:"+tn2); int i=1; while(rs.next()) { String cd=rs.getString(1); String desc=rs.getString(2); log.debug("Row #"+i+": CODE='"+cd+"' DESCRIPTION='"+desc+"'"); i++; } } else { log.debug("Query execution returned false"); } } catch(SQLException se) { log.debug("Something went haywire in the debug code:" + se.toString()); } log.debug("Original jdbcTemplate list result gave:"); Iterator<Map<String, Object>> it1= rows.iterator(); while(it1.hasNext()) { Map mm = (Map)it1.next(); log.debug("Map:"+mm); String code=(String)mm.get("CODE"); String desc=(String)mm.get("description"); log.debug("CODE:"+code+" : "+desc); } //debugcode end return rows; } As you can see I've added some debugging code to list the results from the queryForList and I also obtain the connection from the jdbcTemplate object and uses that to sent the same query using the basic jdbc methods (listID='TRIGGER'). What is puzzling me is that the log outputs something like this: Testquery gave resultset with: Column 1 -name:code -typeID:-9 -typeName:nvarchar Column 2 -name:decription -typeID:-9 -typeName:nvarchar Row #1: CODE='C1' DESCRIPTION='BlodoverxF8rin eller bruk av blodprodukter' Row #2: CODE='C2' DESCRIPTION='Kodetilfelle, hjertestans/respirasjonstans' Row #3: CODE='C3' DESCRIPTION='Akutt dialyse' ... Row #58: CODE='S14' DESCRIPTION='Forekomst av hvilken som helst komplikasjon' ... Original jdbcTemplate list result gave: Map:(CODE=null, DESCRIPTION=null) CODE:null : null Map:(CODE=null, DESCRIPTION=null) CODE:null : null ... 58 repetitions total. Why does the result from the queryForList method return NULL in all columns for every row? How can I get the result I want using jdbcTemplate.queryForList? The xF8 should be the letter ΓΈ so I have some encoding issues, but I can't see how that may cause all values - also strings not containing any strange letters (se row#2) - to turn into NULL values in the list of maps returned from the jdbcTemplate.queryForList method. The same code ran fine on another server against a MySQL Server 5.5 database using the jdbc driver for MySQL.
The issue was resolved by using the MS SQL Server jdbc driver rather than using the JDBC ODBC bridge. I don't know why it didn't work with the bridge though.
SharePoint 2013 - Sorting Search Results not working (KeywordQuery-SortList)
am using KeywordQuery to search and.. the SortList does not affect result, it is always return first 5 results. Any suggestion? The code is bellow... using (KeywordQuery query = new KeywordQuery(site)) { var fedManager = new FederationManager(application); var owner = new SearchObjectOwner(SearchObjectLevel.SPSite, site.RootWeb); query.SourceId = fedManager.GetSourceByName("NewsRS", owner).Id; query.QueryText = string.Format("WorkflowStatusOWSCHCS:Approved PublishedUntilDate>=\"{0}\" OR NewsNewsPublishedDate<=\"{0}\"", DateTime.Now); query.KeywordInclusion = KeywordInclusion.AllKeywords; query.RowLimit = 5; query.StartRow = 1; query.SelectProperties.Add("NewsFriendlyUrl"); query.SelectProperties.Add("NewsNewsTeaser"); query.SelectProperties.Add("NewsNewsDate"); query.SelectProperties.Add("NewsPublishedUntilDate"); query.SelectProperties.Add("NewsNewsContent"); query.SelectProperties.Add("NewsNewsPublishedDate"); query.SelectProperties.Add("NewsNewsImage"); query.SortList.Add("NewsNewsDate", SortDirection.Descending); var searchExecutor = new SearchExecutor(); var myResults = searchExecutor.ExecuteQuery(query); } } ... the NewsNewsDate is marked as Sortable
query.RowLimit = 5; => You are explicitly specifying the Rowlimit to be 5. That is why it returns the first 5 results always. Change the rowlimit and set it to the number of results you need.
Use linq to query blocks of text?
I have a text file that contains some data in a "block" format: source : source location filename : somefile.txt vendor : somevendor version : xx.xx.xxx source : source location2 filename : somefile2.txt vendor : somevendor2 version : yy.yy.yyy can I use Linq to query this data and if so how would you go about it? I have used linq to query lines of data from text file many times, but never a "block" of data as above. Thanks for the input.
Yes, you can use LINQ, this approach is not optimized much if you have large file. Below is how to get data: var lines = File.ReadLines("C:\\text.txt") .Where(line => !string.IsNullOrWhiteSpace(line)) .ToList(); for (int i = 0; i < lines.Count; i += 4) { var location = lines[i].Split(':')[1]; var fileName = lines[i + 1].Split(':')[1]; var vendor = lines[i + 2].Split(':')[1]; var version = lines[i + 3].Split(':')[1]; } Version to use LINQ: var result = Enumerable.Range(0, lines.Count()/4).Select(i => new { location = lines[4*i].Split(':')[1]; fileName = lines[4*i + 1].Split(':')[1]; vendor = lines[4*i + 2].Split(':')[1]; version = lines[4*i + 3].Split(':')[1]; });